multivariate_normal#
Series: lecture-python.myst
File:
lectures/multivariate_normal.mdAudit date: 2026-08-26
Corpus snapshot:
e25fdf2345Categories audited: writing, math, code, figures, links, admonitions (JAX out of scope)
Overall score: 6.5 / 10
Priority: HIGH
Score breakdown#
Category |
Score |
One-line note |
|---|---|---|
Writing |
3/10 |
|
Math |
3/10 |
|
Code |
7.5/10 |
|
JAX |
out of scope |
JAX rules target |
Figures |
5.5/10 |
|
References |
N/A |
no citations in this lecture. |
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: 8. Lines: 111, 292, 346, 369, 393, 1301, 2714, 2811. Example: exponentiation is written with spaces around the operator at 111, 114, 1220, 1222, 1225, 1564, 1624, 2079, 2780 and 2792 (
np.linalg.det(Σ) ** (-1/2),σu ** 2,a ** np.arange(...)) - the rule namesa**bexplicitly - while 2496 writesρ**2correctly, so the file is inconsistent with itself. 346, 347, 353 and 354 put a space between the name and the call,print ("a1 = ", a1)(E211), where 406-416 write the same calls correctly. Eight inline comments have a single space before the#instead of two (292, 436, 449, 476, 524, 720, 1065, 1328). E231 misses after commas at 296 (multi_normal.βs[0],multi_normal.βs[1]), 369 (np.linspace(-4,4,100)), 384 (figsize=(12,12)) and 2445 (Σ11_hat[0,0]); 285 puts a space before one,[.5 ,1.](E203); 393-396 put spaces around keyword=(loc = 'top',label = "$z_1$ on $z_2$", E251) and 378 has a double space before=. 1301 isprint(" E [ X | Y] = ", )- a trailing comma with no argument, printing a label followed by nothing. 2714, 2716-2717, 2785-2786 and 2802 align=and]with runs of spaces (Σt = Σ_hat_seq[t],[[Σt, Σt @ G_ex.T ],, E221/E202); 2811-2816 and 2621-2626 indent continuations to a flat 8 spaces rather than under the opening bracket (E128) and leave trailing whitespace on 2621, 2623, 2625, 2811, 2813 and 2815; and 1099 and 2454 run past 79 characters. Finally 1525-1527, 1545-1557 and 1568 spell alpha with U+1D6FC MATHEMATICAL ITALIC SMALL ALPHA (𝛼0,𝛼1,𝛼2) and 2187-2196 and 2287 spell lambda with U+1D706 (𝜆_tilde), while 2783-2788 in the same file uses ordinary U+03BB (λ_fa) - two visually near-identical characters for one Greek letter, surviving only because Python NFKC-normalises identifiers.[qe-fig-005] — Descriptive figure names for cross-referencing. Count: 8. Lines: 778, 1684, 2232, 2377, 2526, 2594, 2677, 2769. Example: code-cell figure without mystnb figure metadata.
[qe-fig-008] — Use lw=2 for line charts. Count: 15. Lines: 395, 396, 783, 784, 785, 1685, 1686, 1687, 1688, 2539, …. Example: plot() without lw=.
[qe-math-002] — Use \top for transpose notation. Count: 27. Lines: 1733, 1734, 1743, 1745, 1758, 1786, 1789, 1795, 1801, 1813, …. Example: apostrophe transpose
G'.[qe-math-003] — Use square brackets for matrix notation. Count: 38. Lines: 121, 130, 133, 274, 277, 539, 607, 620, 626, 632, …. Example: array used as matrix.
[qe-math-004] — Do not use bold face for matrices or vectors. Count: 5. Lines: 606, 650, 1504, 1505. Example: \boldsymbol.
[qe-math-010 (proposed)] — Blackboard \mathbb{P}, \mathbb{E}, \mathbb{V} with braces. Count: 31. Lines: 84, 896, 1308, 1351, 1485, 1661, 1758, 1786, 2121, 2266, …. Example: bare expectation
E\left[.[qe-math-011 (proposed)] — Distribution names in plain letters, not \mathcal / \mathbb. Count: 10. Lines: 1709, 1729, 1740, 1750, 1768, 1829, 1831, 1833, 1843. Example: decorated distribution
{\mathcal N}.[qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 5. Lines: 346, 920, 1695, 1834, 2157. Example: the file prints the same two numbers twice: 340-347 says “Let’s print out the intercepts and slopes” and prints
a1,b1, then 403-407 says “The intercept and slope of the red line are” and printsa1,b1again, unchanged. Four sentences run past 50 words with no gain: 920-925 (“To confirm that these formulas give the same answers that we computed earlier, we can compare the means and variances of \(\theta\) conditional on \(\{y_i\}_{i=1}^k\) with what we obtained above using the formulas implemented in the classMultivariateNormalbuilt on our original representation of conditional distributions for multivariate normal distributions”, ~52 words ending in “multivariate normal distributions” inside a lecture titled Multivariate Normal Distribution); 1695-1700, ~65 words carrying two counterfactuals and a definition of rational expectations; 1829-1835, ~60 words defining two shock processes and their orthogonality in one breath; and 2157-2161, ~50 words with three nested relative clauses (“how well the first two principal components from a PCA can approximate the conditional expectations \(E f_i | Y\) for our two factors \(f_i\), \(i=1,2\) for the factor analytic model that we have assumed truly governs the data on \(Y\) we have generated”). 509-513 and 576-577 also say the same thing twice fifty lines apart.[qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 6. Lines: 141, 943, 1706, 1885, 2409, 2750. Example: bold is used for emphasis in at least five places: recursively (943), forward and backward (1885-1886), not (2750), and marginal/conditional at 141, 146 and 151, which restate terms already defined in bold at 52 - so the second occurrence is emphasis wearing the definition marker. Meanwhile observation equation (1706) is a definition set in italic, and 1895 italicises a class name, MultivariateNormal, that the rest of the file writes in backticks (51, 260, 923, 941, 1662). Separately, all six exercise titles are whole-line bold used as pseudo-headings inside the directive body - Verify conditional mean and variance by simulation (2409), Product of regression slopes equals squared correlation (2463), IQ inference: effect of the signal-to-noise ratio (2505), Prior vs. likelihood in IQ inference (2560), Kalman filter convergence (2647), PCA vs. factor analysis (2737) - where MyST takes a title as the directive argument,
{exercise} Kalman filter convergence.[qe-writing-008] — Remove excessive whitespace between words. Count: 7. Lines: 599, 701, 940, 1758, 1860, 1885, 1886. Example: 2 spaces.
Medium severity#
[qe-fig-001] — Do not set figure size unless necessary. Count: 2. Lines: 384, 2810. Example: figsize=.
[qe-fig-007] — Keep figure box and spines. Count: 2. Lines: 389, 390. Example: spine removal.
[qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 4. Lines: 80, 502, 820, 1443. Example: line 80 wraps eight single-height groups in
\left(...\right):f\left(z;\mu,\Sigma\right)=\left(2\pi\right)^{-\left(\frac{N}{2}\right)}\det\left(\Sigma\right)^{-\frac{1}{2}}\exp\left(-.5\left(z-\mu\right)^\top\Sigma^{-1}\left(z-\mu\right)\right), and the same reflex runs through 84, 156, 162, 171, 462, 468, 613, 830, 902, 1119-1121, 1198, 1431, 1437, 1477, 1485-1486 and 1641 - plain parentheses would read the same and take a third of the source. The same line mixes-.5with-\frac{1}{2}in one expression, and 820 writes the convergence rate as\frac{1}{n^{.5}}where \(1/\sqrt n\) is both shorter and standard. 502 puts a hat over an entire conditional expectation,$\hat{E z_1 | z_2}$, which typesets as one wide accent over four symbols; the object meant is the sample estimate of \(E[z_1 \mid z_2]\). 1443-1471 stacks\underset{\equiv A}{\underbrace{...}}around three separatearrayblocks in a single display, so one equation carries three labelled underbraces plus an eight-column and three six-row arrays.[qe-writing-001] — Use one sentence per paragraph. Count: 2. Lines: 2822, 2830. Example: 2 sentences in one paragraph.
[qe-writing-003] (reviewer) — Maintain logical flow. Count: 4. Lines: 434, 852, 1353, 1867. Example: 421-424 announces “the mean and variance of the distribution of \(z_2\) conditional on \(z_1=5\)”, and the cell that follows is headed
# compute the cond. dist. of z1(434) - the comment names the wrong variable, and the next cell at 447 carries the identical comment where it is correct, so a reader comparing the two cells cannot tell which way round the conditioning runs. Second, symbols are recycled without warning across sections: \(C\) is the Cholesky factor at 833-837, a diagonal matrix of \(c\)’s at 1169, a \(2\times2\) block of \(\alpha\)’s at 1506 and the shock loading at 1768; \(G\) is \(C^{-1}\) at 852 and the observation matrix at 1712; \(D\) is the \((n+1)\)-square loading at 655, a diagonal of \(d\)’s at 1169, the stacking matrix at 1633 and \(EUU^\top\) at 1994 - and the Python names follow suit, withCrebound at 523, 906, 1234, 1568 and 1930 andfbeing both the density function of 91 and the factor vector of 2104. Third, 1272, 1306 and 1349 are headed “Smoothing example”, “Filtering exercise” and “Prediction exercise” but contain no exercise, and 1353 then cites “exercise 2” by hand - a number that matches nothing, since the lecture’s actual labelled exercises aremv_normal_ex1-mv_normal_ex6at 2406-2761. Fourth, 1867 sends the reader to “a quantecon lecture on the basics of linear quadratic control theory” without naming or linking it, where 1979 and 2145 both use{doc}for exactly this.[qe-writing-004] — Avoid unnecessary capitalization in narrative text. Count: 1. Lines: 2145. Example: mid-sentence ‘Components’.
[qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 3. Lines: 937, 1299, 2395. Example: the three worked examples of the time-series section produce no picture. 1296-1304 is a smoothing calculation whose entire output is
print("X = ", x),print("Y = ", y), a label with nothing after it, and a printed tuple - while exercise 5 at 2667-2668 asks the reader to “plot the filtered state estimates together with the true \(x_t\) and the raw observations”, which is the figure this section itself needed; 1334-1346 and 1374-1386 likewise end on bare tuples. The “Cholesky factor magic” section (937-951) is three sentences and two bullets with neither code nor figure, arriving straight after two cells whose only output is the wordTrue, so the claim that the Cholesky factorisation computes the regression coefficients recursively is never shown - the \(c_i\) sequence of{eq}`mnv_1`, which 883-888 calls the “new information” in test \(i\), is computed at 913 and never plotted. And 2395-2401 prints \(\hat\Sigma_y\) as a raw \(10\times10\) array where the point is its distance from \(\Sigma_y\).[qe-writing-009 (proposed)] — Write “IID” — not “i.i.d.” or “iid”. Count: 3. Lines: 602, 1830, 1832. Example: i.i.d…
Low severity#
None found.
Strengths#
One 60-line class (184-252) carries the whole lecture:
MultivariateNormalwithpartitionandcond_distis instantiated for the bivariate case (288), the trivariate case (526), one-dimensional IQ (706), two-dimensional IQ (1063), smoothing (1286), filtering (1339), prediction (1379), the stock-price model (1678), the single-period and iterated Kalman problems (1912, 1962) and factor analysis (2109) - eleven applications, no second implementation.Every population formula is checked against a computed analogue rather than asserted: 475-506 regresses \(10^6\) simulated draws and compares \(\beta\), \(\hat\Sigma_1\) and \(\hat\mu_1\) term by term; 929 and 934 verify that the Cholesky recursion reproduces the partitioned-covariance answers to within 1e-10; 2120-2127 checks \(E[f \mid Y] = B Y\); 2136-2140 checks \(\Lambda I^{-1} f = \Lambda f\); 2199-2206 checks the orthogonality of \(P\) and the eigendecomposition.
The IQ figure at 778-794 draws the drawn value of \(\theta\) as a horizontal dashed line against the posterior mean and a \(\pm 1.96\hat\sigma_\theta\) band as the conditioning set grows from 1 to 50 scores, and 796-820 then reads the picture out in full - what the band contains, what the black line is, and the \(n^{-1/2}\) rate at which the band closes.
The two-factor IQ model at 972-1005 is constructed so that math tests are uninformative about \(\eta\) and language tests uninformative about \(\theta\), and 1092-1102 loops over the six conditioning sets and prints the conditional moments that demonstrate exactly that (1104-1105) - the identification claim is built into the design and then verified.
The
{note}at 2256-2281 is an honest correction rather than a decoration: it points out that both leading eigenvalues equal 5.25, that a repeated eigenvalue leaves the individual principal components unidentified, that comparing \(\epsilon_1, \epsilon_2\) component-by-component with \(E[f \mid Y]\) is therefore meaningless, and that what is pinned down is the two-dimensional subspace - which in this symmetric example is the column space of \(\Lambda\).2290-2375 does the work of getting the PCA/factor comparison into a common space: it defines \(\hat Y = P_{:,1:2}\epsilon_{1:2}\), names \(\Lambda E[f\mid Y]\) as the observation-space counterpart, gives the shrinkage factor \(5/(5+\sigma_u^2) \approx 0.952\) that separates them, and writes out \(\Lambda a\) explicitly (2338-2353) so the horizontal lines in the figure at 2377-2389 are recognisable as a picture of \(\Lambda E[f \mid Y=y]\).
1880-1889 names the duality between the forward Riccati recursion for the conditional covariance
{eq}at 1864 and the backward Riccati recursion for the LQ value matrix at 1875-1876, and states the difference in direction of time as the thing to notice - a connection a reader would not extract from either equation alone.The six exercises at 2406-2761 each isolate one comparative static and all have executable dropdown solutions: the signal-to-noise ratio (2505), prior against likelihood with the closed-form posterior mean supplied as a
{hint}(2560-2583), Kalman convergence to a steady state (2647), and the PCA-versus-factor-analysis comparison (2737) that answers the rhetorical “(Can you explain why?)” left at 2155.
Recommended actions#
Fix the mislabelled cell at 434: the comment reads
# compute the cond. dist. of z1above the cell that conditions on \(z_1=5\) to get \(z_2\), and the correct version of the same comment sits at 447.Recast the 38
\left[\begin{array}{c}...\end{array}\right]displays asbmatrix(qe-math-003) and drop the\left(...\right)wrappers on single-height groups while doing it - 80 alone has eight of them, and the file already writes\begin{bmatrix}correctly at 653, 1008, 2341 and 2414.Settle the
**spacing on the form the rule names,a**b: 111, 114, 1220, 1222, 1225, 1564, 1624, 2079, 2780 and 2792 writex ** 2, while 2496 already writesρ**2. In the same sweep fix the fourprint (calls at 346-354, the eight single-space inline comments, and the E231/E251/E221/E128 items listed above.Add
mystnb: figure: caption/namemetadata to the seven un-named figure cells (778, 1684, 2232, 2377, 2526, 2594, 2677, 2769) in the form the one captioned cell already uses at 362-368, and setlw=2on the 14plotcalls; the prose refers to figures as “the plot above” (796) and “In the above graph” (1695) because there is nothing to cross-reference.Replace the bare
Var\left(at 902 with\mathbb{V}- written as it stands it typesets as the product \(V\cdot a\cdot r\) - and convert the file’s bareEoperators (84, 318, 324, 462, 502, 843, 896, 1127-1129, 1175, 1190, 1308, 1351, 1485, 1661, 1697, 1758, 1786, 1994-2008, 2033, 2121, 2159, 2245, 2266-2375, 2750-2757, 2833) to\mathbb{E}; the file contains no\mathbbat all.Give the three worked examples of 1272-1387 the figures they need - the smoothing example in particular, whose whole output is four printed arrays where exercise 5 at 2667-2668 asks the reader to draw exactly the missing plot - and plot the \(c_i\) sequence computed at 913 so the “new information” claim of 883-888 is visible.
Rename the pseudo-exercise sections at 1306 and 1349, and replace the hand-written “As what we did in exercise 2” at 1353 with a real reference; name and
{doc}-link the LQ control lecture alluded to at 1867; and label or inline the un-labelled{math}block at 1873-1878 that 1880 refers to as “the two preceding equations”.Sweep the remaining items: bold-for-emphasis at 943, 1885-1886 and 2750 and italic-for-definition at 1706; the six bolded exercise titles moved onto the directive line; the mathematical-italic
𝛼/𝜆identifiers at 1525-1568 and 2187-2287 replaced with plainα/λ; the seven double spaces (599, 701, 940, 1758, 1860, 1885, 1886); the nineteen trailing-whitespace lines; the seven-blank-line gap at 426-432; and the typos at 577 (“populations counterparts”), 752 (“IQ change”), 810 (“estimate … become”), 939 (“factorizations automatically computes”), 1889 (“resemblences … reflects”) and 2067 (“the rest half”).