lln_clt#
Series: lecture-python.myst
File:
lectures/lln_clt.mdAudit date: 2026-08-26
Corpus snapshot:
e25fdf2345Categories audited: writing, math, code, figures, references, links, admonitions (JAX out of scope)
Overall score: 7.1 / 10
Priority: HIGH
Score breakdown#
Category |
Score |
One-line note |
|---|---|---|
Writing |
3.5/10 |
|
Math |
3/10 |
|
Code |
6.5/10 |
|
JAX |
out of scope |
JAX rules target |
Figures |
7/10 |
|
References |
10/10 |
no mechanical violations detected. |
Links |
10/10 |
no mechanical violations detected. |
Admonitions |
10/10 |
no mechanical violations detected. |
Issues#
Critical#
None found.
High severity#
[qe-code-001] (reviewer) — Follow PEP8 unless closer to mathematical notation. Count: 5. Lines: 59, 263, 480, 891, 911. Example: 480 writes
plt.figure(figsize = (10, 6))with spaces around a keyword-argument=, which PEP8 forbids and which the other sevenfigsize=calls in the file get right (239, 332, 405, 696, 915).Axes3Dis imported at 59 and never used - the 3-D axes are created byadd_subplot(projection='3d')at 480. The import block at 54-61 puts the standard-libraryrandom(55) between two third-party imports instead of in its own group.list(range(n))is materialised four times in the same loop body at 263, 265, 267 and 268 whererange(n)or a singlenp.arange(n)bound once outside the loop would do. 891-892 binds\u03a3to a tuple of tuples and then rebinds the same name tonp.array(\u03a3), so the name means two types two lines apart. And 911-912 calls the normalized matrixtemp, which says nothing about the object the next line squares and sums.[qe-fig-001] — Do not set figure size unless necessary. Count: 6. Lines: 239, 332, 405, 480, 696, 915. Example: figsize=.
[qe-fig-005] — Descriptive figure names for cross-referencing. Count: 6. Lines: 226, 331, 390, 444, 675, 883. Example: code-cell figure without mystnb figure metadata.
[qe-math-002] — Use \top for transpose notation. Count: 5. Lines: 572, 750, 765, 870, 871. Example: apostrophe transpose
)'.[qe-math-004] — Do not use bold face for matrices or vectors. Count: 121. Lines: 529, 531, 533, 536, 537, 538, 541, 545, 548, 564, …. Example: \mathbf.
[qe-math-010 (proposed)] — Blackboard \mathbb{P}, \mathbb{E}, \mathbb{V} with braces. Count: 42. Lines: 95, 104, 109, 134, 140, 154, 155, 162, 163, 167, …. Example: missing braces:
\mathbb E.[qe-writing-003] (reviewer) — Maintain logical flow. Count: 5. Lines: 42, 394, 416, 459, 510. Example: five breaks, two of them substantive. (a) 42 promises “We also demonstrate how the LLN and CLT break down when the assumptions they are based on do not hold” - and no such demonstration exists. There is no Cauchy, no infinite-variance, no heavy-tailed and no dependent example anywhere in the 927 lines; the headings run Overview, Relationships, LLN (Classical LLN / Proof / Illustration), CLT (Statement / Intuition / Simulation 1 / Simulation 2 / Multivariate Case), Exercises. The nearest thing is 708-714, where the delta method’s own hypothesis \(g'(\mu) \neq 0\) fails - not the LLN or the CLT. (b) 436-437 says the underlying variable is “the convex combination of three different beta densities” and the docstring at 458 says “j is a random draw from {0, 1, 2}”, but 459 writes
js = rng.integers(0, 2, size=k), whose upper bound is exclusive - only components 0 and 1 are ever drawn, so the third shift at 457 (bdraws[2, :] -= 1.1) never enters and the figure at 480-504 shows a two-component mixture. © 416 tells the reader to “Notice the absence of for loops — every operation is vectorized, meaning that the major calculations are all shifted to highly optimized C code”, and then the lecture’s own final solution at 899-908 fillserror_obswith a 50,000-iteration Python loop that vectorizes in three lines exactly as Simulation 1 does. (d) 384-385 declares the exponential as \(F(x) = 1 - e^{-\lambda x}\) and the comment at 394 says “Exponential distribution, \u03bb = 1/2”, butexpon(2)setsloc=2, scale=1- a unit-rate exponential shifted right by 2, with mean 3, not rate 1/2; 235 has the same error, labellingexpon(1)as “exponential with \u03bb = 1” when its mean is 2. (The CLT demo survives it because the shift cancels in \(\bar X_n - \mu\), which is why it has gone unnoticed.) (e) 510 says “We leave you to investigate its contents if you wish to know more” with no antecedent for “its”, and 512-514 tells the reader to “run the file from the ordinary IPython shell” so the 3-D figure “should pop up in a window that you can rotate with your mouse” - a workflow this book does not have. Also 476’s comment says “Multiply j-th column by sqrt j” where 477 divides.[qe-writing-006] — Capitalize lecture titles properly. Count: 3. Lines: 82, 283, 517. Example: H3 Title Case: ‘The Classical LLN’ (Classical).
Medium severity#
[qe-code-002] — Use Unicode symbols for Greek letters in code. Count: 2. Lines: 462, 463. Example: spelled-out
sigma.[qe-math-003] — Use square brackets for matrix notation. Count: 4. Lines: 550, 558, 580, 809. Example: array used as matrix.
[qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 3. Lines: 296, 570, 592. Example: \(k\) carries two meanings in the same passage: 529 fixes it as the dimension of \(\mathbf X\) and 800 reminds the reader of that, but 592 calls a generic entry of the covariance matrix “the \(j,k\)-th term” when 581-587 has just used \(k\) for the last row and column - so “the \(j,k\)-th term” reads as the last column rather than a generic one, and \(i,j\) was available. The code then takes \(k\) for a third job, the number of draws, at 393. The convergence arrow is spelled two ways in the same lecture -
\stackrel { d } {\to}with spaces inside both groups at 296, 301, 625, 647 and 737, and the tighter\stackrel{d}{\to}at 753, 757, 775, 783, 793, 840, 858 and 876 - and the second is both simpler and the majority spelling. And the variance operator is written\mathop{\mathrm{Var}}at 570, 578, 749 and 750 but plain\mathrm{Var}at 869 and 870; whichever letter is chosen, the\mathop{}wrapper adds nothing that\mathrm{}does not already do.[qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 4. Lines: 145, 196, 218, 274. Example: 145 is a 41-word parenthetical carrying two long link labels and no closing period (“(This version is weaker because we claim only convergence in probability rather than almost sure convergence, and assume a finite second moment)”); the same missing-period pattern recurs at 361, 387, 439, 541, 654 and 800. 196-198 opens on a double negative and needs 33 words to say that the covariances must mostly be near zero. 218 carries a stale instruction to the reader - “(as usual, you can click on it to expand it)” - that does not describe this book’s figures. And 224 with 274 makes a claim the figure cannot support: 251 picks three of six distributions with
random.choiceand no seed, so the published panel changes on every build, yet 224 asserts “In each of the three cases, convergence of \(\bar X_n\) to \(\mu\) occurs as predicted” and 274 then explains that the three were chosen at random - the reader is told to verify something that is different each time.[qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 3. Lines: 308, 310, 742. Example: there are only four bold spans in the file and the split is even: 87 (Kolmogorov’s strong law) and 567 (variance-covariance matrix) are definitions and correctly bold, while 308 (any), 310 (always) and 742 (standard) are emphasis and should be italic - “for any distribution with finite second moment … always leads to a Gaussian curve”. There is not one italic span anywhere in the lecture, so bold is the only emphasis device available to it.
[qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 3. Lines: 42, 190, 200. Example: three places where a figure is the natural carrier and the lecture uses prose. The breakdown case promised at 42 is the clearest: the machinery at 226-272 already plots \(\bar X_n\) against \(n\) for three distributions, and adding a fourth panel with a Cauchy sample would show non-convergence next to convergence in the same axes - which is what the sentence at 42 promises and never delivers. Second, the proof produces a concrete bound, \(\mathbb P\{|\bar X_n - \mu| \geq \epsilon\} \leq \sigma^2/(n\epsilon^2)\) at 184-189, and never plots it against the simulated tail frequency, although Simulation 1 (390-413) already generates 100,000 draws of \(\bar X_n\) and could overlay the two curves in three lines. Third, 200-206 introduces “asymptotic independence” - covariance \(\mathbb E(X_i-\mu)(X_j-\mu)\) falling to zero as \(|i-j|\) grows - calls it “very important in time series analysis”, and illustrates it with nothing at all; it is the one idea in the lecture with no accompanying picture, code or example.
Low severity#
[qe-writing-008] — Remove excessive whitespace between words. Count: 1. Lines: 825. Example: 2 spaces.
Strengths#
The proposed
qe-math-014(proposed) convention holds without exception: every one of the eight probability statements applies \(\mathbb P\) to an event written in braces -\mathbb P \left\{ \bar X_n \to \mu \ldots \right\}(109, 615),\mathbb P \left\{ |\bar X_n - \mu| \geq \epsilon \right\}(140, 154, 187),\mathbb P\{X_i = 0\}(324),\mathbb P\{\mathbf X_1 \leq \mathbf x_1, \ldots\}(536-538) - and there is not one\mathbb P(\cdot)in the file.The proposed
qe-math-015(proposed) convention also holds: uppercase \(F\) is the distribution throughout (90, 379, 385, 658, with \(F(x) = 1 - e^{-\lambda x}\) at 385 and \(\int x F(dx)\) at 95), lowercase \(f\) is the mixture density of Simulation 2 (436, 437, 439), and the 3-D plot labels its vertical axis$p(y_n)$at 498.The weak law is proved instead of cited, in steps a reader can check: Chebyshev quoted with a link at 149-156, the variance of \(\bar X_n\) computed line by line at 160-173, the step that carries the whole argument named out loud at 175-180 (“Here the crucial step is at the third equality, which follows from independence”), and the conclusion assembled at 182-191 - and the version it does not prove is cited to a precise location, theorem 8.3.5 of
{cite}`Dudley2002`at 129.The CLT is motivated through the one example where the mechanism is visible rather than through its proof, which 315-317 candidly calls “elegant but almost anticlimactic”: binary \(X_i\) at 321-327, the PMF of \(Y_n\) for \(n = 1, 2, 4, 8\) plotted at 331-346, the counting argument spelled out at 353-356 (“there are more ways to get 1 success … than to get zero or two successes”), and the counterfactual at 361 that isolates exactly which assumption is doing the work.
The two simulations answer two different questions and the lecture says which: 377-382 sets out Simulation 1 as a four-step recipe (choose \(F\), draw \(Y_n\), histogram, compare to \(N(0,\sigma^2)\)), and 424-442 explains what Simulation 2 adds - the whole sequence of densities for \(n = 1, \ldots, 5\) rather than one - including why an irregular starting density was built from a convex combination (439).
The multivariate section builds its vocabulary before it needs it and in the right order: independence of random vectors at 533-541 (with the vector inequality defined at 541), the mean vector at 543-565, the variance-covariance matrix at 567-593, and only then the two theorems, each in two lines (612-628).
Exercise 2 is scaffolded into the three facts its proof needs, numbered and stated separately (746-768), and the solution then proves the claim algebraically at 836-877 before simulating it at 883-923 - so the same result arrives twice, once as \(\mathbf Q \Sigma \mathbf Q' = \mathbf I\) and once as a histogram against \(\chi^2(2)\).
All five admonition rules and both link rules measure zero: both exercises use gated
{exercise-start}/{exercise-end}markers, both solutions carry:class: dropdown(670, 833), the{hint}at 822-827 is a dropdown too, and the internal cross-references go through labels -{ref}stated above <statement_clt>at 639, `{ref}`above <sim_one>at 660,{ref}discussed above <multivariate_clt>`` at 728.
Recommended actions#
Deliver the demonstration promised at 42 or delete the sentence: one extra panel in the figure at 226-272 showing \(\bar X_n\) for a Cauchy sample would do it, and the lecture’s own machinery already draws the convergent cases.
Fix the mixture:
rng.integers(0, 2, size=k)at 459 must berng.integers(0, 3, size=k)for the third beta component shifted at 457 to appear at all, otherwise 436-437 and the docstring at 458 are both wrong about what is being plotted.Fix the exponential parameterisation -
expon(scale=2)at 394 andexpon(scale=1)at 235 - so the code matches \(F(x) = 1 - e^{-\lambda x}\) at 385 and the labels at 235 and 394.Replace the 121
\mathbf/\boldsymbolspans (107 and 14 respectively, all in 529-877) with plain letters perqe-math-004; this is by far the largest single item in the file and the whole reason the Math category scores 3.Add braces to the 42
\mathbb E/\mathbb Psites (\mathbb{E},\mathbb{P}), and decide on one spelling of the variance operator - the style guide asks for\mathbb{V}- replacing\mathop{\mathrm{Var}}at 570, 578, 749, 750 and\mathrm{Var}at 869, 870.Vectorize the 50,000-iteration loop at 899-908 the way Simulation 1 already does, so the file stops contradicting its own advice at 416; and seed the generators at 251, 468 and the
.rvscalls so that 224 and 274 describe a figure that does not change between builds.Delete 510-514, which refers to “its contents” with no antecedent and to running “the file from the ordinary IPython shell”.
Sweep the mechanical backlog: the three Title-Case H3s (82 “The Classical LLN”, 283 “Statement of the Theorem”, 517 “The Multivariate Case”),
mystnbcaption and name metadata for the six code-cell figures (226, 331, 390, 444, 675, 883), the sixfigsizeoverrides, the fourarraydisplays recast asbmatrix(550, 558, 580, 809),sigmato\u03c3at 462-463,lw=2at 263,figsize =at 480, and the unusedAxes3Dimport at 59.