calvo_machine_learn#
Series: lecture-python-advanced.myst
File:
lectures/calvo_machine_learn.mdAudit date: 2026-08-26
Corpus snapshot:
b83d6da399Categories audited: writing, math, code, figures, references, links, admonitions (JAX out of scope)
Overall score: 7.2 / 10
Priority: HIGH
Score breakdown#
Category |
Score |
One-line note |
|---|---|---|
Writing |
3.5/10 |
|
Math |
3/10 |
|
Code |
6/10 |
|
JAX |
out of scope |
JAX rules target |
Figures |
8/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: 6. Lines: 569, 602, 1078, 1082, 1089, 1131. Example: 161 lines carry trailing whitespace, most of them inside the code cells (554, 557, 561, 564, 567, 575, 577, 581, 583, 586, 590, 611-613, 631, 636, 638, 1084, 1087, 1091, 1094, 1098, 1131, 1133, 1313, 1317). Top-level definitions are separated by one blank line where PEP8 asks for two, at 569-570 and 577-578, and the file uses two elsewhere.
Tis defined two different ways for the same object:T = len(μ) - 1incompute_θ(552) andcompute_V(584), matching the mathematics where \(\tilde\mu\) has \(T+1\) components (345), butT = len(μ)incompute_vt(1082), which is why the line that the comment calls “# Define v_T” has to be writtenv_t[T-1](1093). 1089-1090 gives the wrapper lambda the same parameter names as the enclosing scope,s_p = lambda θ, μ: s(θ, μ, ...), shadowing the θ and μ that the surrounding function is iterating over. Operator spacing is mixed inside single expressions:U(-α*θ) - (c / 2) * μ**2at 1078,λ**(T - jnp.arange(T)) * μbarat 563. And 602 leaves a note to the author in the output cell,print(f'deviation = {np.abs(V_val - clq.J_series[0])}') # good!.[qe-math-002] — Use \top for transpose notation. Count: 14. Lines: 860, 862, 865, 867, 870, 879, 880, 881. Example:
^Ttranspose in\vec{\beta}^T.[qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 12. Lines: 46, 311, 367, 391, 417, 726, 1058, 1328, 1364, 1401. Example: the lecture has not been proofread, and eight of the breaks are inside sentences the reader needs. 311: “the government’s problem is static in the sense that it chooses treats that time-series as a single object”. 367: “Having specified a truncated vector \(\tilde \mu\) and and having computed”. 391: “We hope that answers will agree with those found obtained by other more structured methods”. 417: “We’ll eventually want to compare the results we obtain here to those that we obtain in those obtained in this quantecon lecture”. 726: “We start by recalling that the Ramsey problem that chooses \(\vec \mu\) to maximize the government’s value function
{eq}`eq:Ramseyvalue`subject to equation{eq}`eq:inflation101`” - two relative clauses and a citation run into the next word. 1328: “appears at the peak of the function quadratic function”. 1364-1366: “Assembling these regressions, we have discovered run for our single Ramsey outcome path … that along a Ramsey plan”. 1191: “inflation at time \(t\) is determined \(\{\mu_s\}_{s=t}^\infty\)” is missing its preposition. Plus single-word typos at 46 (“money growh rates”), 1058 (“For subsquent analysis”), 1401 (“represenative agent’s”) and 1184 (“the reasoning that let Chang … to choose”).[qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 9. Lines: 18, 24, 48, 59, 72, 1058, 1167, 1412. Example: prose phrases are wrapped in double backticks, which is reStructuredText quoting and renders in MyST as inline code:
machine learning(18, 389, 724),dynamic programming squared(24),gradient descent(59),artificial intelligence(72) andcontinuation values(1058) all come out as code spans on the page. The same two terms are also given as bold - machine learning (48), human intelligence and artificial intelligence (1167) - so “machine learning” appears as code at 18, as bold at 48 and as plain text at 56 and 63, and “artificial intelligence” as code at 72 and bold at 1167. Meanwhile the double-backtick form is used correctly for a genuine identifier at 1412, 1414 and 1420 (ChangLQ), which is what makes the prose cases read as code to a reader. Italic is available and used once, for liquidity at 82, which is the treatment the scare-quoted phrases want; bold should be kept for the terms actually being defined, as at 77 (time inconsistency), 122 and 302.[qe-writing-008] — Remove excessive whitespace between words. Count: 193. Lines: 18, 19, 21, 24, 27, 29, 31, 36, 39, 43, …. Example: 2 spaces.
Medium severity#
[qe-code-003] — Package installation at lecture top. Count: 4. Lines: 399. Example: non-Anaconda import with no install cell: [‘jax’].
[qe-code-004] — Use quantecon Timer context manager. Count: 2. Lines: 656, 941. Example: %%time.
[qe-fig-005] — Descriptive figure names for cross-referencing. Count: 4. Lines: 1035, 1221, 1262, 1308. Example: code-cell figure without mystnb figure metadata.
[qe-fig-008] — Use lw=2 for line charts. Count: 3. Lines: 1223, 1264, 1313. Example: plot() without lw=.
[qe-math-004] — Do not use bold face for matrices or vectors. Count: 4. Lines: 865, 867, 870, 872. Example: \mathbf.
[qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 3. Lines: 851, 865, 878. Example: 865, 867, 870 and 872 write the diagonal matrix of discount factors as
\vec{\beta} \cdot \mathbf{I}- a \((T+1)\)-vector “times” an identity matrix, which is not a defined product and which the code implements as a diagonal; \(\mathrm{diag}(\vec\beta)\) says it in fewer symbols and is what the reader already knows. The vector itself is named \(\vec\beta\) (851-855) although \(\beta\) is the discount factor throughout, so \(\vec\beta\), \(\beta\) and \(\beta^t\) appear in the same three lines meaning three different things. And the truncated vector has two names: 345 and 353 introduce it as \(\tilde\mu\) and \(\tilde\theta\), which is what makes the truncation visible, but from 860 to 899 the same objects revert to \(\vec\mu\) and \(\vec\theta\) - the symbols 45-46 and 299 use for the infinite sequences - so the reader has to infer from context whether \(\vec\mu\) has \(T+1\) components or infinitely many.[qe-writing-001] — Use one sentence per paragraph. Count: 1. Lines: 1151. Example: 2 sentences in one paragraph.
[qe-writing-003] (reviewer) — Maintain logical flow. Count: 4. Lines: 1163, 1350, 1416, 1075. Example: the numbers that carry the lecture’s conclusion are typed into the prose rather than read from the cells: 1347-1361 states the three fitted relations as \(\mu_t = .0645 + 1.5995 \theta_t\), \(\theta_{t+1} = -.0645 + .4005 \theta_t\) and \(v_t = 6.8052 - .7580\theta_t - 4.6991\theta_t^2\), all six coefficients hard-coded, while the cells at 1195-1290 recompute them from
μs,θsandv_t- change \(\beta\), \(c\) or \(T\) anywhere above and the summary section silently goes stale. Second, 1416-1418 says “compute the parameters \(d_0, d_1\) for the decision rule for \(\mu_t\) and the parameters \(d_0, d_1\) in the updating rule for \(\theta_{t+1}\)” - the first pair is \(b_0, b_1\) in{eq}`eq_old9101`at 1375, and the cell at 1430 prints-(b_0, b_1), negated, with nothing said about why the sign flips before 1440 concludes that “these agree”. Third, 1163 says the two sequences “converge from above to the same constant \(\vec \mu\)”, using the sequence symbol for the scalar limit that 320 called \(\bar \mu\); the same slip appears at 311, where the pair is written(\vec mu, \vec \theta)and the missing backslash makes it render as \(\vec m u\). Fourth, two code comments point at section numbers from a different build: “# Compute g0, g1, and g2 (41.16)” (457) and “# Define function for s and U in section 41.3” (1075) - this lecture has no section 41.3, and 1191’s reference to{eq}`eq_grad_old3`is the kind of pointer that would work.[qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 3. Lines: 664, 1201, 1221. Example: the three regressions that are the point of the lecture print full
statsmodelsOLS summaries (1201, 1247, 1290) - about twenty-five lines each of dependent-variable headers, F-statistics, AIC, BIC, skew, kurtosis and Durbin-Watson - when what the text then quotes is four coefficients and the \(R^2\) of unity (1347-1361, 1389); a three-row table of coefficient, standard error and \(R^2\) would carry the argument and leave the condition-number warning that 1297-1300 discusses visible instead of buried. Second, the comparisons against the sister lecture’sChangLQbaseline are scattered across six bare cells that print a norm - 602, 669, 673, 677, 710, 719, 1111 - four of them consecutive and with no prose between them (664-678), so the reader meets four unexplained numbers in a row; one table of the three methods against \(\bar\mu\), \(V\) and the deviation would do the whole job. Third, only one of the five figures is named (continuation_values, 1121) and it is the only one the text can cross-reference with{numref}(1142); the three regression figures at 1221, 1262 and 1308 carry the punchline and cannot be referenced at all.
Low severity#
[qe-math-013 (proposed)] — Reference equations via
{eq}`label`. Count: 1. Lines: 383. Example: manual reference ‘formula (1)’.
Strengths#
The lecture names the weakness of its own method in the introduction and then keeps the comparison running: 48 explains why “machine learning” is the right label - the approach ignores the structure that dynamic programming squared supplies and “proliferates parameters” - 52-54 casts the sister lecture as a laboratory for judging “promises and limits of machine learning approaches more generally”, and every computed object is checked against
ChangLQ(602, 665-669, 710, 1440).The truncation is stated as a guess, given a closed form, and then implemented as written: 316-338 assumes \(\mu_t = \bar\mu\) for \(t \geq T\) and notes that
{eq}`eq:inflation101`then forces \(\theta_t \to \bar\mu\) too, 357-361 derives \(\theta_t = (1-\lambda)\sum_{j=0}^{T-1-t}\lambda^j \mu_{t+j} + \lambda^{T-t}\bar\mu\), 378-381 writes \(\tilde V\) with the \(\frac{\beta^T}{1-\beta}\) tail the truncation requires, andcompute_θ(550-568) andcompute_V(579-595) are those two formulas and nothing else.The two approaches are distinguished by exactly what mental work each avoids (56-61): the first “hands it over to a gradient descent optimizer”, the second “exerts enough mental effort required to express the Ramsey planner’s objective as an affine quadratic form in \(\vec \mu\), computes first-order conditions …, arranges them into a system of simultaneous linear equations” - and 840-899 then does the second in full, naming \(g\), \(M\), \(F\) and \(G\) with their dimensions as it goes.
The restricted problem is defined against the unrestricted one rather than described loosely: 686-689 repeats the Ramsey objective and adds “the additional restriction that \(\mu_t = \bar\mu\) for all \(t\)”, 691 identifies the solution as the \(\mu^{CR}\) of
{doc}`calvo`, and 710 prints the norm againstclq.μ_CR.The continuation values are set up as a backward recursion with a terminal condition (1060-1072), computed (1074-1101), and then used as a consistency check that the reader can see - 1104-1111 says \(v_0\) should equal the optimized \(V\) and prints the deviation - before 1142-1147 reads the orderings \(v_0 > V^{CR} > v_T\) off the figure and says what each inequality means.
The regression that looks backwards is flagged as such before it is run and revisited afterwards: 1189-1193 admits it “might seem strange because, after all, equation
{eq}`eq_grad_old3`asserts that inflation at time \(t\) is determined [by] \(\{\mu_s\}_{s=t}^\infty\)”, and 1395-1403 returns to the discomfort - “wouldn’t that direction of fit have made more sense?” - and answers that settling it needs more economic theory.The
{note}at 1150-1153 does real work in two sentences: it identifies \(v_T\) as what some researchers call “the value of a Ramsey plan under a time-less perspective” and offers the more descriptive name, “the value of the worst continuation Ramsey plan”, which is exactly the reading the figure above it supports.
Recommended actions#
Stop hard-coding the regression output: have 1347-1361 interpolate the fitted coefficients from
results1,results2andresults3(or state them as a rounded table generated by the cells), so the summary cannot drift from the computation.Fix the parameter names at 1416-1418 - the decision rule for \(\mu_t\) is \(b_0, b_1\), not \(d_0, d_1\) - and say why the cell at 1430 prints them negated before 1440 claims agreement.
Correct \(\vec\mu\) to \(\bar\mu\) at 1163 and add the missing backslash in
(\vec mu, \vec \theta)at 311.Replace the double-backtick prose quoting at 18, 24, 59, 72, 389, 724 and 1058 with italic, keep bold for the terms being defined, and leave the double backticks only where they mark an identifier (1412, 1414, 1420) - preferably as single backticks.
Proofread the ten broken sentences and typos listed above (46, 311, 367, 391, 417, 726, 1058, 1184, 1191, 1328, 1364, 1401).
Add
jaxto the install cell at 402-404: 395 says the implementation uses JAX, 410-411 importsjax.numpyandjax, and onlyquantecon,optaxandstatsmodelsare installed.Replace the three full OLS summaries (1201, 1247, 1290) with a coefficient table, collapse the seven bare
deviationcells (602, 669, 673, 677, 710, 719, 1111) into one comparison table, and give the four unnamed figure cells (1035, 1221, 1262, 1308)mystnbcaptions and names so the text can{numref}them.Write \(\mathrm{diag}(\vec\beta)\) in place of
\vec{\beta} \cdot \mathbf{I}(865, 867, 870, 872) - which also clears the four\mathbfhits - rename \(\vec\beta\) so it does not collide with the discount factor, and keep \(\tilde\mu, \tilde\theta\) for the truncated vectors from 860 onward.Sweep the code: 161 lines of trailing whitespace, two blank lines before the top-level defs at 570 and 578, one convention for
T(1082 against 552 and 584), rename the shadowing lambda parameters at 1089, drop the# good!at 602 and the stale section numbers at 457 and 1075, convert the two%%timemagics (656, 941) to thequanteconTimer, addlw=2at 1223, 1264 and 1313, replace “formula (1)” at 383 with an{eq}reference, and clear the 193 double spaces.