Mathematical Foundations

IV.6 · Probability

How much should a flag change our belief?

Change a fictional quality model's prior and flag likelihoods. Watch both groups contribute evidence, then normalize their masses to obtain a posterior.

Evidence moves probability mass

Prior A= 0.01
Prior Aᶜ= 0.99
A and observed evidence= 0.009
Aᶜ and observed evidence= 0.0495
Posterior A= 2/13
Posterior Aᶜ= 11/13
Expected population of 10,000 · fractional counts are expectations
GroupCountMass
A and E900.009
A and Eᶜ100.001
Aᶜ and E4950.0495
Aᶜ and Eᶜ94050.9405

Fictional quality flag model. E is the positive flag. Expected counts in 10,000 items: A and E = 90; A and Eᶜ = 10; Aᶜ and E = 495; Aᶜ and Eᶜ = 9405. Observed positive evidence changes the mass of A from 0.01 to 2/13. The posterior masses sum to exactly one.

Prior
0.01
Evidence likelihood given A
0.9
Evidence likelihood given Aᶜ
0.05
False negative rate
0.1
Normalizing evidence
0.0585
Posterior
2/130.153846…

= exact model quantity · ≈ numerical companion or observed estimate

from 0 to 100, up to 2 decimal places

from 0 to 100, up to 2 decimal places

from 0 to 100, up to 2 decimal places

Observed positive evidence changes the mass of A from 0.01 to 2/13. The posterior masses sum to exactly one.
P(E)=P(E∣A)P(A)+P(E∣Ac)P(Ac)=0.0585P(E)=P(E\mid A)P(A)+P(E\mid A^c)P(A^c)=0.0585
P(A∣E)=P(E∣A)P(A)P(E)=0.0090.0585=213P(A\mid E)=\frac{P(E\mid A)P(A)}{P(E)}=\frac{0.009}{0.0585}=\frac{2}{13}

Before observing evidence

Prior mass of A is 0.01.

P(A)=0.01P(A)=0.01
Prior A= 0.01
Prior Aᶜ= 0.99

Change the defect prior and the two flag likelihoods. Switch observed evidence between flag and no flag, then compare retained mass, the population table, and the normalized posterior.

The example is a fictional item-quality flag, not a real diagnostic or medical recommendation. Before changing the prior, predict whether a flag rate of 90% among defective items implies that 90% of flagged items are defective.

Intuition: evidence comes from both groups

A flag can be produced by a defective item or a nondefective item. If defective items are rare, the large nondefective group can contribute more flags even when its own flag rate is small. Updating a belief requires comparing these two sources of evidence.

Begin with prior mass in each group. Multiply each by how likely that group is to produce the observed evidence. Their retained masses need not sum to one: their total is the probability of the evidence. Divide by that total to compare the groups among items that match the evidence.

Definition

Let A mean “the item is defective” and E mean “the item is flagged.” Write the prior p=P(A)p=P(A), the flag likelihood t=P(E∣A)t=P(E\mid A), and the other flag likelihood f=P(E∣Ac)f=P(E\mid A^c). All three parameters lie in [0,1][0,1].

The positive-evidence masses are ptpt and (1−p)f(1-p)f. The evidence probability is their sum, and Bayes’ theorem gives

P(E)=pt+(1−p)f,P(A∣E)=ptpt+(1−p)f,P(E)>0.P(E)=pt+(1-p)f,\qquad P(A\mid E)=\frac{pt}{pt+(1-p)f},\qquad P(E)>0.

The posterior is the class probability after observing E. The false-positive rate is ff and the false-negative rate is 1−t1-t, relative to this fictional class model. A likelihood conditions on the class; a posterior conditions on the evidence. They have different denominators.

Mechanics: prior, likelihood, retained mass, posterior

The stage’s canonical parameters specify one joint model. Its mass view, equations, inspector, population table, accessible interpretation, and trace follow that model and the selected evidence. Changing the prior changes group sizes; changing a likelihood changes the retained fraction within its group.

Use the evidence selector to switch to no flag. The likelihoods become 1−t1-t and 1−f1-f, and the retained total becomes P(Ec)P(E^c). Replay the trace to follow the same update with the new evidence. Normalized posterior masses sum to one whenever the selected evidence has positive probability.

Derivation: Bayes from the joint mass

The multiplication rule computes the same intersection in two ways:

P(A∩E)=P(A)P(E∣A)=P(E)P(A∣E).P(A\cap E)=P(A)P(E\mid A)=P(E)P(A\mid E).

The two classes A and AcA^c partition the sample space. Their evidence contributions therefore add to P(E)P(E), which supplies the denominator. For negative evidence,

P(A∣Ec)=p(1−t)p(1−t)+(1−p)(1−f),P(Ec)>0.P(A\mid E^c)=\frac{p(1-t)}{p(1-t)+(1-p)(1-f)}, \qquad P(E^c)>0.

The joint model conserves original total mass: pt+p(1−t)+(1−p)f+(1−p)(1−f)=1pt+p(1-t)+(1-p)f+(1-p)(1-f)=1. Restriction retains only the two evidence-compatible cells; normalization rescales them to total one. It does not change the original four cells.

Worked examples

Use prior p=1/100p=1/100, t=9/10t=9/10, and f=1/20f=1/20. In a notional population of N=10000N=10000 items, the expected counts are:

ClassFlag ENo flagTotal
Defective A9010100
Nondefective49594059900
Total585941510000

These counts scale model probabilities; they are not a simulated sample or a promise that an actual batch contains those numbers. Other parameter choices can produce fractional expected counts, which should remain fractional rather than be silently rounded to people or items.

P(E)=58510000=1172000,P(A∣E)=90585=213≈0.153846.P(E)=\frac{585}{10000}=\frac{117}{2000},\qquad P(A\mid E)=\frac{90}{585}=\frac2{13}\approx0.153846.

Worked example: Evidence moves probability mass

Prior A= 0.01
Prior Aᶜ= 0.99
A and observed evidence= 0.009
Aᶜ and observed evidence= 0.0495
Posterior A= 2/13
Posterior Aᶜ= 11/13
Expected population of 10,000 · fractional counts are expectations
GroupCountMass
A and E900.009
A and Eᶜ100.001
Aᶜ and E4950.0495
Aᶜ and Eᶜ94050.9405

Fictional quality flag model. E is the positive flag. Expected counts in 10,000 items: A and E = 90; A and Eᶜ = 10; Aᶜ and E = 495; Aᶜ and Eᶜ = 9405. Observed positive evidence changes the mass of A from 0.01 to 2/13. The posterior masses sum to exactly one.

Prior
0.01
Evidence likelihood given A
0.9
Evidence likelihood given Aᶜ
0.05
False negative rate
0.1
Normalizing evidence
0.0585
Posterior
2/130.153846…

= exact model quantity · ≈ numerical companion or observed estimate

from 0 to 100, up to 2 decimal places

from 0 to 100, up to 2 decimal places

from 0 to 100, up to 2 decimal places

Observed positive evidence changes the mass of A from 0.01 to 2/13. The posterior masses sum to exactly one.
P(E)=P(E∣A)P(A)+P(E∣Ac)P(Ac)=0.0585P(E)=P(E\mid A)P(A)+P(E\mid A^c)P(A^c)=0.0585
P(A∣E)=P(E∣A)P(A)P(E)=0.0090.0585=213P(A\mid E)=\frac{P(E\mid A)P(A)}{P(E)}=\frac{0.009}{0.0585}=\frac{2}{13}

Before observing evidence

Prior mass of A is 0.01.

P(A)=0.01P(A)=0.01
Prior A= 0.01
Prior Aᶜ= 0.99

Raise the prior from 1% to 10% while keeping flag likelihoods at 90% and 5%. Compare the posterior before and after, then restore the worked model and switch to no-flag evidence.

With no flag, the defective share is 10/(10+9405)=2/1883≈0.00106210/(10+9405)=2/1883\approx0.001062. It is not 1−2/131-2/13; that complement is the nondefective share among flagged items. Raising the prior to 1/101/10 with the same positive likelihoods changes the posterior to (9/100)/(9/100+9/200)=2/3(9/100)/(9/100+9/200)=2/3. Base rates matter even when the flag mechanism does not change.

Executable reference code

Python constructs the exact four-cell joint table and returns evidence mass plus a posterior, using None for impossible evidence. Assertions verify counts, both evidence directions, base-rate sensitivity, and boundary cases. NumPy uses the same independently specified parameters to construct a floating-point joint array and compares it against literal exact fractions. Neither program depends on the browser implementation or imports TypeScript outputs.

code/python/probability_bayes.py
"""Bayes' theorem for a fictional quality flag, not a real diagnostic tool.

All masses and expected counts are exact Fractions. Expected population counts
are a scaled model, not observations; arbitrary parameters can yield fractions.
"""
from fractions import Fraction as F


def joint_table(prior, true_flag, false_flag):
    if any(not isinstance(x, F) or not 0 <= x <= 1 for x in (prior, true_flag, false_flag)):
        raise ValueError("Prior and likelihoods must be Fractions in [0, 1]")
    return {"A,flag": prior * true_flag,
            "A,no flag": prior * (1 - true_flag),
            "not A,flag": (1 - prior) * false_flag,
            "not A,no flag": (1 - prior) * (1 - false_flag)}


def update(prior, true_flag, false_flag, positive=True):
    if type(positive) is not bool:
        raise ValueError("Select flag (True) or no flag (False) evidence")
    joint = joint_table(prior, true_flag, false_flag)
    suffix = "flag" if positive else "no flag"
    a_mass = joint["A," + suffix]
    not_a_mass = joint["not A," + suffix]
    evidence = a_mass + not_a_mass
    posterior = a_mass / evidence if evidence else None
    return evidence, posterior


def main():
    p, t, f = F(1, 100), F(9, 10), F(1, 20)
    joint = joint_table(p, t, f)
    assert sum(joint.values(), F(0)) == 1
    assert joint["A,flag"] + joint["A,no flag"] == p
    expected_counts = {cell: mass * 10000 for cell, mass in joint.items()}
    assert expected_counts == {"A,flag": F(90), "A,no flag": F(10),
                               "not A,flag": F(495), "not A,no flag": F(9405)}
    assert update(p, t, f) == (F(117, 2000), F(2, 13))
    assert update(p, t, f, False) == (F(1883, 2000), F(2, 1883))
    assert update(F(1, 10), t, f) == (F(27, 200), F(2, 3))
    assert update(p, F(1, 5), F(1, 5))[1] == p
    assert update(p, F(1, 5), F(1, 5), False)[1] == p
    assert update(p, t, F(0))[1] == 1
    assert update(p, F(0), F(0)) == (F(0), None)
    assert update(p, F(1), F(1), False) == (F(0), None)
    assert update(F(0), t, f)[1] == 0
    assert update(F(1), t, f)[1] == 1
    assert update(F(0), t, F(0))[1] is None
    tiny = F(1, 10 ** 100)
    assert update(p, tiny, tiny) == (tiny, p)
    assert joint_table(F(1, 3), F(1, 2), F(1, 4))["A,flag"] * 10 == F(5, 3)
    for params in ((F(-1), t, f), (p, F(2), f), (p, t, F(-1, 20)), (0.01, t, f)):
        try:
            update(*params)
        except ValueError:
            pass
        else:
            raise AssertionError("Invalid parameters were accepted")
    print("Fictional quality flag: prior 1%, P(flag|A) 90%, P(flag|not A) 5%")
    print("Exact expected counts for N = 10000:", expected_counts)
    print("Positive evidence (mass, posterior):", update(p, t, f))
    print("Negative evidence (mass, posterior):", update(p, t, f, False))
    print("Prior 10%, unchanged likelihoods:", update(F(1, 10), t, f))
    print("Impossible evidence:", update(p, F(0), F(0)), "; None means undefined")


if __name__ == "__main__":
    main()
code/python/probability_bayes_numpy.py
"""A fictional quality flag as a joint array: rows are classes, columns evidence.

Compare against literal exact fractions with absolute tolerance 1e-12, relative
tolerance 0. Expected counts scale the model; they are not simulated observations.
"""
from fractions import Fraction as F
import numpy as np

ATOL = 1e-12


def update(prior, true_flag, false_flag, positive=True):
    values = np.asarray([prior, true_flag, false_flag], dtype=float)
    if not np.all(np.isfinite(values)) or np.any(values < 0) or np.any(values > 1):
        raise ValueError("Prior and likelihoods must be finite and in [0, 1]")
    if type(positive) is not bool:
        raise ValueError("Select flag (True) or no flag (False) evidence")
    p, t, f = values
    priors = np.array([p, 1 - p])
    likelihoods = np.array([[t, 1 - t], [f, 1 - f]])
    # shortcut: direct float products can underflow, use scaling/log-space for tiny likelihoods.
    joint = priors[:, None] * likelihoods
    np.testing.assert_allclose(joint.sum(), 1.0, rtol=0, atol=ATOL)
    np.testing.assert_allclose(joint.sum(axis=1), priors, rtol=0, atol=ATOL)
    retained = joint[:, 0 if positive else 1]
    evidence = retained.sum()
    posterior = retained / evidence if evidence > 0 else None
    return joint, evidence, posterior


def main():
    p, t, f = 0.01, 0.90, 0.05
    joint, evidence, posterior = update(p, t, f)
    expected_counts = np.array([[90, 10], [495, 9405]])
    np.testing.assert_allclose(joint * 10000, expected_counts, rtol=0, atol=ATOL)
    np.testing.assert_allclose(evidence, float(F(117, 2000)), rtol=0, atol=ATOL)
    np.testing.assert_allclose(posterior, [float(F(2, 13)), float(F(11, 13))], rtol=0, atol=ATOL)
    np.testing.assert_allclose(posterior.sum(), 1.0, rtol=0, atol=ATOL)
    _, negative_mass, negative_posterior = update(p, t, f, False)
    np.testing.assert_allclose(negative_mass, float(F(1883, 2000)), rtol=0, atol=ATOL)
    np.testing.assert_allclose(negative_posterior[0], float(F(2, 1883)), rtol=0, atol=ATOL)
    np.testing.assert_allclose(update(0.1, t, f)[2][0], float(F(2, 3)), rtol=0, atol=ATOL)
    np.testing.assert_allclose(update(p, 0.2, 0.2)[2][0], p, rtol=0, atol=ATOL)
    np.testing.assert_allclose(update(p, 0.2, 0.2, False)[2][0], p, rtol=0, atol=ATOL)
    assert update(p, 0.0, 0.0)[2] is None
    assert update(p, 1.0, 1.0, False)[2] is None
    assert update(0.0, t, f)[2][0] == 0.0
    assert update(1.0, t, f)[2][0] == 1.0
    np.testing.assert_allclose(update(p, t, 0.0)[2], [1.0, 0.0], rtol=0, atol=ATOL)
    # A small positive evidence total is not invalid merely because it is below ATOL.
    np.testing.assert_allclose(update(p, 1e-100, 1e-100)[2][0], p, rtol=0, atol=ATOL)
    for params in ((-0.1, t, f), (p, 1.1, f), (p, t, -0.01), (np.nan, t, f), (p, np.inf, f)):
        try:
            update(*params)
        except ValueError:
            pass
        else:
            raise AssertionError("Invalid Bayes parameters were accepted")
    print("Fictional quality joint masses ≈\n", joint)
    print("Expected counts for N = 10000 ≈\n", joint * 10000)
    print("Positive evidence mass ≈", evidence, "(exact 117/2000)")
    print("Defective/nondefective posterior ≈", posterior, "(exact 2/13, 11/13)")
    print("No-flag defective posterior ≈", negative_posterior[0], "(exact 2/1883)")
    print("Zero represented evidence: undefined (None); underflow needs a separate policy")


if __name__ == "__main__":
    main()

Explore

Set both likelihoods equal and positive. Positive evidence then retains the same proportion of each class, leaving the posterior equal to the prior. If both are strictly less than one, the same is true after negative evidence. Next set the false-positive rate to zero with positive prior and positive true-flag likelihood: every possible flag comes from A, so its posterior is one.

Set both positive likelihoods to zero and choose flag evidence. The evidence is impossible and the posterior must be undefined. Set both to one and choose no flag for the parallel case. Try prior zero or one and identify when the selected evidence is still possible under the surviving class.

Common mistakes and counterexamples

Confusing P(E∣A)P(E\mid A) with P(A∣E)P(A\mid E) reverses the conditioning direction. Ignoring the nondefective evidence contribution commits the base-rate fallacy. Using the false-negative rate as the negative-evidence posterior also skips the denominator.

A flag is evidence under an assumed model, not certainty about an individual item or proof of a cause. The fictional rates are teaching parameters, not empirically calibrated quality guarantees. An observed count table would need its own sampling and estimation analysis before its rates could be treated as known.

Numerical considerations

Finite rational parameters give exact joint masses, expected counts, evidence totals, and posteriors. Decimal displays with ≈\approx are approximations of these exact quantities. The NumPy reference uses absolute tolerance 10−1210^{-12} and zero relative tolerance for these small specified examples, rather than asserting binary-decimal identity.

Very small but positive evidence remains mathematically valid; division may expose input uncertainty or floating-point underflow. A general numerical implementation may need scaling or log-space normalization, but must disclose that policy and preserve the distinction between impossible evidence and arithmetic loss. Adding epsilon to an impossible denominator changes the model and does not derive Bayes’ theorem.

Engineering and ML connections

Bayesian classification updates class priors with feature likelihoods. Changing deployment base rates can change posterior predictions even if the class-conditional likelihoods stay fixed. This is one reason a detection rate alone is insufficient to interpret flagged cases. Practical models must justify their likelihoods and priors; the algebra faithfully updates assumptions but cannot certify those assumptions.

Exercises

calculation

Build the fictional quality-flag table

A means a fictional item has a defect. Prior 1%, flag rate given A 90%, flag rate given not A 5%, N = 10000. Give expected counts: A and flag, A and no flag, not A and flag, not A and no flag.

calculation

Normalize positive evidence

For that quality model, compute P(flag) and P(A | flag). Prior 1%, P(flag | A) = 90%, P(flag | not A) = 5%.

calculation

Switch the observed evidence

For the same model, compute P(A | no flag). Enter an exact fraction.

prediction

Predict a base-rate change

Keep flag likelihoods 90% and 5%, but raise the defect prior from 1% to 10%. What happens after a flag?

Choose one answer

explanation

Handle evidence no group can produce

Both P(flag | A) and P(flag | not A) are zero. A flag is supplied as evidence. What should the update report?

Choose one answer

Summary and checkpoints

Multiply each prior group by its evidence likelihood, add the retained masses, then normalize. Check that you can explain the 90 versus 495 flagged counts, derive the exact posterior 2/132/13, update for negative evidence, predict a base-rate change, and leave impossible evidence undefined.

The map of the book

97 of 97 chapters written · eight Parts

demo Foundation demo Try the live vector example Open as a page

Part I

Mathematical Language

The notation and mental objects everything else uses.

9 of 9 chapters written

  1. I.1 Scalars, quantities, units, powers and roots available
  2. I.2 Coordinates and points available
  3. I.3 Vectors: components, magnitude, and direction reference chapter available
  4. I.4 Algebraic expressions, equations and inequalities available
  5. I.5 Functions as input → transformation → output available
  6. I.6 Essential function families available
  7. I.7 Sets, intervals, and relations available
  8. I.8 Indexed quantities and summation available
  9. I.9 The notation map for ML available

Part II

Linear Algebra

Matrices as transformations: the strongest foundation in the book.

19 of 19 chapters written

  1. II.1 Vector addition and subtraction available
  2. II.2 Scalar multiplication and vector scaling available
  3. II.3 Norms, magnitude, and normalization available
  4. II.4 Dot product, angle, and orthogonality available
  5. II.5 Projection and distance to a direction available
  6. II.6 Linear combinations and span available
  7. II.7 Linear independence, basis, and coordinates available
  8. II.8 Matrices as linear transformations available
  9. II.9 Matrix × vector available
  10. II.10 Matrix × matrix as composition available
  11. II.11 Transpose and orthogonality available
  12. II.12 Determinant: orientation and area/volume scaling available
  13. II.13 Linear systems as intersecting constraints available
  14. II.14 Gaussian elimination and row operations available
  15. II.15 Rank and invertibility available
  16. II.16 Inverse matrices available
  17. II.17 Eigenvalues and eigenvectors available
  18. II.18 Orthogonal bases and least-squares geometry available
  19. II.19 Singular Value Decomposition available

Part III

Calculus

Change, local approximation, and sensitivity made visible.

15 of 15 chapters written

  1. III.1 Limits through approach available
  2. III.2 Continuity and local behavior available
  3. III.3 Derivative as secant → tangent available
  4. III.4 Derivative as rate of change and local linear model available
  5. III.5 Derivative rules available
  6. III.6 Chain rule available
  7. III.7 Multivariable functions and partial derivatives available
  8. III.8 Gradient and directional derivatives available
  9. III.9 Jacobian available
  10. III.10 Computational graphs and automatic differentiation available
  11. III.11 Hessian and curvature available
  12. III.12 Integrals as accumulation available
  13. III.13 Fundamental derivative/integral connection available
  14. III.14 Numerical differentiation available
  15. III.15 Numerical integration available

Part IV

Probability

Uncertainty through sample spaces, evidence, and repetition.

16 of 16 chapters written

  1. IV.1 Random experiments, outcomes, and sample spaces available
  2. IV.2 Events and probability mass available
  3. IV.3 Counting and finite probability where needed available
  4. IV.4 Conditional probability as restricted sample space available
  5. IV.5 Independence available
  6. IV.6 Bayes' theorem as probability-mass update available
  7. IV.7 Random variables available
  8. IV.8 PMF, PDF, and CDF available
  9. IV.9 Bernoulli and Binomial distributions available
  10. IV.10 Uniform and Gaussian distributions available
  11. IV.11 Expectation available
  12. IV.12 Variance and standard deviation available
  13. IV.13 Joint, marginal, and conditional distributions available
  14. IV.14 Covariance and correlation available
  15. IV.15 Law of Large Numbers available
  16. IV.16 Central Limit Theorem available

Part V

Statistics

From observed data to estimates, intervals, and likelihood.

10 of 10 chapters written

  1. V.1 Data summaries: mean, median, mode available
  2. V.2 Spread: variance, standard deviation, robust interpretation available
  3. V.3 Population, sample, and sampling variability available
  4. V.4 Estimators and estimation available
  5. V.5 Confidence intervals through repeated sampling available
  6. V.6 Covariance matrices and multivariate spread available
  7. V.7 Regression fundamentals available
  8. V.8 Likelihood available
  9. V.9 Maximum Likelihood Estimation available
  10. V.10 Maximum A Posteriori estimation available

Part VI

Optimization

Learning as repeated parameter updates governed by an objective.

10 of 10 chapters written

  1. VI.1 Objective functions and optimization landscapes available
  2. VI.2 Local vs global optima and stationary points available
  3. VI.3 Convexity available
  4. VI.4 Gradient descent flagship chapter available
  5. VI.5 Learning rate and convergence behavior available
  6. VI.6 Momentum available
  7. VI.7 Stochastic and mini-batch gradient descent available
  8. VI.8 Adam intuition available
  9. VI.9 Constraints and projected/penalized intuition available
  10. VI.10 Numerical stopping and optimization diagnostics available

Part VII

Information Theory

Logarithms, entropy, and the loss behind token prediction.

8 of 8 chapters written

  1. VII.1 Logarithms and log probabilities in computation available
  2. VII.2 Self-information available
  3. VII.3 Entropy available
  4. VII.4 Cross entropy and negative log-likelihood available
  5. VII.5 KL divergence available
  6. VII.6 Logits and softmax available
  7. VII.7 Numerical stability: log-sum-exp and stable softmax available
  8. VII.8 From token logits to language-model loss available

Part VIII

Numerical Computing

Why equivalent expressions behave differently on real machines.

10 of 10 chapters written

  1. VIII.1 Floating-point representation available
  2. VIII.2 Rounding and representation error available
  3. VIII.3 Error propagation and conditioning available
  4. VIII.4 Catastrophic cancellation available
  5. VIII.5 Overflow and underflow available
  6. VIII.6 Stable algorithms available
  7. VIII.7 Numerical linear algebra realities available
  8. VIII.8 Sparse matrices and sparse structure available
  9. VIII.9 Vectorized computation available
  10. VIII.10 Reproducibility, random seeds, and nondeterminism available