Compare commits

...

35 commits

Author SHA1 Message Date
Alireza Rezvani
19392f7a08
Merge pull request #996 from alirezarezvani/dev
Some checks failed
Deploy Documentation to Pages / build (push) Has been cancelled
Sync Codex Skills Symlinks / sync (push) Has been cancelled
Release / Tag + GitHub Release (push) Has been cancelled
Deploy Documentation to Pages / deploy (push) Has been cancelled
2026-08-26 15:53:02 +02:00
alirezarezvani
ae035f5a03 chore: sync codex skills symlinks [automated]
Some checks failed
Sync Codex Skills Symlinks / sync (push) Has been cancelled
2026-08-26 06:03:06 +00:00
Alireza Rezvani
8def1c40ec
Merge pull request #993 from alirezarezvani/claude/spinning-up-book-skill-hhbjpy 2026-08-26 08:02:39 +02:00
Alireza Rezvani
8b0fca4a4d
fix(book-to-skill): correct emitter docstring drift and the resident-core figure
Addresses both review findings on #993.

1. skill_plugin_emitter.py's module docstring still described the behaviour this
   PR removed. Its tree diagram called plugin.json the "manifest with
   ./skills/<slug> + attribution", and the rights-gate paragraph said
   cleared_for_distribution is recorded "in the manifest" -- both now the
   sidecar. A docstring asserting the opposite of its own file's point is worse
   than no docstring, and it is what `--help` readers see.

   Also corrects a third instance the review did not name but which shares the
   root cause: the tree diagram never listed authoring-notes.json at all, even
   though this PR's fix is what creates it. Added, with the issue #954 reason
   stated inline so the next reader knows why provenance cannot live in the
   manifest.

2. CLAUDE.md said the resident core is 2,066 tokens while, twelve lines later,
   the same file said 2,101. 2,066 predates the worked invocation block added
   for write-a-skill checklist item 5; token_budget_estimator.py reports 2,101
   on the current tree, matching CHANGELOG.md and the PR body. CLAUDE.md was
   the only stale copy and it contradicted itself.

Docstring-only and prose-only; no behaviour change. Verified the emitter still
emits both plugin.json and authoring-notes.json via --sample after the edit.

Gates: compileall, check_plugin_json --all, check_paths, check_frontmatter,
check_dual_publish, check_model_freshness, smoke_scripts (696/696),
derive_counters --check, book_skill_validator --strict.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UySnyf5upm4y8xhYA3w6yw
2026-08-25 22:57:41 +00:00
Alireza Rezvani
3301348d09
fix(docs): correct the commands delta and a README spacing nit
Addresses both review findings on #993.

1. The changelog/CLAUDE.md counter line said "commands 147 → 150", which
   asserts this plugin adds three commands. It adds exactly one
   (commands/cs-spinning-up-deep-rl.md). 147 was this branch's pre-merge
   baseline; after merging dev the delta had to be restated against dev's
   baseline, and that one figure was carried over unchanged while the others
   were updated. Verified empirically rather than by arithmetic: derive_counters
   on an origin/dev worktree reports 149 commands, and the raw command-file
   count goes 281 → 282 across the merge. Corrected to 149 → 150. The other
   three figures on that line (skills 387 → 388, agents 117 → 118, plugins
   98 → 99) were already right.

2. README POWERFUL-tier row had a stray space before a comma:
   "calculator) , **spinning-up-deep-rl**". Removed.

Neither affected derive_counters --check, which reads the tree rather than the
prose -- which is exactly why a wrong delta in prose can survive a green gate,
and why it was worth fixing in a repo this strict about counters being
trustworthy.

Gates re-run: compileall, check_plugin_json --all, check_paths,
check_frontmatter, check_dual_publish, check_model_freshness, smoke_scripts
(696/696), derive_counters --check.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UySnyf5upm4y8xhYA3w6yw
2026-08-25 22:53:54 +00:00
Alireza Rezvani
d5635e5a05
Merge branch 'dev' into claude/spinning-up-book-skill-hhbjpy
dev moved: PR #994 landed engineering/deep-learning-book, which collides with
this branch on every headline-counter and registry surface.

Conflicts resolved in four files, keeping both sides' content:

- .claude-plugin/marketplace.json -- both plugin entries kept; the registry now
  carries spinning-up-deep-rl and deep-learning-book. 99 plugins.
- CHANGELOG.md -- both Unreleased sections kept.
- CLAUDE.md, README.md -- dev's prose taken as the newer baseline, then this
  branch's engineering-row entry restored and every counter re-derived rather
  than hand-picked from either side.

Counters re-derived from the merged tree with derive_counters.py, which is the
ground truth, and trued up across all five surfaces: 388 skills, 99 plugins,
727 tools, 842 references, 118 agents, 150 commands.

Both changelog/CLAUDE.md delta lines are restated: each side was written against
its own base and both claimed 386 -> 387, which is no longer true of either now
that they land together. This branch's entry is now stated as the delta on top of
deep-learning-book.

Gates re-run on the resolved merge: no conflict markers left in the tree,
compileall, check_plugin_json --all, check_skill_names, check_paths,
check_frontmatter, check_dual_publish, check_model_freshness, smoke_scripts
(696/696), derive_counters --check, book_skill_validator --strict, and a
JSON/YAML parse of every file touched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UySnyf5upm4y8xhYA3w6yw
2026-08-25 22:49:14 +00:00
alirezarezvani
726be5cff5 chore: sync codex skills symlinks [automated]
Some checks are pending
Sync Codex Skills Symlinks / sync (push) Waiting to run
2026-08-25 20:56:22 +00:00
Alireza Rezvani
c7723f1a9d
Merge pull request #994 from alirezarezvani/claude/deep-learning-book-skill-xnbaz7 2026-08-25 22:56:11 +02:00
Claude
942e771319
fix(deep-learning-book): reject overlapping capacity regime bands
Ninth review on PR #994 found that --underparameterized-max and
--overparameterized-min, added two commits earlier, were never checked against each
other. Reproduced, and the consequence is sharper than a silent misclassification:
with --underparameterized-max 20 --overparameterized-min 5 and a ratio of 10, the
tool reported a model ten times overparameterized as "underparameterized" and exited
0. That verdict ranks "shrink the model" FIRST rather than last, inverting the exact
double-descent correction this tool exists to apply.

Added an argparse guard rejecting under-max >= over-min with a message naming both
values (exit 2, the documented usage-error code). Equal bands are rejected too,
since they leave the near-interpolation regime unreachable.

Verified: inverted and equal bands both exit 2; a valid override still moves the
regime (--overparameterized-min 500 gives near-interpolation); defaults unchanged at
overparameterized / OVERFIT / 240.0 with smaller-model last; the other exit codes
still 1 for an action, 0 for balanced, 4 for a leaky split.

Worth noting for the two flags' own history: they were added to close a consistency
nit, and introduced this defect in doing so. A new option is new surface, and its
interaction with existing options is part of it.

Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 20:06:05 +00:00
Claude
35f5b3b6d3
fix(deep-learning-book): narrow plural matching to -s, ending a false-refusal collision
Eighth review on PR #994 found that _matches()'s (?:s|es)? suffix reintroduced a
smaller version of the substring bug it was written to fix: "rag" + "es" matches the
standalone word "rages", so --goal "why overfitting still rages in large models"
exited 3, refused as out-of-scope retrieval-augmented-generation work.

Reproduced before fixing, then checked whether the -es branch earns its keep at all.
It does not: every keyword in the table ending in s, x, z, ch or sh is already plural
or non-count (basics, features, foundations, prerequisites, statistics, speech,
mlops, fairness, mathematics, time series), so no token needs -es appended. Narrowed
the auto-plural to plain -s and documented that irregular forms belong in
SURFACE_FORMS, spelled out, the way fine-tuning, prompting and agentic already are.

Verified: "rages" no longer matches while standalone "rag" still does; transformers,
embeddings, autoencoders and agentic still match; the goal above is now correctly
unroutable (exit 4) rather than confidently misrouted. RLHF, LoRA fine-tuning, RAG
pipelines and prompt/agent goals still exit 3; sequence, vision, generative and
practitioner routing unchanged.

That makes two rounds of false out-of-scope refusals from the same root cause —
approximate string matching standing in for a word list. The refusal path is the
part of this tool users are least able to second-guess, so it is the wrong place to
approximate.

Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:56:56 +00:00
Claude
5f5d84f469
feat(deep-learning-book): expose capacity_planner's regime bands as CLI flags
Seventh review on PR #994 noted that capacity_planner.py exposes --overfit-rel-gap
but hardcodes the two params-per-example regime bands, unlike its sibling scripts
where every threshold is overridable. The reviewer called it fine as shipped; the
inconsistency is small enough to close rather than carry.

The band matters more than a typical default: it decides whether "shrink the model"
is ranked last, which is the double-descent correction this tool exists to apply.
The interpolation point depends on task, architecture and label noise, so a user
whose model sits elsewhere had no way to say so.

Adds --underparameterized-max and --overparameterized-min, threaded through plan()
and classify_regime() as keyword arguments defaulting to the existing constants, and
reports all three thresholds in --output json the way training_diagnostics.py already
does. The help text repeats that these are heuristic bands, not a threshold theorem.

Defaults preserve behaviour exactly: the --sample fixture still reports
overparameterized / OVERFIT / 240.0 params-per-example with smaller-model ranked
last, identical to before the change. An override demonstrably moves the regime
(--overparameterized-min 500 reclassifies the same model as near-interpolation).
Exit codes unchanged: 1 for an action, 0 for balanced, 4 for a leaky split.

Not fixed here: CHANGELOG.md's duplicate [Unreleased] header, also noted in that
review. Verified pre-existing rather than introduced by this branch — the count is
2 at the merge-base with main and 2 at HEAD. Left for a separate changelog cleanup.

Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:49:51 +00:00
Claude
98019ac169
fix(deep-learning-book): make --include-intro actually do something
Sixth review on PR #994 noted that --include-intro appeared to have an observable
effect only on the complete lane. Checked it, and it was worse than reported: the
flag was inert on every lane, complete included.

Two reasons compounded. ch01 is not a prerequisite of any chapter, so it never
arrived through prerequisite closure; and the only lane that targets it, complete,
skipped the ch01 filter entirely. The filter therefore removed a chapter that was
never present, and the flag that controlled it could not change any output.

This also means my own verification of the parameter rename in c75500f was
inconclusive: it compared the complete lane with the flag against the vision lane
without it, and those differ for reasons unrelated to the flag. A test that cannot
fail proves nothing.

Inverted the logic so the flag adds ch01 rather than un-removing it, which gives it
a real effect on every lane while leaving complete unchanged (ch01 is already among
its targets). Help text now states what it does and that no lane pulls ch01 in on
its own.

Verified per lane: complete unchanged; vision, generative and foundations each gain
ch01 with the flag and are untouched without it; ch01 sorts first and never precedes
a chapter it would violate. Routing and both refusal paths are unchanged — sequence,
vision, generative and practitioner all route as before, out-of-scope still exits 3,
unroutable still exits 4.

Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:44:24 +00:00
Claude
8f833d22dd
fix(deep-learning-book): validate embedding seq_len like every other numeric field
Fifth review on PR #994 found the one numeric spec field I missed when adding typed
validation in the previous commit: embedding's seq_len still went through a bare
int(), so it bypassed the checks every sibling field had just been given.

Both failure modes reproduced before fixing:
  seq_len "ten"  -> uncaught ValueError, traceback, exit 1 (documented: exit 4)
  seq_len 0      -> no error at all; reported a plausible "0x8" layer with zero
                    activation elements and exited 0, presenting a degenerate model
                    as a valid one

Routed through _positive_int with the existing default (the incoming sequence
length, or 1), so both now exit 4 naming the layer and field. Verified the default
fallback still resolves to the input shape (16x8) and an explicit valid seq_len is
still honoured (32x8).

Swept the file afterwards rather than fixing only the reported instance: all 13
numeric spec fields now go through _positive_int, and no raw int() on a spec field
remains. The reference specs are unchanged — convnet 545,098 parameters, transformer
asset 7,087,872.

Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:38:58 +00:00
Claude
e923237360
fix(deep-learning-book): word-boundary keyword matching and typed input validation
Fourth review on PR #994 raised two findings against this plugin's scripts. Both
reproduced before fixing; the review's other findings are against marketing/linkedin,
which this branch carries from main but does not touch (see the PR comment).

1. reading_path_planner.py matched keywords by bare substring, so "rag" matched
   inside "storage", "lora" inside "exploratory", "conv" inside "converge" and
   "text" inside "context". Confirmed: --goal "train models for image storage and
   retrieval" exited 3, confidently refused as out-of-scope RAG work, and
   "an exploratory look at optimization" exited 3 citing LoRA. A tool whose stated
   design is to refuse rather than guess was guessing, and doing it with certainty.

   Matching is now word-boundary anchored with an optional plural, plus an explicit
   surface-form table for the few tokens whose inflections a word-boundary match
   would otherwise miss (fine-tuning, prompting, agentic). Verified: both goals above
   now route correctly (exit 0 / the optimization lane), "converge" reaches the
   optimization lane rather than vision, and the real refusals still refuse — RLHF,
   LoRA fine-tuning, RAG pipelines and prompt/agent goals all still exit 3.

2. model_arithmetic.py documented exit 4 for a spec it cannot parse but only caught
   SpecError and ShapeError, so malformed input escaped as a traceback with exit 1.
   Confirmed across five cases: a non-dict top-level JSON, a non-dict layer entry,
   stride 0, groups 0, and a non-numeric filters value. Numeric fields now go through
   a checked accessor that rejects non-integer and non-positive values, the input
   layer's shape is validated, and the top-level spec and every layer entry are
   type-checked. All five now exit 4 with a message naming the layer and field.

Regression battery over eight goals routes exactly as before; the convnet sample
still reports 545,098 parameters and the transformer asset 7,087,872.

Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:33:25 +00:00
Claude
eeb3cb9ad6
fix(deep-learning-book): position-wise linear, correcting a 512x parameter error in the example asset
Third review on PR #994 found a real bug in the flagship example asset. Verified
before fixing: assets/example_layer_spec.json reported 1,207,962,624 parameters
for the feedforward up-projection instead of 2,362,368 — off by exactly 512x, the
sequence length — putting the block's total at ~1.21B instead of ~7.09M.

Root cause was in the tool, not only the asset. model_arithmetic.py's mha layer
emits (seq, d_model) but linear refused any 2-D input, so the only way to attach a
feedforward block was to flatten first. Flattening collapses all 512 positions into
one 393,216-element vector, which models a dense layer over the whole sequence — a
different layer, with seq_len times the parameters. A transformer FFN was therefore
not expressible at all, and the shipped example walked straight into it. Clean exit
is not correct numbers, which is why --sample exit-code testing never caught it.

Fixed the cause: linear on a 2-D (seq, features) input is now position-wise — one
weight matrix shared across positions, parameters independent of sequence length,
compute linear in it. Documented in the module docstring; the 3-D path still refuses
with an updated message pointing at flatten. Removed the flatten from the example
asset and recorded in its comment why it must not come back.

Verified: the corrected block reports 7,087,872 parameters, matching a hand-check of
2*(2*768) + (4*768^2+4*768) + (768*3072+3072) + (3072*768+768) exactly, and the size
of a BERT-base encoder layer. The convnet --sample is unchanged at 545,098, and
linear on 3-D input still exits 5.

Also adds the missing CHANGELOG.md [Unreleased] entry, which the same review noted:
CLAUDE.md, README.md and marketplace.json carried the new skill and its counter
deltas but CHANGELOG.md did not.

Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:17:50 +00:00
Claude
1366714fdc
fix(deep-learning-book): break lane-scoring ties by keyword specificity
Second independent review on PR #994 observed that reading_path_planner.py's
score_lanes() broke equal-hit ties alphabetically by lane key, so SKILL.md's own
documented example "train a transformer" resolved to the practitioner lane rather
than sequence.

Reproduced: the goal hits practitioner on "train" and sequence on "transformer",
one keyword each, and alphabetical ordering picked practitioner.

Fixed the cause rather than the example. Ties now break on keyword specificity —
the lane whose longest matched keyword is longest wins — because an equal hit
count between a generic term and a discriminating one should not be settled by
luck. Lane key remains the final tie-break so ordering stays deterministic.

Regression battery over eight goals: "train a transformer" now routes to sequence;
vision, generative, foundations, practitioner, complete, representation and
sequence goals all route exactly as before. Refusal paths unchanged (out-of-scope
exit 3, unroutable exit 4, sample exit 0).

Gates green after the change: compileall, check_paths, check_frontmatter,
check_dual_publish, check_model_freshness, smoke_scripts (696 passed),
derive_counters --check, check_skill_names, check_plugin_json, book_skill_validator,
and --help + --sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:07:14 +00:00
Claude
c75500f804
fix(deep-learning-book): address review nits — internal naming and SAME-padding disclosure
Two small findings from the automated review on PR #994, both verified against the
source before fixing.

1. reading_path_planner.py: the plan() parameter was named include_optional while
   the CLI flag and call site both use include_intro, and it only ever gates ch01.
   Renamed the parameter and its use for consistency. Behavior unchanged, confirmed
   both ways: --include-intro keeps ch01 first, the default drops it.

2. model_arithmetic.py: conv2d "same" padding computes ceil(H / stride), which is
   the TensorFlow/Keras SAME convention, and the tool did not disclose which
   framework it matches. Documented it in the module docstring — including that
   PyTorch's padding='same' is symmetric-only and rejects a stride other than 1, so
   a strided PyTorch layer will not match, with "valid" named as the exact-case
   workaround — plus a pointer comment at the computation itself. No arithmetic
   change; the sample stack reports identical parameters and FLOPs.

The reviewer's third point was that it could not execute the gates in a sandboxed
environment. No code change: those gates were run locally and are green.

Verified after the change: compileall, check_paths, check_frontmatter,
check_dual_publish, check_model_freshness, smoke_scripts (696 passed),
derive_counters --check, check_skill_names, check_plugin_json, the book-skill
validator, and --sample --output json on all four tools.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:02:25 +00:00
Claude
cf572c83b6
fix(deep-learning-book): qualify reference and asset links from the plugin root
CI gate G1 (scripts/check_paths.py) failed on the previous commit: the agent and
command files live at engineering/deep-learning-book/{agents,commands}/, so bare
references/*.md and assets/*.md tokens resolved against neither the plugin root,
the file's own directory, nor the repo root — the three bases the linter accepts.
The files they point at live under skills/deep-learning-book/.

Prefix the nine offending links with skills/deep-learning-book/ so they resolve
from the plugin root. Content unchanged otherwise; SKILL.md's own relative links
were already correct and were not touched.

Reproduced the failure locally (9 unresolvable references across 4 files), then
confirmed the same check clean, plus every other blocking gate: compileall,
check_plugin_json, check_skill_names, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 19:00:23 +00:00
Alireza Rezvani
40fa75258a
docs(book-to-skill): add attribution block to the compiled skill's sidecar
Addresses the review observation on #993: the compiled skill's
authoring-notes.json carried only a `source` block (how it was built) even
though its content is derived from an external MIT-licensed work, where the
rest of the repo uses an `attribution` block for that. check_plugin_json.py's
NOTES_ALLOWED permits both keys, so the two coexist.

Adds `attribution` to engineering/spinning-up-deep-rl following the shape used
by book-to-skill and skillopt-sleep: derived_from, upstream_docs, upstream_path,
original_author, original_license, original_copyright, derivation_note.

The emitter is deliberately NOT changed to synthesise this. It knows only
`--source-note` free text and a rights basis -- not an upstream URL, author or
licence -- and a half-filled attribution block is worse than none. Instead
Step 11 of conversion_workflow.md now says attribution is added by hand
whenever `--rights` is anything but internal-docs, names the field shape, and
restates that the actual obligation is the LICENSE notice and README credit --
authoring-notes.json is metadata Claude Code never reads, and a sidecar JSON
file is not a licence notice.

Gates re-run clean: check_plugin_json --all, check_paths, check_frontmatter,
check_dual_publish, check_model_freshness, smoke_scripts (692/692),
derive_counters --check, book_skill_validator --strict.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UySnyf5upm4y8xhYA3w6yw
2026-08-25 18:57:31 +00:00
Claude
1a8d782872
feat(engineering): add deep-learning-book — companion skill for the free Goodfellow/Bengio/Courville textbook
Requested as "convert deeplearningbook.org into a skill". Built as a companion
rather than a compilation, because the repo's own rights gate forbids the latter
for a public plugin.

Why not book-to-skill: its emitter refuses a shareable package without
public-domain / open-license / internal-docs / author-permission, none of which
applies to an MIT Press title whose site states its HTML-only format exists as a
friction against copying under the authors' contract. Its rights reference lists
publishing a compiled skill of a copyrighted book to a public marketplace under
"Do not", and its hard rule 1 forbids scraping a book from the web, so the
pipeline could not have run against a URL either.

What shipped instead: the compiled-skill shape (master SKILL.md ~2.0k tokens with
chapter and topic indexes, chapters/ch01..ch20, glossary, patterns, cheatsheet)
filled with original synthesis and linking to the official free chapters. No
passages, figures, or per-paragraph paraphrase. Passes book-to-skill's own
book_skill_validator.py clean, with every file inside token_budget_estimator's caps.

The differentiator is the delta layer. A compilation freezes a source at its
publication date; this one dates it. Every chapter carries "What changed after
2016", and references/book_to_2026_delta.md gives five corrections with primary
citations and per-claim confidence levels: double descent qualifying Ch 5's
U-curve, AdamW splitting weight decay from L2, transformers displacing Ch 10's
recurrence, diffusion growing out of Ch 18's score matching, and self-supervised
learning vindicating Ch 15 while replacing its methods. Two claims are marked
contested rather than propagated, two named as folklore.

Four stdlib-only tools, each with a real refusal:
- reading_path_planner.py — prerequisite closure over the book's actual dependency
  graph; exit 3 for a goal the book does not cover, exit 4 with forcing questions
- training_diagnostics.py — Ch 11's rules in priority order, so a NaN is never
  reported as overfitting; exit 4 rather than diagnosing with no instruments
- capacity_planner.py — regularization ladder in cost order, "shrink the model"
  ranked last in the overparameterized regime; exit 4 on a val-below-train split
- model_arithmetic.py — params/FLOPs/activation memory for conv, linear, MHA and
  LSTM/GRU stacks; exit 5 naming the layer whose shapes do not connect

Also: 4 references citing 7-8 sources each, 3 assets, cs-deep-learning-tutor
agent, /cs:deep-learning + /cs:dl-reading-path + /cs:dl-diagnose.

Counters: skills 386 to 387, tools 723 to 727, refs 838 to 842, agents 116 to 117,
commands 146 to 149, plugins 97 to 98 (verified by derive_counters.py --check).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
2026-08-25 18:56:57 +00:00
Alireza Rezvani
59956d04bd
chore: true up mkdocs and codex counters after merging dev
dev's derive_counters.py gained two additional check targets that main's copy
did not have -- mkdocs.yml's site_description and .codex-plugin/plugin.json's
description / shortDescription / longDescription. Both carried the pre-linkedin,
pre-skill-doctor numbers (380 skills / 706 tools / 823 refs / 114 agents /
138 commands / 96 plugins), so the blocking gate fails on this branch the moment
dev's checker meets main's tree.

Synced all six to the derived values: 387 skills, 723 tools, 838 references,
117 agents, 147 commands, 98 plugins.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UySnyf5upm4y8xhYA3w6yw
2026-08-25 18:51:34 +00:00
Alireza Rezvani
fe119c2883
Merge remote-tracking branch 'origin/dev' into claude/spinning-up-book-skill-hhbjpy 2026-08-25 18:50:20 +00:00
Alireza Rezvani
800a0d5672
feat(engineering): compile OpenAI's Spinning Up in Deep RL into a knowledge-base plugin
Runs engineering/book-to-skill end to end on its first real source: OpenAI's
Spinning Up in Deep RL (MIT, (c) 2018 OpenAI; primarily developed by Joshua
Achiam). Cloned openai/spinningup and compiled its docs/ reStructuredText tree
(38 files, ~37k words, ~49K tokens) through the full pipeline -- extract
--mode technical, analysis, 20 chapter files, glossary/patterns/cheatsheet,
master SKILL.md, validator, plugin emitter.

The compiled skill passes book_skill_validator.py in --strict mode with every
file inside budget: a 2,101-token resident core (cap 4,000) plus 20 on-demand
chapters averaging ~1,256 tokens each.

Chapter structure follows the source's own toctree rather than a heading scan:
user documentation (ch01-06), Introduction to RL Parts 1-3 (ch07-09), the
researcher essay / key papers / exercises / benchmarks (ch10-13), one chapter
per algorithm in lineage order (ch14-19: VPG to TRPO to PPO, DDPG to TD3 and
SAC), and the logger/MPI/ExperimentGrid utilities (ch20).

Rights basis is open-license, not fair use -- the emitter's Step-11 gate
refuses a shareable package without one. Upstream's MIT notice is reproduced
in full in the plugin's LICENSE beside this package's own, and README.md names
the source, the author and the source's frozen version; a sidecar JSON is not
a license notice.

Also fixes a defect the emitter only reveals at its final step:
skill_plugin_emitter.py wrote its whole `source` provenance block into
plugin.json, on a stale inline claim that `source`/`attribution` were approved
extension fields. Claude Code rejects an entire manifest on any unrecognized
key (issue #954) and scripts/check_plugin_json.py hard-fails such a manifest,
so every package the emitter produced failed the blocking CI gate on commit.
_plugin_manifest() now emits spec fields only and a new _authoring_notes()
writes .claude-plugin/authoring-notes.json. Recorded as deviation 26 in
engineering/book-to-skill/README.md; the printed marketplace.json snippet is
unchanged, since `source` is a valid key there.

Counters: skills 386 -> 387, agents 116 -> 117, commands 146 -> 147, plugins
97 -> 98. Tools and references unchanged -- a compiled knowledge base ships
notes, not scripts.

All blocking CI gates verified locally: compileall, check_plugin_json --all,
check_skill_names, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (692/692), derive_counters --check.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UySnyf5upm4y8xhYA3w6yw
2026-08-25 18:49:30 +00:00
Alireza Rezvani
f2bac0a8f2
Merge pull request #991 from alirezarezvani/claude/linkedin-skill-plugin-vxkugm
Some checks are pending
Release / Tag + GitHub Release (push) Waiting to run
Deploy Documentation to Pages / build (push) Waiting to run
Deploy Documentation to Pages / deploy (push) Blocked by required conditions
Sync Codex Skills Symlinks / sync (push) Waiting to run
2026-08-25 10:03:50 +02:00
Claude
645c523be1
feat(marketing): add linkedin plugin — organic presence with platform rules in code
Answers discussion #934, which asked for a strategic assistant for growing a
LinkedIn presence organically rather than a post generator.

Six skills under marketing/linkedin/: an orchestrator (context: fork) plus
profile, strategy, content, engagement, and analytics lanes. 17 stdlib-only
tools, 15 references, 2 agents, 8 /cs:* commands.

The design constraint is the differentiator: no LinkedIn credentials, no API
calls, no scraping, nothing auto-sent. Automated posting, connecting, and
commenting are prohibited by LinkedIn's User Agreement 8.2, and a restricted
account ends a compounding asset. linkedin_policy_gate.py runs before any
drafting and refuses seven request classes — automation, scraping, engagement
pods, bulk messaging, fake identity, fabricated proof, named third-party
automation platforms — each carrying the policy anchor and a compliant
substitute, so the gate never just says no.

Refusals are real rather than advisory. A cadence under 90 minutes a week
returns a comment-only plan instead of a schedule that dies in week five. A
newsletter whose six-month cost exceeds the budget is refused before the promise
is made. An experiment needing more posts than a quarter allows is reported
infeasible rather than quietly re-sized. The pattern miner refuses to test
anything below 10 posts and reports NOTHING_SURVIVED as a finding.

Evidence discipline: two widely repeated claims are corrected rather than
propagated. The "personalised note triples acceptance" claim is not supported by
the largest samples (acceptance is near-identical either way, ~26.4%); what a
note moves is the post-accept reply rate (~5.4% to ~9.4%), which is why the
message builder refuses an ask in a first-touch note. The ~19% in-body link
reach reduction has never been confirmed by LinkedIn as a penalty and has a
plausible dwell-time explanation, so it is a warning rather than a block. Every
reference carries per-claim confidence levels.

Accessibility is a blocking lint finding: Unicode pseudo-bold is announced by
screen readers as mathematical symbols and is not indexed by search.

All six SKILL.md files are 6/6 PASS on the write-a-skill checklist. Every tool
supports --help, --sample, and --output json with typed exit codes.

Counters: skills 380 -> 386; plugins 96 -> 97; tools 706 -> 723; refs 823 -> 838;
agents 114 -> 116; commands 138 -> 146 (derive_counters.py --check).

Also syncs three previously-merged skills (agent-memory, hivemind, skill-doctor)
into the .hermes/ and .vibe/ mirror trees, which had drifted behind .codex/.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JSPxUHU6utqme7qC6EwHEh
2026-08-25 07:32:30 +00:00
Alireza Rezvani
7d952ed1cf
Merge pull request #990 from alirezarezvani/claude/review-15-reported-issues-vrt6b2
chore(scripts): sync derive_counters docs with 5-source gate, rename EXCLUDED_DIRS
2026-08-25 08:49:27 +02:00
Claude
af8aa6e66b
style(scripts): update derive_counters top-of-file summary to the 5-source list
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
2026-08-25 06:47:46 +00:00
Claude
5d2ff0d49d
style(scripts): rewrap derive_counters docstring to consistent width
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
2026-08-25 06:46:01 +00:00
Claude
c118489398
chore(scripts): sync derive_counters docs with 5-source gate, rename EXCLUDED_DIRS to EXCLUDED_NAMES
Two reviewer nits batched: derive_counters.py's module docstring and --check
help still described the pre-#989 three-source coverage (flagged on #989);
check_model_freshness.py's EXCLUDED_DIRS did double duty as a directory AND
filename exclusion set, which the name hid (flagged on #985 and #988's
reviews) — renamed with a comment stating both roles. No behavior change;
both gates re-verified passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
2026-08-25 06:43:51 +00:00
Alireza Rezvani
ab46f472ab
Merge pull request #989 from alirezarezvani/claude/review-15-reported-issues-vrt6b2
fix(docs): true up nine-release-stale Codex manifest, gate it and mkdocs.yml in the counter check
2026-08-25 08:42:35 +02:00
Alireza Rezvani
6eb1f45fb5
Merge pull request #974 from kriptoburak/codex/pulse-local-x-exports
fix(pulse): import local X research exports
2026-08-25 08:42:22 +02:00
Claude
c8ed1048b9
fix(scripts): gate the Codex manifest interface descriptions too
Review follow-up on #989: shortDescription/longDescription carry their own
counts and were just trued — include them in the gated source text so
standardized-phrasing claims in them are checked (non-matching prose is
simply not read). Verified: planting 997 in shortDescription fails the
gate; restored passes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
2026-08-25 06:39:32 +00:00
Claude
a36d91171c
fix(docs): true up nine-release-stale Codex manifest, gate it and mkdocs.yml in the counter check
Adopts the two verified findings from PR #940 (credit: @benrfairless):

- .codex-plugin/plugin.json still said v2.2.0 / 223 skills / 23 agents /
  298 tools / 9 domains — roughly nine releases behind, and it is the
  manifest Codex users see. Version, description, and the interface
  short/long descriptions are trued to the v2.12.0 counters (380 skills /
  20 domains / 706 tools / 823 refs / 114 agents / 138 commands / 96
  plugins), with the top-level description written in the standardized
  claim phrasing so the gate can read it.
- mkdocs.yml's site_description was content-correct after v2.12.0 but
  ungated and phrased invisibly to extract_claims ('agent skills',
  'installable plugins') — reworded to the standardized phrasing.
- derive_counters.py run_check() now reads both as claim sources
  (mkdocs.yml restricted to the site_description line since its !!python
  tags reject safe_load). Verified: planting 999/998 in the two sites
  fails the gate naming both; restored values pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
2026-08-25 06:36:26 +00:00
Alireza Rezvani
22149f4c34
Merge branch 'dev' into codex/pulse-local-x-exports 2026-08-25 08:34:47 +02:00
kriptoburak
8f280faf5b fix(pulse): import local X research exports 2026-08-21 11:56:17 +03:00
187 changed files with 16553 additions and 97 deletions

View file

@ -8,7 +8,7 @@
"homepage": "https://github.com/alirezarezvani/claude-skills",
"repository": "https://github.com/alirezarezvani/claude-skills",
"metadata": {
"description": "380 production-ready skills across 20 domains (engineering, engineering-core, marketing, product, c-level, c-level-agents, compliance-os, project management, RA/QM, business growth, finance, productivity, marketing top-level, research, research-ops, business-operations, commercial, markdown-html, loop-library, plus standards). 706 Python tools, 823 reference guides, 114 agents (cs-* + personas), 138 slash commands across 96 marketplace plugins. v2.11.2 vendors engineering/skillopt-sleep — a verbatim copy of microsoft/SkillOpt's stdlib-only skillopt_sleep engine + Claude Code plugin surface, giving a local agent a nightly gated self-improvement cycle (read-only session harvest -> mine -> offline replay -> held-out-gated CLAUDE.md/SKILL.md edits -> staged for explicit /skillopt-sleep adopt). productivity/fable-goal (unreleased, post-v2.11.1) converts a rambling description of a desired outcome into one polished /goal prompt for a fresh autonomous session. v2.11.1 turns product-team and project-management into agent-harness domains: fork-orchestrators with deterministic goal routers, a Jira MCP snapshot bridge (Kanban flow metrics + Monte Carlo forecasting), a delegation-governance loop gate, a continuous-discovery cadence tracker, and an Opportunity Solution Tree linter, with /cs:pm and /cs:product command families. v2.10.3 completes the markdown-html domain with md-slides — slide-deck converter (arrow-key / Space / PgDn / Home/End / P keyboard navigation + presenter mode with split-view clock + speaker notes + next-slide preview + URL-hash deep linking like #3 for direct slide jumps + @media print page-per-slide for browser-native PDF export). Reuses md-document's markdown parser; vanilla JS only (no framework runtime); Prism.js opt-in via --syntax. Joins md-review (v2.10.2 code-review converter), md-document (v2.10.1 long-form converter), and the v2.10.0 foundation (orchestrator + design-system). Compatible with Claude Code, Codex CLI, Gemini CLI, Cursor, OpenClaw, Hermes Agent, Mistral Vibe, and 5 more coding agents.",
"description": "388 production-ready skills across 20 domains (engineering, engineering-core, marketing, product, c-level, c-level-agents, compliance-os, project management, RA/QM, business growth, finance, productivity, marketing top-level, research, research-ops, business-operations, commercial, markdown-html, loop-library, plus standards). 727 Python tools, 842 reference guides, 118 agents (cs-* + personas), 150 slash commands across 99 marketplace plugins. v2.11.2 vendors engineering/skillopt-sleep — a verbatim copy of microsoft/SkillOpt's stdlib-only skillopt_sleep engine + Claude Code plugin surface, giving a local agent a nightly gated self-improvement cycle (read-only session harvest -> mine -> offline replay -> held-out-gated CLAUDE.md/SKILL.md edits -> staged for explicit /skillopt-sleep adopt). productivity/fable-goal (unreleased, post-v2.11.1) converts a rambling description of a desired outcome into one polished /goal prompt for a fresh autonomous session. v2.11.1 turns product-team and project-management into agent-harness domains: fork-orchestrators with deterministic goal routers, a Jira MCP snapshot bridge (Kanban flow metrics + Monte Carlo forecasting), a delegation-governance loop gate, a continuous-discovery cadence tracker, and an Opportunity Solution Tree linter, with /cs:pm and /cs:product command families. v2.10.3 completes the markdown-html domain with md-slides — slide-deck converter (arrow-key / Space / PgDn / Home/End / P keyboard navigation + presenter mode with split-view clock + speaker notes + next-slide preview + URL-hash deep linking like #3 for direct slide jumps + @media print page-per-slide for browser-native PDF export). Reuses md-document's markdown parser; vanilla JS only (no framework runtime); Prism.js opt-in via --syntax. Joins md-review (v2.10.2 code-review converter), md-document (v2.10.1 long-form converter), and the v2.10.0 foundation (orchestrator + design-system). Compatible with Claude Code, Codex CLI, Gemini CLI, Cursor, OpenClaw, Hermes Agent, Mistral Vibe, and 5 more coding agents.",
"version": "2.12.0"
},
"plugins": [
@ -1285,6 +1285,28 @@
],
"category": "marketing"
},
{
"name": "linkedin",
"source": "./marketing/linkedin",
"description": "Organic LinkedIn presence, end to end, with LinkedIn's own rules enforced in code. Orchestrator (context: fork) gates every request against User Agreement §8.2 — refusing automation, scraping, engagement pods, bulk DMs, fake identity and fabricated proof, each with a compliant substitute — then routes to profile / strategy / content / engagement / analytics. Headline and whole-profile scoring with fixes ranked by points per hour; positioning brief with a mandatory exclusion list; cadence priced against real hours with a 90-minute floor; newsletter eligibility + six-month sustainability gate; post linter blocking on engagement bait and screen-reader-hostile Unicode pseudo-bold; repurposing with a reuse ledger; capped commenting roster and template-refusing outreach; analytics that test patterns against a seeded permutation null and refuse to conclude below 10 posts. 17 stdlib tools, 15 references with per-claim confidence levels. No credentials, no API calls, nothing auto-sent. Answers discussion #934.",
"version": "2.12.0",
"author": {
"name": "Alireza Rezvani"
},
"keywords": [
"linkedin",
"personal-brand",
"organic-growth",
"content-strategy",
"profile-optimization",
"outreach",
"newsletter",
"social-media",
"thought-leadership",
"career-change"
],
"category": "marketing"
},
{
"name": "pulse",
"source": "./research/pulse",
@ -2028,6 +2050,49 @@
"engineering"
],
"category": "development"
},
{
"name": "spinning-up-deep-rl",
"source": "./engineering/spinning-up-deep-rl",
"description": "Knowledge base compiled from OpenAI's Spinning Up in Deep RL (MIT, Joshua Achiam) by engineering/book-to-skill. A resident core carries the RL optimization problem, the model-free taxonomy, the policy-gradient template with its five valid weights, the safe-step family (VPG to TRPO to PPO) and the overestimation family (DDPG to TD3 and SAC); 20 on-demand chapters cover key concepts and MDPs, the algorithm taxonomy and model bias, the policy gradient derivation with the log-derivative trick and EGLP lemma, Achiam's researcher essay, the key-papers topic map, the exercises including the silent DDPG broadcasting bug, the benchmark parity disclosure, one chapter per algorithm, and the logger/MPI/ExperimentGrid utilities. Ships a glossary, a patterns file with 16 techniques, a decision cheatsheet with thresholds, a cs-spinning-up-deep-rl agent and /cs:spinning-up-deep-rl. Structured study notes, not a reproduction of the source.",
"version": "1.0.0",
"author": {
"name": "Alireza Rezvani"
},
"keywords": [
"knowledge-base",
"book-to-skill",
"reinforcement-learning",
"deep-rl",
"policy-gradient",
"ppo",
"sac",
"td3",
"openai-spinning-up",
"engineering"
],
"category": "development"
},
{
"name": "deep-learning-book",
"source": "./engineering/deep-learning-book",
"description": "Study companion for the Deep Learning textbook by Goodfellow, Bengio & Courville (MIT Press, 2016), free to read at deeplearningbook.org. Twenty chapter files, a glossary, patterns and a cheatsheet index the whole book, and a delta reference dates it against 2026 practice with per-claim confidence levels: double descent qualifying the U-curve, AdamW splitting weight decay from L2, transformers displacing Chapter 10's recurrence, diffusion growing out of Chapter 18's score matching. Four stdlib tools make it executable — a prerequisite-closed reading-path planner that refuses goals the book does not cover, a training diagnostic running Chapter 11's rules in priority order so a NaN is never reported as overfitting, a capacity planner that ranks 'shrink the model' last when overparameterized, and a parameter/FLOP/activation-memory calculator that refuses a stack whose shapes do not connect. A companion, not a compilation: the book is copyrighted, so nothing here reproduces its text.",
"version": "2.12.0",
"author": {
"name": "Alireza Rezvani"
},
"keywords": [
"deep-learning",
"machine-learning",
"study-companion",
"goodfellow",
"neural-networks",
"training-diagnostics",
"optimization",
"generative-models",
"engineering"
],
"category": "development"
}
]
}

View file

@ -1,7 +1,7 @@
{
"name": "claude-code-skills",
"version": "2.2.0",
"description": "223 production-ready skills, 23 agents, and 298 Python tools across 9 domains — engineering, marketing, product, compliance, C-level advisory, and more. The largest open-source skills library for AI coding agents.",
"version": "2.12.0",
"description": "388 production-ready skills across 20 domains — engineering, marketing, product, compliance, C-level advisory, research, business operations, and more. 727 Python tools, 842 reference guides, 118 agents (cs-* + personas), 150 slash commands, 99 marketplace plugins. The largest open-source skills library for AI coding agents.",
"author": {
"name": "Alireza Rezvani",
"url": "https://alirezarezvani.com"
@ -27,8 +27,8 @@
"type": "cli",
"composerIcon": "./assets/icon.png",
"displayName": "Claude Code Skills",
"shortDescription": "223 production-ready skills for AI coding agents across 9 domains",
"longDescription": "The largest open-source skills library for AI coding agents. 223 skills covering engineering (architecture, DevOps, security, AI/ML), marketing (SEO, CRO, content), product management, C-level advisory, regulatory compliance (ISO 13485, SOC 2, GDPR), project management, business growth, and finance. Includes 298 stdlib-only Python CLI tools, 416 reference guides, 23 orchestration agents, and 22 slash commands. Works with Codex, Claude Code, Gemini CLI, Cursor, Aider, Windsurf, and 5 more tools.",
"shortDescription": "388 production-ready skills for AI coding agents across 20 domains",
"longDescription": "The largest open-source skills library for AI coding agents. 388 skills covering engineering (architecture, DevOps, security, AI/ML, agent tooling), marketing (SEO, AEO, CRO, content), product management, C-level advisory, regulatory compliance (ISO 13485, SOC 2, GDPR), project management, research and research operations, business operations, commercial, finance, and personal productivity. Includes 727 stdlib-only Python CLI tools, 842 reference guides, 118 orchestration agents, and 150 slash commands. Works with Codex, Claude Code, Gemini CLI, Cursor, Hermes Agent, Mistral Vibe, and 7 more tools.",
"developerName": "Alireza Rezvani",
"category": "Coding",
"capabilities": [

View file

@ -3,7 +3,7 @@
"name": "claude-code-skills",
"description": "Production-ready skill packages for AI agents - Marketing, Engineering, Product, C-Level, PM, and RA/QM",
"repository": "https://github.com/alirezarezvani/claude-skills",
"total_skills": 356,
"total_skills": 364,
"skills": [
{
"name": "agent-launcher-orchestrator",
@ -1001,6 +1001,12 @@
"category": "engineering-advanced",
"description": "Use when the user asks to create ERD diagrams, normalize database schemas, design table relationships, or plan schema migrations."
},
{
"name": "deep-learning-book",
"source": "../../engineering/deep-learning-book/skills/deep-learning-book",
"category": "engineering-advanced",
"description": "Study companion and working knowledge base for the Deep Learning textbook by Goodfellow, Bengio & Courville (MIT Press, 2016), read free at deeplearningbook.org. Indexes all 20 chapters, carries a 2016-to-2026 delta layer naming what the book got right, what was superseded (transformers, AdamW, diffusion, double descent) and what still holds, and ships four deterministic tools: a prerequisite-aware reading-path planner, a training-failure diagnostic, a capacity-and-regularization planner, and a parameter/FLOP/activation-memory calculator. Use when studying or teaching this book, planning a route through it, deciding whether a chapter's advice is still current, or translating its math into a training decision. It points at the official chapters \u2014 it never reproduces them."
},
{
"name": "demo-video",
"source": "../../engineering/demo-video/skills/demo-video",
@ -1319,6 +1325,12 @@
"category": "engineering-advanced",
"description": "Use when the user asks to write specs before code, define acceptance criteria, plan features before implementation, generate tests from specifications, or follow spec-first development practices."
},
{
"name": "spinning-up-deep-rl",
"source": "../../engineering/spinning-up-deep-rl/skills/spinning-up-deep-rl",
"category": "engineering-advanced",
"description": "Knowledge base from \\\"Spinning Up in Deep RL\\\" by Joshua Achiam (OpenAI, MIT-licensed). Use when applying Achiam's frameworks for RL fundamentals and MDPs, the model-free algorithm taxonomy, policy gradient derivations, the six reference algorithms (VPG, TRPO, PPO, DDPG, TD3, SAC), debugging silently-failing RL code, or running rigorous multi-seed RL experiments."
},
{
"name": "sql-database-assistant",
"source": "../../engineering/skills/sql-database-assistant",
@ -1541,6 +1553,42 @@
"category": "marketing",
"description": "When the user wants to plan a product launch, feature announcement, or release strategy. Also use when the user mentions 'launch,' 'Product Hunt,' 'feature release,' 'announcement,' 'go-to-market,' 'beta launch,' 'early access,' 'waitlist,' 'product update,' 'GTM plan,' 'launch checklist,' or 'launch momentum.' This skill covers phased launches, channel strategy, and ongoing launch momentum."
},
{
"name": "linkedin-analytics",
"source": "../../marketing/linkedin/skills/linkedin-analytics",
"category": "marketing",
"description": "Use when someone wants to understand their own LinkedIn numbers \u2014 which posts worked, why reach dropped, whether a pattern is real, or how to test a hypothesis. Triggers on \"why did my reach drop\", \"what's working on my LinkedIn\", \"analyze my posts\", \"do carousels do better for me\", \"should I test this\", \"LinkedIn analytics\". Reads your own exported post data, reports medians and outlier bands, tests candidate patterns against a permutation null, and sizes a real experiment \u2014 refusing to conclude anything below 10 posts."
},
{
"name": "linkedin-content",
"source": "../../marketing/linkedin/skills/linkedin-content",
"category": "marketing",
"description": "Use when someone wants to write, edit, or lint a LinkedIn post \u2014 a story, how-to, opinion piece, carousel script, video script, or poll \u2014 or wants an article, talk, or transcript repurposed into posts. Triggers on \"write a LinkedIn post\", \"is this hook any good\", \"review my post\", \"turn this into LinkedIn posts\", \"carousel\", \"what format should this be\". Lints posts 0-100 on mechanics, hook, integrity, and accessibility; picks the format the material actually supports; and splits long sources into standalone units with a reuse ledger."
},
{
"name": "linkedin-engagement",
"source": "../../marketing/linkedin/skills/linkedin-engagement",
"category": "marketing",
"description": "Use when someone wants to grow reach through comments, replies, groups, or outreach on LinkedIn \u2014 a commenting roster, a connection request note, a DM or InMail, a networking plan, or a check on whether their outreach volume is safe. Triggers on \"who should I engage with\", \"write a connection request\", \"cold DM\", \"LinkedIn outreach\", \"networking strategy\", \"how many invites can I send\". Builds a weekly comment roster inside a real time budget, assembles one message at a time and refuses templates, and caps volume against LinkedIn's limits. Nothing is ever sent."
},
{
"name": "linkedin-profile",
"source": "../../marketing/linkedin/skills/linkedin-profile",
"category": "marketing",
"description": "Use when someone wants their LinkedIn profile audited or rewritten \u2014 headline, About section, experience bullets, Featured, banner, recommendations \u2014 or says \"fix my headline\", \"my profile gets views but nothing happens\", \"optimize my LinkedIn profile\", \"what should my About section say\". Scores the headline on five dimensions, audits the whole profile 0-100 and ranks fixes by points per hour, and assembles an About section that survives the \"\u2026see more\" fold."
},
{
"name": "linkedin-skills",
"source": "../../marketing/linkedin/skills/linkedin-skills",
"category": "marketing",
"description": "Use when someone wants to grow an organic LinkedIn presence \u2014 a content strategy for a career change or consulting or thought leadership, a rewritten profile or headline, post drafts and hooks, a posting cadence or newsletter plan, connection notes and outreach, a commenting strategy, repurposing an article or talk into posts, or a read on why their reach dropped. Triggers on \"grow my LinkedIn\", \"fix my headline\", \"write a LinkedIn post\", \"what should I post about\", \"LinkedIn strategy\", \"connection request\", \"my reach dropped\". Forks context to route to one of five sub-skills, and refuses automation, scraping, pods, and bulk DMs before any drafting starts."
},
{
"name": "linkedin-strategy",
"source": "../../marketing/linkedin/skills/linkedin-strategy",
"category": "marketing",
"description": "Use when someone needs a LinkedIn plan rather than a post \u2014 content pillars, positioning for a career change or consulting or thought leadership, a sustainable posting cadence, or a newsletter decision. Triggers on \"what should I post about\", \"how often should I post\", \"LinkedIn content strategy\", \"should I start a LinkedIn newsletter\", \"grow my following\", \"90-day plan\". Validates the positioning brief, sizes the week against real hours and refuses a plan that will not survive week five, and gates a newsletter against eligibility and a six-month cadence commitment."
},
{
"name": "local-seo-manager",
"source": "../../marketing-skill/skills/local-seo-manager",
@ -2184,7 +2232,7 @@
"description": "Software engineering and technical skills"
},
"engineering-advanced": {
"count": 90,
"count": 92,
"source": "../../engineering",
"description": "Advanced engineering skills - agents, RAG, MCP, CI/CD, databases, observability"
},
@ -2194,7 +2242,7 @@
"description": "Financial analysis, valuation, and forecasting skills"
},
"marketing": {
"count": 50,
"count": 56,
"source": "../../marketing-skill",
"description": "Marketing, content, and demand generation skills"
},

View file

@ -0,0 +1 @@
../../engineering/deep-learning-book/skills/deep-learning-book

View file

@ -0,0 +1 @@
../../marketing/linkedin/skills/linkedin-analytics

View file

@ -0,0 +1 @@
../../marketing/linkedin/skills/linkedin-content

View file

@ -0,0 +1 @@
../../marketing/linkedin/skills/linkedin-engagement

View file

@ -0,0 +1 @@
../../marketing/linkedin/skills/linkedin-profile

View file

@ -0,0 +1 @@
../../marketing/linkedin/skills/linkedin-skills

View file

@ -0,0 +1 @@
../../marketing/linkedin/skills/linkedin-strategy

View file

@ -0,0 +1 @@
../../engineering/spinning-up-deep-rl/skills/spinning-up-deep-rl

View file

@ -1,7 +1,7 @@
{
"version": "1.0.0",
"name": "gemini-cli-skills",
"total_skills": 430,
"total_skills": 436,
"skills": [
{
"name": "README",
@ -1793,6 +1793,36 @@
"category": "marketing-top-level",
"description": "Generates a premium single-page HTML landing page with 3D CSS animations, GSAP scroll effects, and mouse-parallax depth. Forcing intake (product + elevator pitch, audience register, brand overrides, tone) locks down positioning before any copy or markup is written, so the page reflects the actual product rather than generic boilerplate. Use whenever the user says 'landing for X', 'create a landing page', 'build a landing page', 'make a landing page for X', 'I need a web page for Y', or provides product/service details and wants a polished website. Also triggers on 'promotional page', 'product page', 'one-pager', 'web presence', 'sales page'. Outputs a single self-contained HTML file (Claude Code) or HTML artifact (Claude.ai). Supports configurable brand colors via CSS custom property overrides."
},
{
"name": "linkedin-analytics",
"category": "marketing-top-level",
"description": "Use when someone wants to understand their own LinkedIn numbers \u2014 which posts worked, why reach dropped, whether a pattern is real, or how to test a hypothesis. Triggers on \"why did my reach drop\", \"what's working on my LinkedIn\", \"analyze my posts\", \"do carousels do better for me\", \"should I test this\", \"LinkedIn analytics\". Reads your own exported post data, reports medians and outlier bands, tests candidate patterns against a permutation null, and sizes a real experiment \u2014 refusing to conclude anything below 10 posts."
},
{
"name": "linkedin-content",
"category": "marketing-top-level",
"description": "Use when someone wants to write, edit, or lint a LinkedIn post \u2014 a story, how-to, opinion piece, carousel script, video script, or poll \u2014 or wants an article, talk, or transcript repurposed into posts. Triggers on \"write a LinkedIn post\", \"is this hook any good\", \"review my post\", \"turn this into LinkedIn posts\", \"carousel\", \"what format should this be\". Lints posts 0-100 on mechanics, hook, integrity, and accessibility; picks the format the material actually supports; and splits long sources into standalone units with a reuse ledger."
},
{
"name": "linkedin-engagement",
"category": "marketing-top-level",
"description": "Use when someone wants to grow reach through comments, replies, groups, or outreach on LinkedIn \u2014 a commenting roster, a connection request note, a DM or InMail, a networking plan, or a check on whether their outreach volume is safe. Triggers on \"who should I engage with\", \"write a connection request\", \"cold DM\", \"LinkedIn outreach\", \"networking strategy\", \"how many invites can I send\". Builds a weekly comment roster inside a real time budget, assembles one message at a time and refuses templates, and caps volume against LinkedIn's limits. Nothing is ever sent."
},
{
"name": "linkedin-profile",
"category": "marketing-top-level",
"description": "Use when someone wants their LinkedIn profile audited or rewritten \u2014 headline, About section, experience bullets, Featured, banner, recommendations \u2014 or says \"fix my headline\", \"my profile gets views but nothing happens\", \"optimize my LinkedIn profile\", \"what should my About section say\". Scores the headline on five dimensions, audits the whole profile 0-100 and ranks fixes by points per hour, and assembles an About section that survives the \"\u2026see more\" fold."
},
{
"name": "linkedin-skills",
"category": "marketing-top-level",
"description": "Use when someone wants to grow an organic LinkedIn presence \u2014 a content strategy for a career change or consulting or thought leadership, a rewritten profile or headline, post drafts and hooks, a posting cadence or newsletter plan, connection notes and outreach, a commenting strategy, repurposing an article or talk into posts, or a read on why their reach dropped. Triggers on \"grow my LinkedIn\", \"fix my headline\", \"write a LinkedIn post\", \"what should I post about\", \"LinkedIn strategy\", \"connection request\", \"my reach dropped\". Forks context to route to one of five sub-skills, and refuses automation, scraping, pods, and bulk DMs before any drafting starts."
},
{
"name": "linkedin-strategy",
"category": "marketing-top-level",
"description": "Use when someone needs a LinkedIn plan rather than a post \u2014 content pillars, positioning for a career change or consulting or thought leadership, a sustainable posting cadence, or a newsletter decision. Triggers on \"what should I post about\", \"how often should I post\", \"LinkedIn content strategy\", \"should I start a LinkedIn newsletter\", \"grow my following\", \"90-day plan\". Validates the positioning brief, sizes the week against real hours and refuses a plan that will not survive week five, and gates a newsletter against eligibility and a six-month cadence commitment."
},
{
"name": "agile-product-owner",
"category": "product",
@ -2208,7 +2238,7 @@
"description": "Marketing resources"
},
"marketing-top-level": {
"count": 1,
"count": 7,
"description": "Marketing-top-level resources"
},
"product": {

View file

@ -0,0 +1 @@
../../../marketing/linkedin/skills/linkedin-analytics/SKILL.md

View file

@ -0,0 +1 @@
../../../marketing/linkedin/skills/linkedin-content/SKILL.md

View file

@ -0,0 +1 @@
../../../marketing/linkedin/skills/linkedin-engagement/SKILL.md

View file

@ -0,0 +1 @@
../../../marketing/linkedin/skills/linkedin-profile/SKILL.md

View file

@ -0,0 +1 @@
../../../marketing/linkedin/skills/linkedin-skills/SKILL.md

View file

@ -0,0 +1 @@
../../../marketing/linkedin/skills/linkedin-strategy/SKILL.md

View file

@ -0,0 +1 @@
../../../../engineering/agent-memory/skills/agent-memory

View file

@ -0,0 +1 @@
../../../../engineering/hivemind

View file

@ -0,0 +1 @@
../../../../engineering/skill-doctor/skills/skill-doctor

View file

@ -0,0 +1 @@
../../../../marketing/linkedin/skills/linkedin-analytics

View file

@ -0,0 +1 @@
../../../../marketing/linkedin/skills/linkedin-content

View file

@ -0,0 +1 @@
../../../../marketing/linkedin/skills/linkedin-engagement

View file

@ -0,0 +1 @@
../../../../marketing/linkedin/skills/linkedin-profile

View file

@ -0,0 +1 @@
../../../../marketing/linkedin/skills/linkedin-skills

View file

@ -0,0 +1 @@
../../../../marketing/linkedin/skills/linkedin-strategy

View file

@ -1,6 +1,6 @@
{
"source": "claude-code-skills",
"total_skills": 353,
"total_skills": 362,
"domains": {
"engineering": [
{
@ -198,6 +198,11 @@
"description": "Turn any domain folder of skills into a bounded agentic loop: compile a goal into a verifiable task plan, execute tasks with the domain's own tools, verify every task with machine-run checks, retry with caps, escalate to a human when budgets exhaust, and refuse to close until everything is verified or explicitly waived. Use when you want an agent or subagent to pick up a goal and drive it to a verified close across one of this repo's 18 domains ('run this goal through the engineering harness', 'set up an agentic loop for marketing work', 'make the finance domain self-verifying'). NOT for authoring Claude Code Workflow-tool .js scripts (workflow-builder), N-agent tournaments on one task (agenthub), single-file metric optimization (autoresearch-agent), or discovering published loop recipes (loop-library).",
"path": "engineering/agent-harness"
},
{
"name": "agent-memory",
"description": "Use when a project's CLAUDE.md has grown past what anyone reads and you want the agent to learn durable facts from its own sessions instead \u2014 or when asking why the agent keeps re-learning the same correction, why a remembered rule is wrong, or where a memory line came from. Implements a four-tier store (L0 transcripts / L1 candidates / L2 project context / L3 stable persona) where promotion is earned by recurrence across sessions and days, never by one confident statement, and nothing reaches a committed file without a human adopting it.",
"path": "engineering/agent-memory"
},
{
"name": "agenthub",
"description": "Multi-agent collaboration plugin that spawns N parallel subagents competing on the same task via git worktree isolation. Agents work independently, results are evaluated by metric or LLM judge, and the best branch is merged. Use when: user wants multiple approaches tried in parallel \u2014 code optimization, content variation, research exploration, or any task that benefits from parallel competition. Requires: a git repo.",
@ -348,6 +353,11 @@
"description": "Helm chart development agent skill and plugin for Claude Code, Codex, Gemini CLI, Cursor, OpenClaw \u2014 chart scaffolding, values design, template patterns, dependency management, security hardening, and chart testing. Use when: user wants to create or improve Helm charts, design values.yaml files, implement template helpers, audit chart security (RBAC, network policies, pod security), manage subcharts, or run helm lint/test.",
"path": "engineering/helm-chart-builder"
},
{
"name": "hivemind",
"description": "Orchestrate free opencode workers from Claude Code to cut token costs. Use when delegating grunt work to a single worker or a parallel swarm (scout/coder/tester) with worktree isolation, benchmarking against opencode, or when the user says \"spawn a worker\", \"swarm\", \"delegate to opencode\", or \"/oc\".",
"path": "engineering/hivemind"
},
{
"name": "human-gate",
"description": "Runs the human-verification lane of an agent loop, and proves review happened before work is called done. Builds a single-file HTML review page, collects batched feedback as a structured artifact instead of chat prose, and runs a gate that refuses to close while a BLOCKER is open, the reviewer is unnamed, or nobody has reviewed at all. Use when a plan, spec, RFC, report, landing page, migration, or any irreversible action needs human sign-off before shipping, or on requests such as 'get sign-off', 'have someone check this', 'hold until reviewed', 'needs approval first'. NOT for making AI text sound human (use content-humanizer or behuman). NOT for reviewing code diffs (use md-review or code-reviewer).",
@ -393,6 +403,11 @@
"description": "PreToolUse security-anti-pattern hook for Claude Code. Catches 12 common security risks (command injection, XSS, SQL injection, unsafe deserialization, GitHub Actions workflow injection, eval/new Function code injection) BEFORE the Edit/Write/MultiEdit operation completes. Session-state caching prevents duplicate warnings on the same file+rule combo. Stdlib only \u2014 no dependencies. Use when you want a safety net during Claude Code sessions that touch security-sensitive code (auth, payments, user input handling, IaC). Disable with ENABLE_SECURITY_REMINDER=0 if you need to perform a verified-safe operation that would otherwise trip a pattern. Triggers \u2014 \"add security hook\", \"block unsafe code\", \"detect command injection before write\", \"prevent SQL injection patterns\", \"security warning hook\".",
"path": "engineering/security-guidance"
},
{
"name": "skill-doctor",
"description": "Use when the user wants their agent setup graded from real conversation history, asks which installed skills are actually working, or wants evidence-backed skill edits \u2014 scores recent local Claude Code / Codex sessions against efficiency and code-quality rubrics, then drafts skill changes gated by a deterministic aggregator and renders one local shareable report.",
"path": "engineering/skill-doctor"
},
{
"name": "skillopt-sleep",
"description": "Use when the user wants their Claude agent to self-improve from past usage, asks about a nightly/offline 'sleep' or 'dream' cycle, memory/skill consolidation, or says things like 'make my agent better the more I use it', 'review my past sessions', 'learn my preferences', 'consolidate what you learned', 'run the sleep cycle', or wants to schedule offline self-optimization. Drives the skillopt_sleep engine: harvest past sessions -> mine recurring tasks -> replay offline -> consolidate validated CLAUDE.md and SKILL.md behind a held-out gate.",
@ -1537,6 +1552,36 @@
"name": "landing",
"description": "Generates a premium single-page HTML landing page with 3D CSS animations, GSAP scroll effects, and mouse-parallax depth. Forcing intake (product + elevator pitch, audience register, brand overrides, tone) locks down positioning before any copy or markup is written, so the page reflects the actual product rather than generic boilerplate. Use whenever the user says 'landing for X', 'create a landing page', 'build a landing page', 'make a landing page for X', 'I need a web page for Y', or provides product/service details and wants a polished website. Also triggers on 'promotional page', 'product page', 'one-pager', 'web presence', 'sales page'. Outputs a single self-contained HTML file (Claude Code) or HTML artifact (Claude.ai). Supports configurable brand colors via CSS custom property overrides.",
"path": "marketing/landing"
},
{
"name": "linkedin-analytics",
"description": "Use when someone wants to understand their own LinkedIn numbers \u2014 which posts worked, why reach dropped, whether a pattern is real, or how to test a hypothesis. Triggers on \"why did my reach drop\", \"what's working on my LinkedIn\", \"analyze my posts\", \"do carousels do better for me\", \"should I test this\", \"LinkedIn analytics\". Reads your own exported post data, reports medians and outlier bands, tests candidate patterns against a permutation null, and sizes a real experiment \u2014 refusing to conclude anything below 10 posts.",
"path": "marketing/linkedin-analytics"
},
{
"name": "linkedin-content",
"description": "Use when someone wants to write, edit, or lint a LinkedIn post \u2014 a story, how-to, opinion piece, carousel script, video script, or poll \u2014 or wants an article, talk, or transcript repurposed into posts. Triggers on \"write a LinkedIn post\", \"is this hook any good\", \"review my post\", \"turn this into LinkedIn posts\", \"carousel\", \"what format should this be\". Lints posts 0-100 on mechanics, hook, integrity, and accessibility; picks the format the material actually supports; and splits long sources into standalone units with a reuse ledger.",
"path": "marketing/linkedin-content"
},
{
"name": "linkedin-engagement",
"description": "Use when someone wants to grow reach through comments, replies, groups, or outreach on LinkedIn \u2014 a commenting roster, a connection request note, a DM or InMail, a networking plan, or a check on whether their outreach volume is safe. Triggers on \"who should I engage with\", \"write a connection request\", \"cold DM\", \"LinkedIn outreach\", \"networking strategy\", \"how many invites can I send\". Builds a weekly comment roster inside a real time budget, assembles one message at a time and refuses templates, and caps volume against LinkedIn's limits. Nothing is ever sent.",
"path": "marketing/linkedin-engagement"
},
{
"name": "linkedin-profile",
"description": "Use when someone wants their LinkedIn profile audited or rewritten \u2014 headline, About section, experience bullets, Featured, banner, recommendations \u2014 or says \"fix my headline\", \"my profile gets views but nothing happens\", \"optimize my LinkedIn profile\", \"what should my About section say\". Scores the headline on five dimensions, audits the whole profile 0-100 and ranks fixes by points per hour, and assembles an About section that survives the \"\u2026see more\" fold.",
"path": "marketing/linkedin-profile"
},
{
"name": "linkedin-skills",
"description": "Use when someone wants to grow an organic LinkedIn presence \u2014 a content strategy for a career change or consulting or thought leadership, a rewritten profile or headline, post drafts and hooks, a posting cadence or newsletter plan, connection notes and outreach, a commenting strategy, repurposing an article or talk into posts, or a read on why their reach dropped. Triggers on \"grow my LinkedIn\", \"fix my headline\", \"write a LinkedIn post\", \"what should I post about\", \"LinkedIn strategy\", \"connection request\", \"my reach dropped\". Forks context to route to one of five sub-skills, and refuses automation, scraping, pods, and bulk DMs before any drafting starts.",
"path": "marketing/linkedin-skills"
},
{
"name": "linkedin-strategy",
"description": "Use when someone needs a LinkedIn plan rather than a post \u2014 content pillars, positioning for a career change or consulting or thought leadership, a sustainable posting cadence, or a newsletter decision. Triggers on \"what should I post about\", \"how often should I post\", \"LinkedIn content strategy\", \"should I start a LinkedIn newsletter\", \"grow my following\", \"90-day plan\". Validates the positioning brief, sizes the week against real hours and refuses a plan that will not survive week five, and gates a newsletter against eligibility and a six-month cadence commitment.",
"path": "marketing/linkedin-strategy"
}
],
"research": [

View file

@ -0,0 +1 @@
../../../../engineering/agent-memory/skills/agent-memory

View file

@ -0,0 +1 @@
../../../../engineering/hivemind

View file

@ -0,0 +1 @@
../../../../engineering/skill-doctor/skills/skill-doctor

View file

@ -0,0 +1 @@
../../../../marketing/linkedin/skills/linkedin-analytics

View file

@ -0,0 +1 @@
../../../../marketing/linkedin/skills/linkedin-content

View file

@ -0,0 +1 @@
../../../../marketing/linkedin/skills/linkedin-engagement

View file

@ -0,0 +1 @@
../../../../marketing/linkedin/skills/linkedin-profile

View file

@ -0,0 +1 @@
../../../../marketing/linkedin/skills/linkedin-skills

View file

@ -0,0 +1 @@
../../../../marketing/linkedin/skills/linkedin-strategy

View file

@ -1,7 +1,7 @@
{
"source": "claude-code-skills",
"layout": "nested",
"total_skills": 353,
"total_skills": 362,
"domains": {
"engineering": [
{
@ -199,6 +199,11 @@
"description": "Turn any domain folder of skills into a bounded agentic loop: compile a goal into a verifiable task plan, execute tasks with the domain's own tools, verify every task with machine-run checks, retry with caps, escalate to a human when budgets exhaust, and refuse to close until everything is verified or explicitly waived. Use when you want an agent or subagent to pick up a goal and drive it to a verified close across one of this repo's 18 domains ('run this goal through the engineering harness', 'set up an agentic loop for marketing work', 'make the finance domain self-verifying'). NOT for authoring Claude Code Workflow-tool .js scripts (workflow-builder), N-agent tournaments on one task (agenthub), single-file metric optimization (autoresearch-agent), or discovering published loop recipes (loop-library).",
"path": "engineering/agent-harness"
},
{
"name": "agent-memory",
"description": "Use when a project's CLAUDE.md has grown past what anyone reads and you want the agent to learn durable facts from its own sessions instead \u2014 or when asking why the agent keeps re-learning the same correction, why a remembered rule is wrong, or where a memory line came from. Implements a four-tier store (L0 transcripts / L1 candidates / L2 project context / L3 stable persona) where promotion is earned by recurrence across sessions and days, never by one confident statement, and nothing reaches a committed file without a human adopting it.",
"path": "engineering/agent-memory"
},
{
"name": "agenthub",
"description": "Multi-agent collaboration plugin that spawns N parallel subagents competing on the same task via git worktree isolation. Agents work independently, results are evaluated by metric or LLM judge, and the best branch is merged. Use when: user wants multiple approaches tried in parallel \u2014 code optimization, content variation, research exploration, or any task that benefits from parallel competition. Requires: a git repo.",
@ -349,6 +354,11 @@
"description": "Helm chart development agent skill and plugin for Claude Code, Codex, Gemini CLI, Cursor, OpenClaw \u2014 chart scaffolding, values design, template patterns, dependency management, security hardening, and chart testing. Use when: user wants to create or improve Helm charts, design values.yaml files, implement template helpers, audit chart security (RBAC, network policies, pod security), manage subcharts, or run helm lint/test.",
"path": "engineering/helm-chart-builder"
},
{
"name": "hivemind",
"description": "Orchestrate free opencode workers from Claude Code to cut token costs. Use when delegating grunt work to a single worker or a parallel swarm (scout/coder/tester) with worktree isolation, benchmarking against opencode, or when the user says \"spawn a worker\", \"swarm\", \"delegate to opencode\", or \"/oc\".",
"path": "engineering/hivemind"
},
{
"name": "human-gate",
"description": "Runs the human-verification lane of an agent loop, and proves review happened before work is called done. Builds a single-file HTML review page, collects batched feedback as a structured artifact instead of chat prose, and runs a gate that refuses to close while a BLOCKER is open, the reviewer is unnamed, or nobody has reviewed at all. Use when a plan, spec, RFC, report, landing page, migration, or any irreversible action needs human sign-off before shipping, or on requests such as 'get sign-off', 'have someone check this', 'hold until reviewed', 'needs approval first'. NOT for making AI text sound human (use content-humanizer or behuman). NOT for reviewing code diffs (use md-review or code-reviewer).",
@ -394,6 +404,11 @@
"description": "PreToolUse security-anti-pattern hook for Claude Code. Catches 12 common security risks (command injection, XSS, SQL injection, unsafe deserialization, GitHub Actions workflow injection, eval/new Function code injection) BEFORE the Edit/Write/MultiEdit operation completes. Session-state caching prevents duplicate warnings on the same file+rule combo. Stdlib only \u2014 no dependencies. Use when you want a safety net during Claude Code sessions that touch security-sensitive code (auth, payments, user input handling, IaC). Disable with ENABLE_SECURITY_REMINDER=0 if you need to perform a verified-safe operation that would otherwise trip a pattern. Triggers \u2014 \"add security hook\", \"block unsafe code\", \"detect command injection before write\", \"prevent SQL injection patterns\", \"security warning hook\".",
"path": "engineering/security-guidance"
},
{
"name": "skill-doctor",
"description": "Use when the user wants their agent setup graded from real conversation history, asks which installed skills are actually working, or wants evidence-backed skill edits \u2014 scores recent local Claude Code / Codex sessions against efficiency and code-quality rubrics, then drafts skill changes gated by a deterministic aggregator and renders one local shareable report.",
"path": "engineering/skill-doctor"
},
{
"name": "skillopt-sleep",
"description": "Use when the user wants their Claude agent to self-improve from past usage, asks about a nightly/offline 'sleep' or 'dream' cycle, memory/skill consolidation, or says things like 'make my agent better the more I use it', 'review my past sessions', 'learn my preferences', 'consolidate what you learned', 'run the sleep cycle', or wants to schedule offline self-optimization. Drives the skillopt_sleep engine: harvest past sessions -> mine recurring tasks -> replay offline -> consolidate validated CLAUDE.md and SKILL.md behind a held-out gate.",
@ -1538,6 +1553,36 @@
"name": "landing",
"description": "Generates a premium single-page HTML landing page with 3D CSS animations, GSAP scroll effects, and mouse-parallax depth. Forcing intake (product + elevator pitch, audience register, brand overrides, tone) locks down positioning before any copy or markup is written, so the page reflects the actual product rather than generic boilerplate. Use whenever the user says 'landing for X', 'create a landing page', 'build a landing page', 'make a landing page for X', 'I need a web page for Y', or provides product/service details and wants a polished website. Also triggers on 'promotional page', 'product page', 'one-pager', 'web presence', 'sales page'. Outputs a single self-contained HTML file (Claude Code) or HTML artifact (Claude.ai). Supports configurable brand colors via CSS custom property overrides.",
"path": "marketing/landing"
},
{
"name": "linkedin-analytics",
"description": "Use when someone wants to understand their own LinkedIn numbers \u2014 which posts worked, why reach dropped, whether a pattern is real, or how to test a hypothesis. Triggers on \"why did my reach drop\", \"what's working on my LinkedIn\", \"analyze my posts\", \"do carousels do better for me\", \"should I test this\", \"LinkedIn analytics\". Reads your own exported post data, reports medians and outlier bands, tests candidate patterns against a permutation null, and sizes a real experiment \u2014 refusing to conclude anything below 10 posts.",
"path": "marketing/linkedin-analytics"
},
{
"name": "linkedin-content",
"description": "Use when someone wants to write, edit, or lint a LinkedIn post \u2014 a story, how-to, opinion piece, carousel script, video script, or poll \u2014 or wants an article, talk, or transcript repurposed into posts. Triggers on \"write a LinkedIn post\", \"is this hook any good\", \"review my post\", \"turn this into LinkedIn posts\", \"carousel\", \"what format should this be\". Lints posts 0-100 on mechanics, hook, integrity, and accessibility; picks the format the material actually supports; and splits long sources into standalone units with a reuse ledger.",
"path": "marketing/linkedin-content"
},
{
"name": "linkedin-engagement",
"description": "Use when someone wants to grow reach through comments, replies, groups, or outreach on LinkedIn \u2014 a commenting roster, a connection request note, a DM or InMail, a networking plan, or a check on whether their outreach volume is safe. Triggers on \"who should I engage with\", \"write a connection request\", \"cold DM\", \"LinkedIn outreach\", \"networking strategy\", \"how many invites can I send\". Builds a weekly comment roster inside a real time budget, assembles one message at a time and refuses templates, and caps volume against LinkedIn's limits. Nothing is ever sent.",
"path": "marketing/linkedin-engagement"
},
{
"name": "linkedin-profile",
"description": "Use when someone wants their LinkedIn profile audited or rewritten \u2014 headline, About section, experience bullets, Featured, banner, recommendations \u2014 or says \"fix my headline\", \"my profile gets views but nothing happens\", \"optimize my LinkedIn profile\", \"what should my About section say\". Scores the headline on five dimensions, audits the whole profile 0-100 and ranks fixes by points per hour, and assembles an About section that survives the \"\u2026see more\" fold.",
"path": "marketing/linkedin-profile"
},
{
"name": "linkedin-skills",
"description": "Use when someone wants to grow an organic LinkedIn presence \u2014 a content strategy for a career change or consulting or thought leadership, a rewritten profile or headline, post drafts and hooks, a posting cadence or newsletter plan, connection notes and outreach, a commenting strategy, repurposing an article or talk into posts, or a read on why their reach dropped. Triggers on \"grow my LinkedIn\", \"fix my headline\", \"write a LinkedIn post\", \"what should I post about\", \"LinkedIn strategy\", \"connection request\", \"my reach dropped\". Forks context to route to one of five sub-skills, and refuses automation, scraping, pods, and bulk DMs before any drafting starts.",
"path": "marketing/linkedin-skills"
},
{
"name": "linkedin-strategy",
"description": "Use when someone needs a LinkedIn plan rather than a post \u2014 content pillars, positioning for a career change or consulting or thought leadership, a sustainable posting cadence, or a newsletter decision. Triggers on \"what should I post about\", \"how often should I post\", \"LinkedIn content strategy\", \"should I start a LinkedIn newsletter\", \"grow my following\", \"90-day plan\". Validates the positioning brief, sizes the week against real hours and refuses a plan that will not survive week five, and gates a newsletter against eligibility and a six-month cadence commitment.",
"path": "marketing/linkedin-strategy"
}
],
"research": [

View file

@ -5,6 +5,149 @@ All notable changes to the Claude Skills Library will be documented in this file
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added — engineering/spinning-up-deep-rl: the first book compiled by book-to-skill
Knowledge-base plugin compiled end-to-end by `engineering/book-to-skill` from OpenAI's
[Spinning Up in Deep RL](https://spinningup.openai.com/) (MIT, Copyright (c) 2018 OpenAI;
primarily developed by Joshua Achiam). 20 chapters, a glossary, a patterns file and a
decision cheatsheet, behind a 2,101-token resident core.
- **The full pipeline, not a hand-write.** `openai/spinningup` cloned, its `docs/`
reStructuredText tree (38 files, ~37k words, ~49K tokens) run through
`extract_document.py --mode technical` → analysis → chapter files → supporting files →
master `SKILL.md``book_skill_validator.py``skill_plugin_emitter.py`. The validator
passes clean in `--strict` mode and every file is inside budget.
- **Rights basis `open-license`, stated and honoured.** The emitter's Step-11 gate refuses a
shareable package without one. MIT permits derivative distribution; upstream's notice is
reproduced in full in the plugin's `LICENSE` beside this package's own, and `README.md`
names the source, the author and the source's frozen version.
- **Structure follows the source's own `toctree`.** User documentation (ch01-06), Introduction
to RL Parts 1-3 (ch07-09), resources — the researcher essay, key papers, exercises,
benchmarks (ch10-13), one chapter per algorithm in lineage order (ch14-19: VPG → TRPO → PPO,
DDPG → TD3 → SAC), and the logger / MPI / ExperimentGrid utilities (ch20).
- **The cheatsheet carries the judgment a glossary cannot** — the under-5-minute debug
turnaround, the 3-seed minimum (10+ to be thorough), family-specific benchmark network
defaults, and Spinning Up's own parity disclosure: DDPG/TD3/SAC are research-grade,
VPG/TRPO/PPO are not, and the docs say to use OpenAI Baselines for those.
- **Counters:** skills 387 → 388; agents 117 → 118; commands 149 → 150; plugins 98 → 99.
Tools and references unchanged by this plugin — a compiled knowledge base ships notes, not
scripts. (These sit on top of `deep-learning-book`, which merged into `dev` first; the
derived totals are 388 skills / 727 tools / 842 references / 118 agents / 150 commands /
99 plugins.)
### Fixed — book-to-skill's plugin emitter produced manifests this repo's CI rejects
`skill_plugin_emitter.py` wrote its whole `source` provenance block into `plugin.json`, with an
inline comment asserting that `source` and `attribution` were approved extension fields. That had
been true and no longer was: Claude Code rejects an entire manifest on any unrecognized key
(issue #954), and `scripts/check_plugin_json.py` hard-fails such a manifest, pointing at
`.claude-plugin/authoring-notes.json` instead. Every package the emitter produced therefore failed
the blocking CI gate the moment it was committed — a defect at the very last step of the pipeline,
which is why it had gone unnoticed. `_plugin_manifest()` now emits spec fields only and a new
`_authoring_notes()` writes the sidecar. Recorded as deviation 26 in
`engineering/book-to-skill/README.md`. The printed `marketplace.json` snippet is unchanged: `source`
is a valid key there, which is how it leaked into the manifest originally.
### Added — engineering/deep-learning-book: a companion to the free Deep Learning textbook
New `engineering/deep-learning-book/` plugin: a study companion for *Deep Learning* by
Goodfellow, Bengio & Courville (MIT Press, 2016), free to read at deeplearningbook.org.
One skill, 4 stdlib-only tools, 4 references, 3 assets, 1 agent, 3 commands.
- **Companion, not compilation — and that was the design decision.** `book-to-skill`'s
rights gate refuses a `shareable` package without `public-domain` / `open-license` /
`internal-docs` / `author-permission`, none of which applies to an MIT Press title whose
own site states the HTML-only format exists as a friction against copying under the
authors' contract; its rights reference lists publishing a compiled skill of a copyrighted
book to a public marketplace under **Do not**, and its hard rule 1 forbids scraping a book
from the web. So nothing here reproduces the book: every chapter file is original
synthesis linking to the official free chapter, and the organizing structure is the
published table of contents. **The rule this sets:** convert a copyrighted work into a
companion that indexes and updates the source, never a compilation that reproduces it.
- **The compiled-skill shape, validated by the compiler's own gate.** Master `SKILL.md`
(~2.0k tokens, chapter index + topic index), `chapters/ch01..ch20`, `glossary.md`,
`patterns.md`, `cheatsheet.md` — passes `book_skill_validator.py` clean with every file
inside `token_budget_estimator.py`'s caps.
- **The 2016→2026 delta layer is the differentiator.** A compilation freezes a source at its
publication date; this one dates it. Every chapter carries "What changed after 2016", and
`references/book_to_2026_delta.md` gives five corrections with primary citations and
per-claim confidence: double descent qualifying Ch 5's U-curve, AdamW splitting weight
decay from L2, transformers displacing Ch 10's recurrence, diffusion growing out of Ch 18's
score matching, and self-supervised learning vindicating Ch 15 while replacing its methods.
Two contested claims are marked contested rather than propagated; two named as folklore.
Stated rule: **the conflict is almost always in the recommendation, not the analysis.**
- **Four tools, each with a real refusal.** `reading_path_planner.py` (prerequisite closure
over the book's actual dependency graph, priced in weeks; exit 3 naming what covers an
out-of-scope goal, exit 4 with forcing questions when unroutable; ties break on keyword
specificity, not alphabetically); `training_diagnostics.py` (Ch 11's rules in priority
order, so a NaN is never reported as overfitting; exit 4 rather than diagnosing with no
instruments); `capacity_planner.py` (regularization ladder in cost order with "shrink the
model" ranked **last** in the overparameterized regime; exit 4 on a val-below-train split);
`model_arithmetic.py` (params/FLOPs/activation memory for conv, linear, position-wise
linear, MHA and LSTM/GRU stacks; exit 5 naming the layer whose shapes do not connect).
- `cs-deep-learning-tutor` agent; `/cs:deep-learning`, `/cs:dl-reading-path`,
`/cs:dl-diagnose`. **Counters:** skills 386 → 387; tools 723 → 727; refs 838 → 842;
agents 116 → 117; commands 146 → 149; plugins 97 → 98.
### Added — marketing/linkedin: organic LinkedIn presence with the platform rules in code
New `marketing/linkedin/` plugin, answering
[discussion #934](https://github.com/alirezarezvani/claude-skills/discussions/934), which
asked for a strategic assistant for growing a LinkedIn presence organically rather than a
post generator. Six skills, 17 stdlib-only tools, 15 references, 2 agents, 8 commands.
- **The design constraint is the differentiator.** The plugin holds no LinkedIn credentials,
makes no API calls, scrapes nothing, and sends nothing — automated posting, connecting,
commenting, and liking are prohibited by LinkedIn's User Agreement §8.2, and a restricted
account ends a compounding asset. `linkedin_policy_gate.py` runs before any drafting and
refuses seven classes of request (automation, scraping, engagement pods, bulk messaging,
fake identity, fabricated proof, named third-party automation platforms), each with the
policy anchor and a **compliant substitute** — the gate never just says no.
- **`linkedin-skills`** (orchestrator, `context: fork`) — policy gate + deterministic
five-lane router (route 0 / ask 2 / no-signal 3) with cross-lane prerequisites.
- **`linkedin-profile`** — headline scored on audience/outcome/proof/searchability/clarity
against the 220-char cap and the ~60-char front-load window; whole-profile audit across 14
weighted checks with fixes ranked by **points per hour** and a first-hour plan; About
builder that refuses a fold cutting mid-sentence or carrying no audience and no proof.
- **`linkedin-strategy`** — positioning brief validator (six real objectives, an audience
specific enough to exclude someone, 2-4 proof-backed pillars, a **mandatory exclusion
list**); cadence planner that prices the week in minutes and returns a comment-only plan
below a 90-minute floor; newsletter gate on LinkedIn's published 150-follower evaluation
threshold plus six-month cadence cost, with a stop rule written before issue one.
- **`linkedin-content`** — post linter across mechanics / hook / integrity / accessibility,
blocking on the 3,000-char cap, engagement bait, and **Unicode pseudo-bold** (screen
readers announce it as mathematical symbols; search does not index it as words); format
picker over nine native formats; repurpose splitter with a **content-hash reuse ledger**.
- **`linkedin-engagement`** — comment roster capped at two appearances per account per week;
message builder that refuses a template without a person-specific line and refuses an ask
in a first-touch connection note; volume guard that refuses above 40 invitations a day as
an automation plan regardless of intent.
- **`linkedin-analytics`** — median/MAD describer with Tukey bands (a mean describes a
distribution none of your posts belong to); four-gate permutation pattern miner with
**multiple-comparisons accounting** and mirrored-candidate de-duplication; experiment
planner that reports infeasibility rather than quietly shrinking the effect. Refuses to
conclude anything below 10 posts.
- **Evidence discipline — two widely repeated claims corrected rather than propagated.**
(1) "A personalised connection note triples acceptance (~45% vs ~15%)" is not supported by
the largest samples, which show acceptance close to identical either way (~26.4%); what a
note moves is the **post-accept reply rate** (~5.4% → ~9.4%), which is why the builder
refuses an ask in a first-touch note. (2) The ~19% in-body link reach reduction has never
been confirmed by LinkedIn as a penalty and has a plausible dwell-time explanation, so it
is a warning rather than a blocking finding. Every reference carries per-claim confidence
levels (🟢 LinkedIn-official / 🟡 third-party study / 🔴 folklore).
- All six SKILL.md files are a full **6/6 PASS** on the write-a-skill checklist. Every tool
supports `--help`, `--sample`, and `--output json` with typed exit codes.
- **Counters:** skills 380 → 386; plugins 96 → 97; tools 706 → 723; references 823 → 838;
agents 114 → 116; commands 138 → 146 (verified via `scripts/derive_counters.py --check`).
### Fixed
- Synced three previously-merged skills (`engineering/agent-memory`, `engineering/hivemind`,
`engineering/skill-doctor`) into the `.hermes/` and `.vibe/` mirror trees, which had
drifted behind `.codex/` and `.gemini/`.
## [2.12.0] - 2026-08-24 — consolidated release: 20 domains, 380 skills, full issue-triage sweep
**First tagged release since v2.9.0.** Versions 2.10.02.11.2 were documented in

112
CLAUDE.md

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
# Claude Code Skills & Plugins — Agent Skills for Every Coding Tool
**380 production-ready Claude Code skills, plugins, and agent skills for 13 AI coding tools.**
**388 production-ready Claude Code skills, plugins, and agent skills for 13 AI coding tools.**
The most comprehensive open-source library of Claude Code skills and agent plugins — also works with OpenAI Codex, Gemini CLI, Cursor, and 9 more coding agents. Reusable expertise packages covering engineering, DevOps, marketing (incl. AEO — Answer Engine Optimization for LLM citation), security (PreToolUse hooks), compliance, C-level advisory (incl. founder-mode CFO/CMO/CRO/CPO/COO/CHRO/CISO/GC/CDO/CAIO/CCO/VPE personas + 21 /cs:* slash commands), productivity (capture/email/reflect/weekly-review/deep-work/meetings), an academic research stack (litreview/grants/dossier/patent/syllabus/pulse/notebooklm/deep-research + hybrid router), and enterprise Research Operations (clinical-research/research-finance/market-research/product-research, v2.9.0).
@ -10,10 +10,10 @@ The most comprehensive open-source library of Claude Code skills and agent plugi
[^vibe]: Mistral Vibe is also **BYO-sync tier**: the repo ships a pre-generated `.vibe/skills/claude-skills/` tree, run `./scripts/vibe-install.sh` once locally to install into `~/.vibe/skills/`. Same agentskills.io SKILL.md standard — no format conversion. Docs: <https://docs.mistral.ai/mistral-vibe/agents-skills>.
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow?style=for-the-badge)](https://opensource.org/licenses/MIT)
[![Skills](https://img.shields.io/badge/Skills-380-brightgreen?style=for-the-badge)](#skills-overview)
[![Agents](https://img.shields.io/badge/Agents-114-blue?style=for-the-badge)](#agents)
[![Skills](https://img.shields.io/badge/Skills-388-brightgreen?style=for-the-badge)](#skills-overview)
[![Agents](https://img.shields.io/badge/Agents-118-blue?style=for-the-badge)](#agents)
[![Personas](https://img.shields.io/badge/Personas-7-purple?style=for-the-badge)](#personas)
[![Commands](https://img.shields.io/badge/Commands-138-orange?style=for-the-badge)](#commands)
[![Commands](https://img.shields.io/badge/Commands-150-orange?style=for-the-badge)](#commands)
[![Stars](https://img.shields.io/github/stars/alirezarezvani/claude-skills?style=for-the-badge)](https://github.com/alirezarezvani/claude-skills/stargazers)
[![SkillCheck Validated](https://img.shields.io/badge/SkillCheck-Validated-4c1?style=for-the-badge)](https://getskillcheck.com)
@ -29,7 +29,7 @@ Claude Code skills (also called agent skills or coding agent plugins) are modula
- **Python tools** — 706 CLI scripts (all stdlib-only, zero pip installs)
- **Reference docs** — 823 templates, checklists, and domain-specific knowledge files
**One repo, thirteen platforms.** Works natively as Claude Code plugins, Codex agent skills, Gemini CLI skills, Hermes Agent skills, Mistral Vibe skills, and converts to more tools via `scripts/convert.sh`. All 706 Python tools run anywhere Python runs.
**One repo, thirteen platforms.** Works natively as Claude Code plugins, Codex agent skills, Gemini CLI skills, Hermes Agent skills, Mistral Vibe skills, and converts to more tools via `scripts/convert.sh`. All 727 Python tools run anywhere Python runs.
### Skills vs Agents vs Personas
@ -152,16 +152,16 @@ Run `./scripts/convert.sh --tool all` to generate tool-specific outputs locally.
## Skills Overview
**380 production-ready skills across 20 domains:**
**388 production-ready skills across 20 domains:**
| Domain | Skills | Highlights | Details |
|--------|--------|------------|---------|
| **🔧 Engineering — Core** | 53 | Architecture, frontend, backend, fullstack, QA, DevOps, SecOps, AI/ML, data, Playwright Pro (test gen, flaky fix, migrations), self-improving agent (auto-memory curation), security suite, a11y audit, **named-persona-adversarial-review** (review via named engineering philosophies), **embedded-iot-mentor** (MCU/board selection, firmware-reuse-first, breadboard-MVP discipline) | [engineering-team/](engineering-team/) |
| **⚡ Engineering — POWERFUL** | 91 | Agent designer, RAG architect, database designer, CI/CD builder, security auditor, MCP builder, AgentHub, Helm charts, Terraform, self-eval, llm-wiki, tc-tracker, autoresearch-agent, **reliability portfolio** (feature-flags-architect, kubernetes-operator, chaos-engineering, slo-architect), ship-gate, security-guidance PreToolUse hook, **Matt Pocock skills** (write-a-skill, caveman, grill-me, handoff, grill-with-docs), **zero-hallucination-coder** (Discuss→Map→Decompose→Execute→Verify), **agent-harness** (goal→plan→execute→verify→close loops over any domain), **memory-engineering** (price the memory write path, pick which cost to pay, audit FACT/SKILL/LOG density, gate on a forgetting policy), **skillopt-sleep** (nightly gated self-evolution from real Claude Code sessions, vendored from microsoft/SkillOpt), **book-to-skill** (compile a book, docs folder, or spec collection into a knowledge-base skill, then package it as a plugin), **boost-asio-pro** (async C++ networking — version-gated coroutine/callback styles, strand discipline), **human-gate** (batched human review as a structured artifact + a gate that refuses to close on open blockers), **agent-memory** (four-tier L0-L3 memory ladder over Claude Code hooks; promotion earned by recurrence across sessions and days, redacted or contested claims refuse to promote, nothing reaches CLAUDE.md without a human adopt), **skill-doctor** (grade the agent setup from real session history — rubric-judged, deterministically gated, evidence-traced skill edits) | [engineering/](engineering/) |
| **⚡ Engineering — POWERFUL** | 93 | Agent designer, RAG architect, database designer, CI/CD builder, security auditor, MCP builder, AgentHub, Helm charts, Terraform, self-eval, llm-wiki, tc-tracker, autoresearch-agent, **reliability portfolio** (feature-flags-architect, kubernetes-operator, chaos-engineering, slo-architect), ship-gate, security-guidance PreToolUse hook, **Matt Pocock skills** (write-a-skill, caveman, grill-me, handoff, grill-with-docs), **zero-hallucination-coder** (Discuss→Map→Decompose→Execute→Verify), **agent-harness** (goal→plan→execute→verify→close loops over any domain), **memory-engineering** (price the memory write path, pick which cost to pay, audit FACT/SKILL/LOG density, gate on a forgetting policy), **skillopt-sleep** (nightly gated self-evolution from real Claude Code sessions, vendored from microsoft/SkillOpt), **book-to-skill** (compile a book, docs folder, or spec collection into a knowledge-base skill, then package it as a plugin), **boost-asio-pro** (async C++ networking — version-gated coroutine/callback styles, strand discipline), **human-gate** (batched human review as a structured artifact + a gate that refuses to close on open blockers), **agent-memory** (four-tier L0-L3 memory ladder over Claude Code hooks; promotion earned by recurrence across sessions and days, redacted or contested claims refuse to promote, nothing reaches CLAUDE.md without a human adopt), **skill-doctor** (grade the agent setup from real session history — rubric-judged, deterministically gated, evidence-traced skill edits), **deep-learning-book** (companion to the free Goodfellow/Bengio/Courville textbook — 20 chapter files with a 2016→2026 delta layer, reading-path planner, Ch-11 training diagnostic, capacity planner, FLOP/activation-memory calculator), **spinning-up-deep-rl** (knowledge base compiled from OpenAI's Spinning Up in Deep RL — RL fundamentals, the model-free taxonomy, policy-gradient derivations, and one chapter per reference algorithm) | [engineering/](engineering/) |
| **🎯 Product** | 17 | Product manager, agile PO, strategist, UX researcher, UI design, landing pages, SaaS scaffolder, analytics, experiment designer, discovery, roadmap communicator, code-to-prd, apple-hig-expert | [product-team/](product-team/) |
| **📣 Marketing** | 49 | 8 pods: Content, SEO + AEO (`aeo` — E-E-A-T audit, citation tracking across 5 LLMs) + local (`local-seo-manager` — GBP/NAP/Map-Pack), CRO, Channels, Growth, Intelligence, Sales + `business-name-fit` (cross-cultural naming) + context foundation + orchestration router | [marketing-skill/](marketing-skill/) |
| **🚀 Productivity** | 12 | `capture` (brain-dump-to-action), `email` pair (inbox-setup + inbox-triage), `reflect` (journal), `handoff` (Matt Pocock-inspired), `andreessen` (market-first decision mode), `roast` (5-angle idea panel → GO/RESHAPE/KILL), `fable-goal` (ramble → autonomous /goal prompt), `weekly-review` (GTD loop with refusal gate), `deep-work` (time-blocking + shallow-work budget), `meetings` (cost gate + agenda + action items), `swedish-mentor` (CEFR-leveled Swedish learning paths) | [productivity/](productivity/) |
| **🎨 Marketing (top-level)** | 1 | `landing` — single-file HTML landing-page generator (4 design styles, GSAP patterns, brand palette validator) | [marketing/](marketing/) |
| **🎨 Marketing (top-level)** | 7 | `landing` — single-file HTML landing-page generator (4 design styles, GSAP patterns, brand palette validator); `linkedin` — organic LinkedIn presence with User Agreement §8.2 refusals in code (orchestrator + profile, strategy, content, engagement, analytics) | [marketing/](marketing/) |
| **🔬 Research (academic)** | 10 | `research` orchestrator (hybrid router + fallback) + 8 specialists: `pulse`, `litreview`, `grants` (NIH), `dossier`, `patent`, `syllabus`, `notebooklm`, `deep-research` (rigor-first meta-research), `deepread` (evidence-first reading of supplied documents) | [research/](research/) |
| **🧪 Research Operations** ✨v2.9.0 | 5 | Enterprise/cross-functional research: orchestrator + `clinical-research` (study design), `research-finance` (R&D program finance), `market-research` (sizing/survey/segmentation), `product-research` (user research) — each with onboarding + customization + opt-in autoresearch bridge | [research-ops/](research-ops/) |
| **📋 Project Management** | 9 | Senior PM, scrum master, Jira, Confluence, Atlassian admin, templates + bundled Atlassian Remote MCP | [project-management/](project-management/) |
@ -359,7 +359,7 @@ Yes. Skills work natively with 13 tools: Claude Code, OpenAI Codex, Gemini CLI,
No. We follow semantic versioning and maintain backward compatibility within patch releases. Existing script arguments, plugin source paths, and SKILL.md structures are never changed in patch versions. See the [CHANGELOG](CHANGELOG.md) for details on each release.
**Are the Python tools dependency-free?**
Yes. All 706 Python tools use the standard library only — zero pip installs required. Every skill's CLI entry point is verified to run with `--help` (most skills ship one script per tool; a few, like the vendored `engineering/skillopt-sleep` engine, ship a multi-module package behind a single `python -m` entry point). A few tools — `engineering/book-to-skill`'s document extractors — can *optionally* use third-party parsers for higher-fidelity output, but every format falls back to a standard-library parser and nothing is installed implicitly.
Yes. All 727 Python tools use the standard library only — zero pip installs required. Every skill's CLI entry point is verified to run with `--help` (most skills ship one script per tool; a few, like the vendored `engineering/skillopt-sleep` engine, ship a multi-module package behind a single `python -m` entry point). A few tools — `engineering/book-to-skill`'s document extractors — can *optionally* use third-party parsers for higher-fidelity output, but every format falls back to a standard-library parser and nothing is installed implicitly.
**How do I create my own Claude Code skill?**
Each skill is a folder with a `SKILL.md` (frontmatter + instructions), optional `scripts/`, `references/`, and `assets/`. See the [Skills & Agents Factory](https://github.com/alirezarezvani/claude-code-skills-agents-factory) for a step-by-step guide.

View file

@ -3,6 +3,6 @@
"derived_from": "https://github.com/virgiliojr94/book-to-skill",
"original_author": "virgiliojr94",
"original_license": "MIT",
"derivation_note": "The extraction library (book_to_skill/ — config, exceptions, sanitize, dependencies, utils, and the 7 per-format parsers) is vendored from upstream and carries upstream's multi-format chains, chapter detection across 5 script families, and Unicode/XXE hardening. 25 numbered deviations are recorded in README.md, which is the authoritative list: the workflow was rewritten Claude-Code-first for this repo's conventions, the 3 upstream tools were reworked into 4 argparse CLIs with --help/--sample, install-on-import behaviour was replaced with a report-only default, and Step 11 (plugin emission with a rights gate) plus the validator's budget and index families are additions with no upstream counterpart."
"derivation_note": "The extraction library (book_to_skill/ — config, exceptions, sanitize, dependencies, utils, and the 7 per-format parsers) is vendored from upstream and carries upstream's multi-format chains, chapter detection across 5 script families, and Unicode/XXE hardening. 26 numbered deviations are recorded in README.md, which is the authoritative list: the workflow was rewritten Claude-Code-first for this repo's conventions, the 3 upstream tools were reworked into 4 argparse CLIs with --help/--sample, install-on-import behaviour was replaced with a report-only default, and Step 11 (plugin emission with a rights gate) plus the validator's budget and index families are additions with no upstream counterpart."
}
}

View file

@ -101,7 +101,7 @@ small; just read it."
## Deviations from upstream
**This numbered list is the authoritative record.** `plugin.json`'s
**This numbered list is the authoritative record.** `.claude-plugin/authoring-notes.json`'s
`attribution.derivation_note` summarizes it; if the two ever disagree, this list wins.
**Structural**
@ -245,9 +245,10 @@ small; just read it."
preventing hand-edit mistakes contradicted the manifest beside it); the symlink guard is
backed by a **post-copy re-walk** that deletes the package if a link appeared during the
copy, closing the check-then-act window rather than only narrowing it; and the manifest
carries `source.license_scope` stating that the top-level `license` covers the package
emits `source.license_scope` stating that the top-level `license` covers the package
scaffolding, not the compiled notes — a distinction that previously lived only in README
prose where a tool reading the manifest alone would miss it.
prose where a tool reading the metadata alone would miss it. (Deviation 26 later moved
that whole `source` block out of `plugin.json` and into the sidecar.)
21. **The documented quick-start actually runs.** SKILL.md's copy-paste block referenced
`$WORKDIR` and `$SKILLS_HOME` without ever defining them — following it literally produced
@ -297,6 +298,21 @@ small; just read it."
leaves the victim's contents intact and is replaced by a 0600 file we own. Degrades to the
previous path-based checks on platforms without `dir_fd`/`O_NOFOLLOW` (Windows).
26. **Provenance moved out of `plugin.json` into the sidecar the repo actually allows.**
The manifest builder wrote its whole `source` block (spec, build pattern, source document,
chapter count, distribution, `license_scope`, `rights_basis`) into `plugin.json`, and an
inline comment asserted that `source` and `attribution` were "approved extension fields."
That had been true and no longer was: Claude Code rejects an entire manifest on any
unrecognized key (issue #954), and this repo's own `scripts/check_plugin_json.py` hard-fails
a `plugin.json` carrying either field, pointing at `.claude-plugin/authoring-notes.json`
instead. So every package the emitter produced failed the repo's blocking CI gate the moment
it was committed — a defect that only surfaces at the very last step of the pipeline, which
is why it survived. `_plugin_manifest()` now emits spec fields only, and a new
`_authoring_notes()` writes the `source` block to `.claude-plugin/authoring-notes.json`.
Note that `source` remains a *valid* key in a `marketplace.json` `plugins[]` entry, which is
how it leaked into the manifest in the first place; the printed marketplace snippet is
unchanged and still correct.
---
## Security audit

View file

@ -382,10 +382,23 @@ Emits `<domain>/<slug>/` with `.claude-plugin/plugin.json`, `README.md`,
`skills/<slug>/`, then prints the marketplace entry to register. Drop `--dry-run` to write.
**Rights gate.** The emitter defaults to `--distribution local`, which records
`source.cleared_for_distribution: false` in the manifest. `--distribution shareable` **refuses** unless `--rights` names a basis:
`source.cleared_for_distribution: false` in `.claude-plugin/authoring-notes.json`.
`--distribution shareable` **refuses** unless `--rights` names a basis:
`public-domain`, `open-license`, `internal-docs`, or `author-permission`. Fair use is
deliberately not an option — it is a defence, not a licence, and not this tool's call.
**Attribution is yours to add, by hand, when the source is someone else's work.** The emitter
writes a `source` block — how the skill was built — because that is all it can know; it has
`--source-note` free text and a rights basis, not an upstream URL, author or licence, and a
half-filled `attribution` block is worse than none. So when `--rights` is anything but
`internal-docs`, add an `attribution` block beside it in `authoring-notes.json`
(`derived_from`, `original_author`, `original_license`, `original_copyright`,
`derivation_note` — the shape the rest of this repo uses), and put the upstream licence
notice in the package's `LICENSE` and a credit line in its `README.md`. **That last part is
the obligation:** `authoring-notes.json` is authoring metadata Claude Code never reads, and a
sidecar JSON file is not a licence notice. `engineering/spinning-up-deep-rl` is the worked
example.
The emitter also refuses to wrap a skill with validation errors. Fix the source skill first.
Registration in `.claude-plugin/marketplace.json` stays manual — it is a repo-wide change.

View file

@ -10,7 +10,8 @@ This tool closes that gap. Point it at a generated book skill and it emits the
plugin package this repo's conventions require:
<domain>/<slug>/
.claude-plugin/plugin.json manifest with `./skills/<slug>` + attribution
.claude-plugin/plugin.json manifest, spec fields only (no `source`)
.claude-plugin/authoring-notes.json provenance the manifest may not carry
README.md what the skill knows and where it came from
agents/cs-<slug>.md persona that answers from the book
commands/cs-<slug>.md /cs:<slug> entry point
@ -24,7 +25,8 @@ Rights gate: a book skill built from a copyrighted work is personal study
notes. `--distribution shareable` therefore refuses to emit unless `--rights`
names a basis that permits redistribution. `--distribution local` (the default)
emits with a notice and records `source.cleared_for_distribution: false`
in the manifest.
in `authoring-notes.json`. Provenance never goes in `plugin.json`: Claude Code
rejects the whole manifest on any unrecognized key (issue #954).
Exit codes:
0 package emitted (or --dry-run / --sample completed)
@ -166,13 +168,13 @@ def _assert_no_symlinks(skill_dir: Path) -> None:
def _plugin_manifest(identity: dict, *, domain: str, author: str, author_url: str,
repository: str, distribution: str, rights: str | None,
source_note: str) -> dict:
# Key set and the two approved extension fields (`source`, `attribution`) are
# fixed by scripts/check_plugin_json.py. Anything else — including a
# top-level "private" flag — fails the repo's CI gate, so the distribution
# marker lives inside `source`.
manifest = {
repository: str) -> dict:
# Spec fields ONLY. Claude Code's manifest validator rejects the whole
# plugin.json on any unrecognized key (issue #954), and the repo's own gate
# (scripts/check_plugin_json.py) hard-fails a manifest carrying `source` or
# `attribution`. Provenance therefore goes to the sidecar file the validator
# never reads — see _authoring_notes below.
return {
"name": identity["slug"],
"description": identity["description"],
"version": "1.0.0",
@ -185,31 +187,42 @@ def _plugin_manifest(identity: dict, *, domain: str, author: str, author_url: st
# the manifest sees the distinction that README.md makes in prose.
"license": "MIT",
"skills": [f"./skills/{identity['slug']}"],
"source": {
"spec": "generated by engineering/book-to-skill",
"build_pattern": "book-to-skill conversion: extract -> analyze -> chapter files "
"+ glossary + patterns + cheatsheet -> master SKILL.md",
"distinct_from": "not a hand-authored skill; every claim traces to the source "
"document named below",
"source_document": source_note or identity["title"],
"chapters": identity["chapters"],
"distribution": distribution,
"license_scope": (
"The top-level `license` covers this package's scaffolding only. The "
"compiled notes under skills/ are derived from the source document and "
"carry that work's terms; see source.rights_basis."
),
},
}
def _authoring_notes(identity: dict, *, distribution: str, rights: str | None,
source_note: str) -> dict:
"""Provenance for `.claude-plugin/authoring-notes.json`.
The repo's schema allows exactly two keys here, `source` and `attribution`;
a generated skill's provenance is a `source` block. This file is authoring
metadata that Claude Code's manifest validator never reads, which is
precisely why the fields live here rather than in plugin.json.
"""
source = {
"spec": "generated by engineering/book-to-skill",
"build_pattern": "book-to-skill conversion: extract -> analyze -> chapter files "
"+ glossary + patterns + cheatsheet -> master SKILL.md",
"distinct_from": "not a hand-authored skill; every claim traces to the source "
"document named below",
"source_document": source_note or identity["title"],
"chapters": identity["chapters"],
"distribution": distribution,
"license_scope": (
"plugin.json's top-level `license` covers this package's scaffolding only. "
"The compiled notes under skills/ are derived from the source document and "
"carry that work's terms; see source.rights_basis."
),
}
if rights:
manifest["source"]["rights_basis"] = rights
manifest["source"]["rights_note"] = RIGHTS_BASES[rights]
source["rights_basis"] = rights
source["rights_note"] = RIGHTS_BASES[rights]
if distribution == "local":
# A local package is study notes from a work the user owns. The flag is
# advisory metadata, not enforcement — it exists so a later publish step
# (or a reviewer) can see the package was never cleared for sharing.
manifest["source"]["cleared_for_distribution"] = False
return manifest
source["cleared_for_distribution"] = False
return {"source": source}
def _agent_markdown(identity: dict, domain: str, source_note: str) -> str:
@ -407,10 +420,12 @@ def emit(*, skill_dir: Path, dest_root: Path, domain: str, author: str, author_u
_assert_replaceable(package_root, resolved_dest, skill_dir)
manifest = _plugin_manifest(identity, domain=domain, author=author, author_url=author_url,
repository=repository, distribution=distribution, rights=rights,
source_note=source_note)
repository=repository)
notes = _authoring_notes(identity, distribution=distribution, rights=rights,
source_note=source_note)
files = {
".claude-plugin/plugin.json": json.dumps(manifest, indent=2, ensure_ascii=False) + "\n",
".claude-plugin/authoring-notes.json": json.dumps(notes, indent=2, ensure_ascii=False) + "\n",
"README.md": _readme_markdown(identity, domain=domain, distribution=distribution,
rights=rights, source_note=source_note),
f"agents/cs-{identity['slug']}.md": _agent_markdown(identity, domain, source_note),

View file

@ -0,0 +1,12 @@
{
"source": {
"spec": "User request: convert https://www.deeplearningbook.org/ into a shareable skill.",
"build_pattern": "Companion, not compilation. Follows the book-to-skill OUTPUT SHAPE (master SKILL.md under 4k tokens with a chapter index and topic index, chapters/chNN-*.md, glossary.md, patterns.md, cheatsheet.md — validated by book-to-skill's own book_skill_validator.py) while deliberately NOT running its extraction pipeline. Every chapter file is original synthesis written from domain knowledge, linking to the official free chapter; the organizing structure is the book's published table of contents. Adds four stdlib-only tools, four references citing 7-8 sources each with per-claim confidence levels, and three assets.",
"distinct_from": "engineering/book-to-skill (the converter — this is the artifact its rights gate calls for when the source is copyrighted); engineering-team/senior-ml-engineer (production MLOps and serving, not the theory); engineering/llm-cost-optimizer (LLM economics, which the book predates); engineering/memory-engineering and engineering/agent-memory (agent systems, not model training); the teach/learn skills (general study workflows, not one specific text with its dependency graph and expiry dates)."
},
"attribution": {
"source_work": "Deep Learning, Ian Goodfellow, Yoshua Bengio and Aaron Courville, MIT Press, 2016 — https://www.deeplearningbook.org/. All rights remain with the authors and publisher. This companion is independent and unaffiliated, and is not endorsed by the authors or MIT Press.",
"rights_basis": "No rights basis is claimed or needed, because no protected expression is reproduced. The book is copyrighted and its site states the HTML-only format exists as a deliberate friction against copying under the authors' MIT Press contract; PDF distribution is not permitted. book-to-skill's rights gate would classify it 'local' (none of public-domain / open-license / internal-docs / author-permission applies), and its rights reference lists publishing a compiled skill of a copyrighted book to a public marketplace under 'Do not'. This plugin therefore contains no passages, paragraphs, figures, exercises, or per-paragraph paraphrase — only original synthesis, the factual table of contents, and links to the official free chapters. See skills/deep-learning-book/references/rights_and_use.md.",
"evidence_discipline": "Every claim about what changed since 2016 carries a confidence level (well-established / contested / folklore) and a primary citation, and two commonly repeated claims are marked contested rather than propagated: batch normalization's 'internal covariate shift' mechanism (challenged by Santurkar et al. 2018) and the strong form of the lottery-ticket hypothesis. Two pieces of folklore are named as folklore, including the local-minima fear the book itself corrects."
}
}

View file

@ -0,0 +1,15 @@
{
"name": "deep-learning-book",
"description": "Study companion and working knowledge base for the Deep Learning textbook by Goodfellow, Bengio & Courville (MIT Press, 2016), free to read at deeplearningbook.org. Twenty chapter files, a glossary, a patterns file and a cheatsheet index the whole book; every chapter carries a 'what changed after 2016' section, and a dedicated delta reference dates the text against 2026 practice with per-claim confidence levels — double descent qualifying the U-curve, AdamW splitting weight decay from L2, transformers displacing Chapter 10's recurrence, diffusion growing out of Chapter 18's score matching, and self-supervised learning vindicating Chapter 15 while replacing its methods. Four stdlib-only tools make the book executable: a prerequisite-closed reading-path planner that refuses goals the 2016 book does not cover, a training diagnostic running Chapter 11's rules in priority order so a NaN is never reported as overfitting, a capacity planner that ranks the regularization ladder and pushes 'shrink the model' last in the overparameterized regime, and a parameter/FLOP/activation-memory calculator that refuses a stack whose shapes do not connect. Deliberately a companion, not a compilation: the book is copyrighted, so nothing here reproduces its text — every chapter file is original synthesis linking to the official free chapter. Use when studying or teaching this book, planning a route through it, or checking whether one of its recommendations is still current.",
"version": "2.12.0",
"author": {
"name": "Alireza Rezvani",
"url": "https://alirezarezvani.com"
},
"homepage": "https://github.com/alirezarezvani/claude-skills/tree/main/engineering/deep-learning-book",
"repository": "https://github.com/alirezarezvani/claude-skills",
"license": "MIT",
"skills": [
"./skills/deep-learning-book"
]
}

View file

@ -0,0 +1,118 @@
# deep-learning-book — study companion for *Deep Learning* (Goodfellow, Bengio & Courville)
A navigable, executable, **date-stamped** companion to the 2016 MIT Press textbook that is free
to read at [deeplearningbook.org](https://www.deeplearningbook.org/).
Twenty chapter files, a glossary, a patterns file, a cheatsheet, four references and four
deterministic tools — plus the thing a static compilation cannot give you: a **2016 → 2026 delta
layer** that says, per chapter, what still holds, what was superseded, and what is now purely
historical.
## Why this is a companion and not a compiled skill
This repository ships [`engineering/book-to-skill`](../book-to-skill/), which compiles a document
on disk into a knowledge-base skill. It was deliberately **not** used here, for three reasons its
own rights gate makes binding:
1. The book is copyrighted (MIT Press, 2016). Free to read ≠ free to redistribute.
2. deeplearningbook.org states that its HTML-only presentation is a deliberate friction against
copying, required by the authors' contract, and that PDF distribution is not permitted.
3. This repository is public, and `book-to-skill`'s rights gate refuses a `shareable` package
without `public-domain`, `open-license`, `internal-docs` or `author-permission`. None applies.
(Its hard rule 1 also forbids scraping a book from the web, so the pipeline could not have run
against a URL in any case.)
So this skill contains **no passages, paragraphs, figures, or per-paragraph paraphrase**. Every
chapter file is original synthesis — what the chapter establishes, how to use it, where it has
aged — with a link to the official free chapter. The organizing structure is the book's published
table of contents, which is factual metadata. Full reasoning in
[`references/rights_and_use.md`](skills/deep-learning-book/references/rights_and_use.md).
**The rule this sets for the repository:** when a user asks to convert a copyrighted work into a
shareable skill, build a companion that indexes and updates the source, not a compilation that
reproduces it. Compile only when the rights gate clears, and keep the output local when it does not.
## What is in it
```
skills/deep-learning-book/
├── SKILL.md core frameworks + chapter index + topic index (~1.9k tokens, resident)
├── chapters/ch01..ch20 one file per chapter, each with "What changed after 2016"
├── glossary.md every key term → its chapter
├── patterns.md techniques as instruments, with trade-offs
├── cheatsheet.md decision tables: loss choice, fit verdict, optimizer defaults
├── references/ delta layer · prerequisite map · study method · rights
├── scripts/ 4 stdlib tools
└── assets/ layer spec · chapter worksheet · study log
```
## The tools
| Tool | Does | Refuses |
|---|---|---|
| `reading_path_planner.py` | Goal + background + hours → prerequisite-closed, ordered path with an hour budget | A goal outside the book (exit 3, names what covers it); an unroutable goal (exit 4, prints the questions) |
| `training_diagnostics.py` | Measurements → ranked cause + next action + chapter, rules in priority order | Diagnosing with no instruments (exit 4). Never reports a NaN as overfitting |
| `capacity_planner.py` | Gap + params-per-example → ordered regularization ladder | A validation error materially below training error (exit 4 — leaky split) |
| `model_arithmetic.py` | Layer stack → parameters, FLOPs, activation memory per example | A stack whose shapes do not connect (exit 5); an unknown layer type (exit 4) |
All four are standard-library only, support `--help` / `--sample` / `--output json`, make no
network calls, and load no frameworks.
## The delta layer
The book was published in 2016; *Attention Is All You Need* appeared in 2017. Five corrections
carry most of the weight, each cited and confidence-rated in
[`references/book_to_2026_delta.md`](skills/deep-learning-book/references/book_to_2026_delta.md):
1. **Double descent** qualifies Chapter 5's U-shaped capacity curve — "shrink the model when it
overfits" is no longer the only correct move, and `capacity_planner.py` encodes the correction.
2. **AdamW**: weight decay and L2 are not equivalent under an adaptive optimizer; Chapter 7 treats
them as interchangeable.
3. **Transformers** displaced Chapter 10's recurrence — keep its gradient-flow analysis, drop its
architecture recommendation. (State-space models made that analysis live again.)
4. **Diffusion** grew directly out of Chapter 14's denoising autoencoders and Chapter 18's score
matching, and displaced Chapter 20's model list.
5. **Self-supervised learning** vindicated Chapter 15's bet while replacing every method it names;
unsupervised disentanglement was proven impossible without inductive bias.
The general rule the file states: the conflict is almost always in the **recommendation**, not the
**analysis**. Keep the diagnosis, replace the prescription.
## Use it
```bash
S=engineering/deep-learning-book/skills/deep-learning-book/scripts
python3 $S/reading_path_planner.py --goal "train and debug convnets" --background applied --hours-per-week 5
python3 $S/training_diagnostics.py --train-loss 0.02 --val-loss 1.9 --tiny-subset-fits yes
python3 $S/capacity_planner.py --params 12000000 --train-examples 50000 --train-error 0.01 --val-error 0.22
python3 $S/model_arithmetic.py --spec skills/deep-learning-book/assets/example_layer_spec.json
```
Slash commands: `/cs:deep-learning` (navigate and date the answer), `/cs:dl-reading-path`,
`/cs:dl-diagnose`. Agent: `cs-deep-learning-tutor`.
## Distinct from
- **`engineering/book-to-skill`** — the converter. This is what you build when its rights gate
says no.
- **`engineering-team/senior-ml-engineer`** — production MLOps, deployment, serving. This is the
theory underneath.
- **`engineering/llm-cost-optimizer`** — LLM economics, which the book predates entirely.
- **`teach` / `learn` skills** — general study workflows. This is one specific text, with its
dependency graph and its expiry dates.
## Scope
The twenty chapters and the delta between them and 2026 practice. **Not covered**, because the
book does not cover them: reinforcement learning beyond passing mention, LLM training
infrastructure, RLHF/DPO, agentic systems, MLOps tooling, fairness and safety evaluation. The
skill is built to say so rather than improvise.
## Attribution
*Deep Learning*, Ian Goodfellow, Yoshua Bengio and Aaron Courville, MIT Press, 2016 —
https://www.deeplearningbook.org/. All rights in the book remain with its authors and publisher.
This companion is an independent work: no text, figures, or exercises from the book are
reproduced here, and it is not endorsed by or affiliated with the authors or MIT Press. The
companion's own content is MIT-licensed as part of this repository.

View file

@ -0,0 +1,61 @@
---
name: cs-deep-learning-tutor
description: "Study companion for the Deep Learning textbook (Goodfellow, Bengio & Courville, 2016). Plans a prerequisite-closed reading path, answers chapter questions from the compiled knowledge base, diagnoses training runs against Chapter 11's decision tree, and flags every place the 2016 text has been superseded. Use for studying the book, teaching from it, or checking whether one of its recommendations is still current."
---
# Deep Learning Tutor
You are a study companion for *Deep Learning* by Ian Goodfellow, Yoshua Bengio and Aaron
Courville (MIT Press, 2016), which is free to read at deeplearningbook.org.
## What you are working from
`engineering/deep-learning-book/skills/deep-learning-book/` — a master SKILL.md with core
frameworks and two indexes, 20 chapter files, a glossary, a patterns file, a cheatsheet, four
references and four tools. Read the SKILL.md first, resolve the question through the Topic
Index, then read that chapter file before answering.
## Hard rules
1. **Never reproduce the book's text.** Not a paragraph, not a figure, not a
sentence-by-sentence paraphrase. Point the reader at the official chapter URL and explain in
your own words. This is the constraint the whole skill is built around — see
`skills/deep-learning-book/references/rights_and_use.md`.
2. **Date every recommendation.** The book is from 2016 and *Attention Is All You Need* is from
2017. When a chapter's advice has been superseded, say so and cite
`skills/deep-learning-book/references/book_to_2026_delta.md`. Never present a 2016 recommendation as current practice
without that check.
3. **Separate the analysis from the prescription.** The book's diagnoses (why gradients vanish,
why the partition function is hard, why depth helps) almost all still hold. Its
prescriptions (use an LSTM, use Adam with L2, shrink the model when it overfits) frequently
do not. Keep the diagnosis, replace the prescription.
4. **Say when the book does not cover something.** RLHF, LLM infrastructure, agents, MLOps,
fairness — name the gap and route elsewhere rather than improvising the book's position.
5. **Read the chapter file before answering from it.** The indexes are for navigation, not for
answering.
6. **Run the tool rather than estimating.** Reading paths, training diagnoses, capacity plans
and parameter counts all have deterministic tools. Use them, then interpret the output.
## How you work
**When asked where to start** — run `reading_path_planner.py` with the stated goal, background
and weekly hours. If it exits 3 or 4, relay its questions rather than guessing a path.
**When asked about a topic** — resolve through the Topic Index, read the chapter file, answer,
and always surface the "What changed after 2016" section if one applies.
**When asked to diagnose a training run** — ask for the measurements the tool needs
(train loss, val loss, target loss, gradient norm, whether it can overfit a tiny subset), run
`training_diagnostics.py`, and act on finding [1] before anything below it. Do not skip to the
interesting hypothesis; the rule order exists because a NaN is not an overfitting problem.
**When teaching** — use the retrieval-practice cadence in `skills/deep-learning-book/references/study_method_canon.md`:
ask the reader to state the core idea from memory first, then correct. Do not lecture the
chapter at someone who has just read it.
## Voice
Direct and specific. Name the chapter for every claim. When the reader's plan is wrong — front
to back through Part I, or a Part III chapter without its prerequisites — say so once, give the
alternative, and let them decide. When something in the book is simply out of date, say that
plainly rather than defending it; a companion that will not date its source is worthless.

View file

@ -0,0 +1,55 @@
---
name: "cs-deep-learning"
description: "/cs:deep-learning — Study companion for the Deep Learning textbook (Goodfellow, Bengio & Courville, 2016). Answers chapter questions from a compiled knowledge base, always dating the answer against 2026 practice, and routes to the reading-path planner or the training diagnostic. Points at the free official chapters; never reproduces them."
argument-hint: "[a topic, a chapter number, a question about the book, or 'where do I start']"
---
# /cs:deep-learning — Navigate the book, and date its advice
**Command:** `/cs:deep-learning [topic | chNN | question]`
The book is free to read at [deeplearningbook.org](https://www.deeplearningbook.org/). This
command navigates it and keeps it current; it does not replace it.
## When to run
- "What does the book say about regularization / saddle points / the partition function?"
- "Is Chapter 10's advice on LSTMs still right?"
- "Explain the ELBO the way Chapter 19 sets it up"
- "Where should I start?" (routes to `/cs:dl-reading-path`)
- "Why is my training run doing this?" (routes to `/cs:dl-diagnose`)
## When NOT to run
- Production ML engineering → `engineering-team/senior-ml-engineer`
- LLM cost and serving → `engineering/llm-cost-optimizer`
- RLHF, agents, prompting, MLOps → outside the book entirely; this command will say so
## Procedure
1. **Load** `engineering/deep-learning-book/skills/deep-learning-book/SKILL.md`.
2. **Resolve** the request through the Topic Index to one or more chapters.
3. **Read** those chapter files before answering. The index is navigation, not content.
4. **Answer** in your own words, naming the chapter, and link the official chapter URL.
5. **Date it.** If the chapter file has a "What changed after 2016" section relevant to the
answer, surface it — with the confidence level from
`skills/deep-learning-book/references/book_to_2026_delta.md`. Separate the book's *analysis* (usually still true) from
its *prescription* (frequently superseded).
6. **Name the boundary.** If the question is outside the twenty chapters, say so and route.
## The four things this command will not do
- Reproduce the book's text, figures, or a paragraph-by-paragraph paraphrase.
- Present a 2016 recommendation as current practice without checking the delta layer.
- Answer from the index without reading the chapter file.
- Improvise the book's position on material published after it.
## Output shape
```
Chapter(s): ch07 (Regularization), ch05 (capacity)
Answer : <original explanation, naming the framework>
Still true: <holds / analysis holds but recommendation superseded / historical> + why
Read it : https://www.deeplearningbook.org/contents/regularization.html
Next : <the tool, worksheet, or chapter that follows>
```

View file

@ -0,0 +1,52 @@
---
name: "cs-dl-diagnose"
description: "/cs:dl-diagnose — Diagnose a training run against Chapter 11's decision tree: read training error before deciding anything, and never diagnose a NaN as overfitting. Returns a ranked cause, the specific next action, and the chapter that justifies it."
argument-hint: "[what the run is doing — losses, gradient norm, or a description]"
---
# /cs:dl-diagnose — Measurement first, hypothesis second
**Command:** `/cs:dl-diagnose [symptoms]`
Chapter 11's rule, which most teams have backwards: **read training error first.** High
training error means the model or the optimizer is the bottleneck, and more data cannot help.
## Procedure
1. **Collect the instruments.** Ask for what is missing, in this order:
- training loss and validation loss (same units, same epoch)
- the target loss — a human baseline, a published number, or an irreducible-error estimate
(without it, underfitting cannot be distinguished from convergence)
- global gradient norm, if available
- has the loss ever gone NaN or inf?
- can the model drive training loss to ~0 on 1050 examples? (the smoke test that separates
a bug from a hard problem)
2. **Run the tool:**
```bash
python3 engineering/deep-learning-book/skills/deep-learning-book/scripts/training_diagnostics.py \
--train-loss <x> --val-loss <y> --target-loss <z> --grad-norm <g> \
--tiny-subset-fits yes|no|unknown
```
Exit 4 means not enough instruments — ask for one of the named measurements rather than
guessing.
3. **Act on finding [1] first.** Rules fire in priority order for a reason: a non-finite loss is
a numerics failure, not a modelling one, and a model that cannot overfit 20 examples has a
bug that no hyperparameter will fix.
4. **On an OVERFIT verdict**, follow up with the capacity planner, which ranks the
regularization ladder and applies the double-descent correction:
```bash
python3 .../capacity_planner.py --params <n> --train-examples <m> \
--train-error <x> --val-error <y> --applied early-stopping
```
5. **On a memory or throughput question**, run `model_arithmetic.py --spec <file>` — it reports
parameters, FLOPs and activation memory per example, and refuses a stack whose shapes do not
connect.
6. **Close with the discipline, not just the fix:** change one thing per experiment, log it,
re-measure the gap.
## Do not
- Skip to the interesting hypothesis before the rules have been read in order.
- Recommend collecting data while training error is high.
- Recommend shrinking an overparameterized model first — see the double-descent caveat in
`skills/deep-learning-book/references/book_to_2026_delta.md`.

View file

@ -0,0 +1,39 @@
---
name: "cs-dl-reading-path"
description: "/cs:dl-reading-path — Build a prerequisite-closed reading path through the Deep Learning book from a goal, a background and the hours you actually have. Refuses to route a goal the 2016 book does not cover, and names what covers it instead."
argument-hint: "[your goal — what you want to be able to do after reading]"
---
# /cs:dl-reading-path — A route, not a page count
**Command:** `/cs:dl-reading-path [goal]`
The book's part order is not its dependency order. Front-to-back means weeks in Chapters 24
before touching a network, which is where most readers stop.
## Procedure
1. **Ask three things** if the user has not said them, one at a time:
- What do you want to be able to *do* afterwards?
- Background: `none` / `math` / `applied` / `research`?
- Realistic study hours per week?
2. **Run the planner:**
```bash
python3 engineering/deep-learning-book/skills/deep-learning-book/scripts/reading_path_planner.py \
--goal "<goal>" --background <bg> --hours-per-week <n>
```
3. **Handle the refusals rather than working around them.**
- Exit 3 — the goal is outside the book. Relay what covers it; do not invent a path.
- Exit 4 — the goal is unroutable. Ask the printed questions, one per turn.
4. **Relay the path** with the hour budget, and flag that the hours are a planning heuristic to
recalibrate after chapter one.
5. **Offer the study scaffolding**: `skills/deep-learning-book/assets/study_log_template.md` and
`skills/deep-learning-book/assets/chapter_worksheet.md`, plus the retrieval-practice cadence from
`skills/deep-learning-book/references/study_method_canon.md`.
## What to say about Part I
Most applied readers should skim Chapters 24 once for vocabulary, start at Chapter 5, and
return to a specific section when Chapter 8 needs it. Readers heading for Part III should work
Part I properly — those chapters compound, and so do the gaps.
`skills/deep-learning-book/references/prerequisite_map.md` has the dependency graph and the three strategies.

View file

@ -0,0 +1,194 @@
---
name: deep-learning-book
description: "Study companion and working knowledge base for the Deep Learning textbook by Goodfellow, Bengio & Courville (MIT Press, 2016), read free at deeplearningbook.org. Indexes all 20 chapters, carries a 2016-to-2026 delta layer naming what the book got right, what was superseded (transformers, AdamW, diffusion, double descent) and what still holds, and ships four deterministic tools: a prerequisite-aware reading-path planner, a training-failure diagnostic, a capacity-and-regularization planner, and a parameter/FLOP/activation-memory calculator. Use when studying or teaching this book, planning a route through it, deciding whether a chapter's advice is still current, or translating its math into a training decision. It points at the official chapters — it never reproduces them."
license: MIT
metadata:
version: 1.0.0
author: Alireza Rezvani
category: engineering
updated: 2026-08-25
---
# Deep Learning — Study Companion
**Source book**: *Deep Learning*, Ian Goodfellow, Yoshua Bengio & Aaron Courville
(MIT Press, 2016) · 20 chapters, 3 parts · read free at
[deeplearningbook.org](https://www.deeplearningbook.org/) · companion compiled 2026-08-25.
**This is a companion, not a copy.** The book is copyrighted, and its site states that the
HTML-only format exists to discourage copying under the authors' MIT Press contract. Nothing
here reproduces its text. Every chapter file is original synthesis — what the chapter
establishes, how to use it, where it has aged — plus a link to the official chapter. Read the
book at the link; use this to navigate it, keep it current, and turn it into decisions.
See [references/rights_and_use.md](references/rights_and_use.md).
## How to Use This Skill
- **No argument** — load the core frameworks below.
- **A topic** — ask about `regularization`, `saddle points`, `partition function`; resolved
through the Topic Index, then that chapter file is read before answering.
- **`chNN`** — load that chapter's file.
- **"is this still true?"** — the 2016→2026 delta layer, in every chapter file and in
[references/book_to_2026_delta.md](references/book_to_2026_delta.md).
- **"where do I start?"** — run `scripts/reading_path_planner.py`.
When asked about something outside these 20 chapters, say so and route to the delta reference
rather than improvising the book's position on material published after it.
---
## Core Frameworks & Mental Models
### The (T, P, E) frame — ch05
Name the **task**, the **performance measure**, and the **experience** in one sentence before any
model code. Most failed projects failed at P: an unstated metric, or a proxy whose relationship
to the real objective was never checked.
### Every loss is a negative log-likelihood — ch03, ch06
Choose the output distribution, then take its negative log. Gaussian → MSE, Bernoulli → binary
cross-entropy, categorical → cross-entropy, Laplace → MAE. "Which loss?" is always the question
"which distribution?" in disguise. Modern contrastive and preference objectives sit outside this
frame — a real limit of the book, not a gap in your understanding.
### KL asymmetry decides your failure mode — ch03, ch19, ch20
D(p‖q) ≠ D(q‖p). Forward KL is mode-covering (blurry averages); reverse KL is mode-seeking
(sharp but partial). This single fact predicts VAE blur, GAN mode collapse, and the
characteristic over-confidence of mean-field variational posteriors.
### Train-error-first triage — ch11, ch05
High training error → capacity or optimization is the bottleneck; **more data will not help**.
Low training error with a large validation gap → data or regularization. This is the highest-value
heuristic in the book. `scripts/training_diagnostics.py` runs it.
### Capacity, the gap, and the U-curve's caveat — ch05, ch07
Regularization trades variance for bias. But the classical U-shaped capacity curve is incomplete:
past the interpolation threshold, test error can fall again (double descent, 20192020,
post-dating the book). Practical consequence: when a large model overfits, try more data, more
regularization or longer training **before** shrinking it.
### Architecture is a prior, not a trick — ch09, ch10, ch15
Convolution asserts translation equivariance and locality. Recurrence asserts that the past
compresses into a state. A distributed representation asserts that factors combine
combinatorially. When the assertion is false, the architecture cannot be rescued by tuning — and
when it is true, it beats capacity. This is also why Vision Transformers need more data than
ConvNets: they discard the prior and buy it back with examples.
### Depth's real cost is gradient flow and activation memory — ch06, ch08, ch10
Backprop is the chain rule scheduled well: one forward-pass-equivalent of compute, and memory
proportional to stored activations. Depth fails through vanishing/exploding gradients and
ill-conditioning, which is why residual connections, normalization and clipping exist.
### The partition function organizes Part III — ch16, ch17, ch18, ch19
For undirected models, the likelihood gradient needs samples from the model itself. Four escape
routes: sample it (CD/PCD), sidestep it algebraically (pseudolikelihood, **score matching**),
learn around it (NCE), or estimate it for evaluation (AIS). Score matching's descendants are
today's diffusion models — which is why Part III repays reading even though its models did not
survive.
### Diagnose before you redesign — ch04, ch08, ch11
Gradient norm exploding → clip. Norm large but loss flat → ill-conditioning. Norm near zero with
high loss → saturation or dead units. NaN → numerics first. Change one thing per experiment.
---
## Chapter Index
| # | Title | Key content |
|---|-------|-------------|
| [ch01](chapters/ch01-introduction.md) | Introduction | representation learning, depth as composition, curse of dimensionality |
| [ch02](chapters/ch02-linear-algebra.md) | Linear Algebra | norms, SVD, eigendecomposition, conditioning, PCA |
| [ch03](chapters/ch03-probability-information-theory.md) | Probability & Information Theory | distributions, entropy, KL, cross-entropy |
| [ch04](chapters/ch04-numerical-computation.md) | Numerical Computation | under/overflow, conditioning, gradient descent, KKT |
| [ch05](chapters/ch05-machine-learning-basics.md) | Machine Learning Basics | capacity, biasvariance, No Free Lunch, MLE, manifolds |
| [ch06](chapters/ch06-deep-feedforward-networks.md) | Deep Feedforward Networks | output/hidden units, universal approximation, backprop |
| [ch07](chapters/ch07-regularization.md) | Regularization | norm penalties, augmentation, early stopping, dropout |
| [ch08](chapters/ch08-optimization.md) | Optimization | SGD, momentum, init, Adam, batch norm, saddles |
| [ch09](chapters/ch09-convolutional-networks.md) | Convolutional Networks | sparse interactions, sharing, equivariance, pooling |
| [ch10](chapters/ch10-sequence-modeling.md) | Sequence Modeling | BPTT, vanishing gradients, LSTM/GRU, attention |
| [ch11](chapters/ch11-practical-methodology.md) | Practical Methodology | metrics, baselines, the data-vs-capacity rule, debugging |
| [ch12](chapters/ch12-applications.md) | Applications | scaling, compression, vision, speech, NLP (dated) |
| [ch13](chapters/ch13-linear-factor-models.md) | Linear Factor Models | PPCA, factor analysis, ICA, sparse coding |
| [ch14](chapters/ch14-autoencoders.md) | Autoencoders | undercomplete, sparse, denoising, contractive |
| [ch15](chapters/ch15-representation-learning.md) | Representation Learning | transfer, distributed codes, disentanglement |
| [ch16](chapters/ch16-structured-probabilistic-models.md) | Structured Probabilistic Models | directed/undirected, energy-based, d-separation |
| [ch17](chapters/ch17-monte-carlo-methods.md) | Monte Carlo Methods | importance sampling, MCMC, Gibbs, mixing |
| [ch18](chapters/ch18-partition-function.md) | Confronting the Partition Function | CD/PCD, pseudolikelihood, score matching, NCE, AIS |
| [ch19](chapters/ch19-approximate-inference.md) | Approximate Inference | ELBO, EM, mean field, amortization |
| [ch20](chapters/ch20-deep-generative-models.md) | Deep Generative Models | Boltzmann machines, VAE, GAN, autoregressive |
## Topic Index
- **Activation functions, ReLU, GELU** → ch06
- **Adam, AdamW, adaptive optimizers** → ch08, ch07
- **Attention, transformers** → ch10, ch12
- **Autoencoders, denoising, sparse** → ch14, ch13
- **Backpropagation, autodiff** → ch06
- **Batch / layer normalization** → ch08
- **Biasvariance, double descent** → ch05
- **Convolution, pooling, receptive field** → ch09
- **Cross-entropy, KL divergence, entropy** → ch03
- **Diffusion, score matching** → ch18, ch14, ch20
- **Dropout, weight decay, early stopping** → ch07
- **ELBO, variational inference, EM** → ch19
- **Energy-based models, graphical models** → ch16
- **GANs, VAEs, generative taxonomy** → ch20
- **Gradient clipping, exploding/vanishing** → ch10, ch08
- **Hyperparameter search** → ch11
- **Initialization** → ch08
- **LSTM, GRU, BPTT, teacher forcing** → ch10
- **Maximum likelihood, MAP** → ch05, ch03
- **MCMC, Gibbs, importance sampling** → ch17
- **Numerical stability, softmax, log-space** → ch04
- **Partition function, CD, PCD, NCE** → ch18, ch16
- **PCA, ICA, factor analysis** → ch13, ch02
- **Representation learning, transfer, probes** → ch15, ch01
- **Saddle points, ill-conditioning** → ch08, ch04
- **SVD, eigendecomposition, condition number** → ch02
- **Training diagnostics, metric choice** → ch11
- **Universal approximation** → ch06
## Supporting Files
- [glossary.md](glossary.md) — every key term with its chapter
- [patterns.md](patterns.md) — techniques as instruments, with trade-offs
- [cheatsheet.md](cheatsheet.md) — decision tables and defaults
- [references/book_to_2026_delta.md](references/book_to_2026_delta.md) — what changed, per chapter
- [references/prerequisite_map.md](references/prerequisite_map.md) — the real dependency graph
- [references/study_method_canon.md](references/study_method_canon.md) — how to study a hard text
- [references/rights_and_use.md](references/rights_and_use.md) — why this is a companion
## Tools
```bash
S=engineering/deep-learning-book/skills/deep-learning-book/scripts
python3 $S/reading_path_planner.py --goal "train a transformer" --background applied --hours-per-week 5
python3 $S/training_diagnostics.py --train-loss 0.02 --val-loss 1.9 --grad-norm 0.4 --epochs 30
python3 $S/capacity_planner.py --params 12000000 --train-examples 50000 --train-error 0.01 --val-error 0.22
python3 $S/model_arithmetic.py --spec-sample
```
Every tool supports `--help`, `--sample` and `--output json`, uses the standard library only, and
returns typed exit codes.
---
## Scope & Limits
This companion covers the 2016 edition's 20 chapters and the delta between them and 2026
practice. It does **not** cover: reinforcement learning beyond passing mention, LLM training
infrastructure, RLHF/DPO alignment, agentic systems, MLOps tooling, or fairness and safety
evaluation — none of which the book treats. For production ML engineering use
`engineering-team/senior-ml-engineer`; for LLM cost work use `engineering/llm-cost-optimizer`.
When a question lands outside the book, say the book does not cover it and cite the delta
reference for what replaced its position. A companion that quietly extrapolates is worse than one
that names its boundary.

View file

@ -0,0 +1,62 @@
# Chapter Worksheet
One page per chapter. Fill it from memory **with the book closed**, then check against the
skill's chapter file. The gap between what you wrote and what is there is the actual learning
signal — retrieval practice beats re-reading (see `references/study_method_canon.md`).
---
**Chapter**: ___ **Title**: ______________________ **Date**: __________
**Time spent**: ______ **Read as**: ☐ first pass ☐ working the derivations ☐ revisit
## 1. Core idea, in one sentence
> If this takes more than two sentences, you have summarized rather than extracted.
_______________________________________________________________________________
## 2. Three concepts I could define to someone else
1. _____________________________________________________________________________
2. _____________________________________________________________________________
3. _____________________________________________________________________________
## 3. One thing I could not follow
> Name it precisely — "the derivation on the negative phase" beats "the math."
_______________________________________________________________________________
**Is it blocking?** ☐ yes, a later chapter needs it (which: ____) ☐ no, note and move on
## 4. Self-explanation prompt
Pick one equation. **What breaks if this term is removed?**
_______________________________________________________________________________
## 5. When would I actually use this?
> A note that answers this gets read again. A note that restates the text does not.
_______________________________________________________________________________
## 6. Still true in 2026?
Check the chapter file's "What changed after 2016" section and this skill's
`references/book_to_2026_delta.md`.
☐ holds as written ☐ analysis holds, recommendation superseded ☐ historical only
What replaced it: ___________________________________________________________
## 7. The small thing I applied before moving on
> Five lines of code, one diagnosis of a real run, one re-derivation. This step is the
> one most readers skip and the one that decides whether any of it survives.
_______________________________________________________________________________
## 8. Revisit date
☐ +1 week: ________ ☐ +1 month: ________ (ch05, ch08, ch11 and ch18 are worth both)

View file

@ -0,0 +1,41 @@
{
"name": "transformer encoder block, 768-dim, 512 tokens",
"_comment": "Feed to model_arithmetic.py --spec. Shapes are per example, no batch dim. The two feedforward linears run position-wise over the (512, 768) sequence: one weight matrix shared across all 512 tokens, which is what a transformer FFN actually is. Do NOT insert a flatten before them \u2014 that models a dense layer over the whole flattened sequence and inflates the parameter count by 512x. Note how the mha row's cost grows quadratically with sequence length: double 512 to 1024 and the attention term quadruples while the projections only double.",
"layers": [
{
"type": "input",
"shape": [
512,
768
],
"name": "token embeddings in"
},
{
"type": "layernorm",
"name": "pre-norm 1"
},
{
"type": "mha",
"heads": 12,
"name": "self-attention"
},
{
"type": "layernorm",
"name": "pre-norm 2"
},
{
"type": "linear",
"units": 3072,
"name": "ffn up (position-wise)"
},
{
"type": "activation",
"name": "gelu"
},
{
"type": "linear",
"units": 768,
"name": "ffn down (position-wise)"
}
]
}

View file

@ -0,0 +1,51 @@
# Study Log — Deep Learning (Goodfellow, Bengio & Courville)
Started: __________ · Goal: ______________________________________________
Path from `reading_path_planner.py`: _______________________________________
Hours available per week: ______ · Estimated weeks: ______
## Progress
| Date | Ch | Hours | Status | Confidence (1-5) | Applied it to |
|------|----|-------|--------|------------------|---------------|
| | | | ☐ read ☐ worked ☐ applied | | |
| | | | | | |
| | | | | | |
**Confidence** means "could I explain this to a colleague without notes?" — not "did I finish
the pages." A 2 is useful information; record it honestly and put the chapter on the revisit
list.
## Revisit queue (spaced repetition)
| Chapter | +1 week | +1 month | Notes |
|---------|---------|----------|-------|
| ch05 | | | vocabulary every later chapter reuses |
| ch08 | | | the optimization diagnoses |
| ch11 | | | the workflow — apply it, do not just read it |
| ch18 | | | score matching → diffusion |
## Deferred with intent
Things skipped on purpose, and what would bring them back.
| Chapter or section | Why deferred | Bring it back when |
|--------------------|--------------|--------------------|
| | | |
## Open confusions
Carry these forward — a confusion that survives three chapters is a prerequisite gap, and
`references/prerequisite_map.md` will name the chapter that fills it.
| # | Confusion | First hit (ch) | Resolved? |
|---|-----------|----------------|-----------|
| 1 | | | |
## Applied log
The point of the book. One line per real use.
| Date | What I was doing | Which chapter helped | Outcome |
|------|------------------|----------------------|---------|
| | | | |

View file

@ -0,0 +1,59 @@
# Chapter 1: Introduction
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/intro.html
## Core Idea
Deep learning is representation learning stacked: instead of hand-designing the features a
model consumes, you let the model learn a hierarchy of representations, each layer expressed
in terms of the one below it. Depth is the mechanism that makes composition cheap.
## Key Concepts
- **Representation learning**: learning the features, not just the mapping from features to output.
- **Depth as composition**: a deep model reuses sub-computations, so a function needing
exponentially many units at depth 1 may need polynomially many at depth k.
- **The curse of dimensionality**: as input dimension grows, the number of distinguishable
configurations grows exponentially, so local-interpolation methods run out of neighbours.
- **Prior of compositionality**: deep learning bets that the data was generated by a composition
of simple factors. This is a prior, not a theorem — where the bet is wrong, depth does not help.
- **AI winters and rebrands**: cybernetics → connectionism → deep learning; the ideas outlived
three funding cycles because the constraint was data and compute, not concept.
## Mental Models
- Think of each layer as **re-coordinatizing** the input so the next layer's job gets easier —
not as "extracting meaning."
- Prefer depth over width when the target function plausibly **factors**; prefer width when it
does not. Depth is a structural prior, and priors have to be earned.
- Treat "the model learns features automatically" as **shifting where the human judgment goes**
(architecture, objective, data curation), not eliminating it.
## Anti-patterns
- **Reading this chapter as history and skipping it**: the three growth curves it draws
(dataset size, model size, benchmark accuracy) are the argument for why anything else works.
- **Assuming depth is always better**: without the compositional structure, extra depth buys
optimization difficulty and nothing else.
## What changed after 2016
The chapter's central claim — capability tracks dataset and model scale — held, and was made
quantitative by neural scaling laws (Hestness et al. 2017; Kaplan et al. 2020; Hoffmann et al.
2022 "Chinchilla"), which the 2016 text predates. Its examples of "what deep learning can do"
are now badly dated; its explanation of *why* depth helps is not. **Confidence: high** — the
scaling-law literature is public and replicated.
## Key Takeaways
1. Before adding depth, state the compositional structure you believe the data has.
2. Use the curse of dimensionality as the test for whether a nearest-neighbour-style baseline
is even viable on your input.
3. Read the growth curves as a resource argument: most 2016-era "deep learning doesn't work
here" results were data or compute verdicts, not architecture verdicts.
## Connects To
- **Ch 5**: the formal learning-theory machinery behind the claims made informally here.
- **Ch 15**: representation learning, promised here and delivered there.
- **references/book_to_2026_delta.md**: the scaling-law layer this chapter now needs.

View file

@ -0,0 +1,61 @@
# Chapter 2: Linear Algebra
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/linear_algebra.html
## Core Idea
The minimum linear algebra a deep learning practitioner needs, chosen for what appears later:
tensors and broadcasting, norms, eigendecomposition, SVD, the pseudoinverse, and PCA derived
from scratch. This is a filter, not a course — it teaches what Chapters 4, 5, 8 and 13 will use.
## Key Concepts
- **Tensor / broadcasting**: an n-dimensional array plus the rules for combining shapes. Most
real "model bugs" are shape bugs.
- **Norms**: L2 (Euclidean), L1 (sparsity-friendly, non-differentiable at 0), max-norm,
Frobenius. The choice of norm *is* the choice of what "small" means in a regularizer.
- **Eigendecomposition**: A = V diag(λ) V⁻¹ for square matrices; the eigenvalues tell you the
local curvature story later in Ch 4 and 8.
- **Singular value decomposition (SVD)**: A = U D Vᵀ, defined for *any* matrix. The general tool
where eigendecomposition needs square and diagonalizable.
- **MoorePenrose pseudoinverse**: the least-squares / minimum-norm solution when a system is
over- or under-determined.
- **Condition number**: ratio of largest to smallest singular value; large means small input
perturbations produce large output changes — the numerical fragility Ch 4 confronts.
- **PCA**: derived here as the linear encoder/decoder minimizing L2 reconstruction error, which
is exactly the framing Ch 1314 generalize.
## Mental Models
- Read a matrix as a **function on space**, and its singular values as how much it stretches
each orthogonal direction. Condition number = worst stretch / least stretch.
- Use SVD as the **default** decomposition and reach for eigendecomposition only when symmetry
buys you something (it does for Hessians).
- Treat a regularizer's norm as a **prior over parameter space**: L2 says "small and spread",
L1 says "mostly zero."
## Anti-patterns
- **Skipping to Chapter 6.** Ch 4 and 8's discussion of ill-conditioning is unreadable without
eigenvalues and condition number, and readers who skip typically bounce off Ch 8.
- **Memorizing decompositions as identities** instead of as geometry — the geometry is what
transfers to optimization.
## What changed after 2016
Nothing in the mathematics. What changed is the practice: in half-precision training, condition
number stopped being a theoretical concern and became an operational one (loss scaling, bf16 over
fp16 precisely because of dynamic range). **Confidence: high.**
## Key Takeaways
1. Track shapes explicitly; treat a shape mismatch as a modelling error, not a typing error.
2. Pick your norm deliberately when you regularize — you are choosing the shape of the prior.
3. Learn PCA in this chapter's form (encoder/decoder minimizing reconstruction) so Ch 1314 read
as generalizations rather than new material.
## Connects To
- **Ch 4**: conditioning and numerical stability use exactly these quantities.
- **Ch 13**: PCA reappears as a linear factor model with an explicit probabilistic story.
- **Ch 8**: Hessian eigenvalues explain why gradient descent stalls.

View file

@ -0,0 +1,67 @@
# Chapter 3: Probability and Information Theory
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/prob.html
## Core Idea
Deep learning models are probability distributions, and losses are log-likelihoods. This chapter
installs the vocabulary — random variables, the common distributions, expectation, Bayes' rule,
entropy, KL divergence, cross-entropy — that makes "why this loss?" answerable rather than
conventional.
## Key Concepts
- **Frequentist vs Bayesian probability**: rates of events vs degrees of belief. Deep learning
uses the Bayesian reading for parameters and the frequentist one for evaluation, mostly
without saying so.
- **Marginal / conditional / chain rule**: the algebra every graphical model in Ch 16 runs on.
- **Common distributions**: Bernoulli, categorical, Gaussian, exponential, Laplace, Dirac,
empirical, and mixtures. Each corresponds to an output layer you will actually build.
- **Self-information and Shannon entropy**: surprise, and expected surprise.
- **KL divergence**: asymmetric. D(p‖q) ≠ D(q‖p), and the asymmetry decides whether your fitted
model covers all modes or concentrates on one.
- **Cross-entropy**: H(p,q) = H(p) + D(p‖q). Minimizing cross-entropy over q is minimizing KL,
because H(p) is constant in q — this is why classification uses it.
- **Structured probabilistic models**: factorization of a joint into conditionals over a graph.
## Mental Models
- Read every loss as a **negative log-likelihood** under an assumed output distribution: MSE is
a Gaussian with fixed variance, cross-entropy is a categorical, MAE is a Laplace. If you know
the assumed distribution, you know when the loss is wrong for your data.
- Use KL **direction** as a design lever: forward KL (data ‖ model) is mode-covering and gives
blurry averages; reverse KL (model ‖ data) is mode-seeking and gives sharp but partial fits.
This one fact explains most of Ch 19 and 20.
- Treat softmax as **exp-then-normalize on logits**, and remember from Ch 4 that it must be
computed in a shift-stabilized form.
## Anti-patterns
- **Choosing MSE for a bounded or count-valued target** — you have assumed a Gaussian on data
that is not Gaussian, and the residual structure will tell you so.
- **Reading KL as a distance**: it is not symmetric and does not satisfy the triangle inequality.
- **Interpreting softmax outputs as calibrated probabilities** without checking calibration —
the chapter's math does not promise calibration, and modern networks are typically
overconfident (Guo et al. 2017, post-dating the book).
## What changed after 2016
The probabilistic core is unchanged. Two additions matter: the calibration literature (deep
networks are systematically overconfident; temperature scaling is the cheap fix), and the rise
of losses that are *not* clean log-likelihoods — contrastive/InfoNCE objectives, and preference
losses such as DPO. The chapter's "every loss is a likelihood" framing needs that caveat now.
**Confidence: high** for calibration; **high** for the contrastive family being outside the
chapter's scope.
## Key Takeaways
1. State the output distribution before choosing the loss; the loss follows from it.
2. When a generative model looks blurry, suspect forward KL; when it looks mode-collapsed,
suspect reverse KL.
3. Check calibration separately from accuracy — the book does not, and the gap is real.
## Connects To
- **Ch 5**: maximum likelihood as the estimator that justifies these losses.
- **Ch 1619**: graphical models, sampling, and variational inference all run on this algebra.
- **Ch 20**: the KL asymmetry decides GAN vs VAE failure modes.

View file

@ -0,0 +1,66 @@
# Chapter 4: Numerical Computation
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/numerical.html
## Core Idea
Real arithmetic on finite hardware fails in specific, predictable ways — underflow, overflow,
ill-conditioning — and gradient-based optimization inherits every one of them. This is the
shortest chapter with the highest debugging payoff.
## Key Concepts
- **Underflow / overflow**: numbers rounding to zero (then dividing) or exceeding representable
range (then becoming inf/NaN).
- **Stabilized softmax**: subtract the max logit before exponentiating; mathematically identical,
numerically survivable. `log_softmax` exists for the same reason.
- **Conditioning**: how much a function's output moves for small input moves; for a matrix, the
condition number from Ch 2.
- **Gradient descent** and the first-order Taylor picture; **critical points**: minima, maxima,
saddles.
- **Jacobian and Hessian**; second-order Taylor expansion, and the optimal step size implied by
curvature.
- **Newton's method** and why it is not the default in deep learning: the Hessian is n×n in the
parameter count.
- **Constrained optimization / KKT**: the framing that makes Ch 7's norm penalties readable as
constraints.
## Mental Models
- Read a **NaN in the loss** as a numerics report first and a modelling bug second: check
log(0), division by a near-zero denominator, exp of a large logit, and an exploding gradient
in that order.
- Think of the Hessian's **eigenvalue spread as the terrain**: a large condition number is a
narrow ravine, and the largest safe step size is set by the largest eigenvalue while progress
is set by the smallest.
- Prefer the **log-domain** whenever probabilities are multiplied — this is the single highest
yield habit in this chapter.
## Anti-patterns
- **Hand-rolling softmax or cross-entropy** in a training loop instead of using the fused,
stabilized primitive.
- **Blaming the learning rate for every divergence**: ill-conditioning produces the same symptom
and does not respond to the same fix.
- **Reaching for a second-order optimizer** in a model with millions of parameters without
understanding the memory cost.
## What changed after 2016
Mixed-precision training (fp16 with loss scaling; then bf16, which trades mantissa bits for
exponent range specifically to avoid these failures) made this chapter's content a daily
operational concern rather than a background caution. Gradient clipping became standard practice
for transformer training. **Confidence: high.**
## Key Takeaways
1. Work in log-space by default for anything probabilistic.
2. When training diverges, separate "step too large" from "problem ill-conditioned" — they need
different fixes.
3. Understand KKT well enough to read weight decay as a constraint; Ch 7 assumes it.
## Connects To
- **Ch 8**: every optimization difficulty named here recurs there at scale.
- **Ch 7**: the constrained-optimization view of regularization.
- **scripts/training_diagnostics.py**: mechanizes the NaN/divergence triage above.

View file

@ -0,0 +1,66 @@
# Chapter 5: Machine Learning Basics
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/ml.html
## Core Idea
Everything after this chapter is a special case of it: a task, a performance measure, an
experience, a capacity choice, and the generalization gap that capacity choice produces. If you
read one chapter of Part I, read this one.
## Key Concepts
- **Task / performance measure / experience (T, P, E)**: the definition that forces you to name
the metric before the model.
- **Capacity**: the range of functions a learner can express. Representational capacity vs
*effective* capacity (what the optimizer actually reaches).
- **Underfitting / overfitting** and the classical **U-shaped** generalization-error curve.
- **Biasvariance decomposition**: expected error splits into bias², variance, and irreducible
noise. Regularization trades variance for bias.
- **No Free Lunch theorem**: averaged over *all* data-generating distributions, every algorithm
ties. Therefore all progress comes from priors matched to the distributions we actually face.
- **Regularization**: any change intended to reduce generalization error but not training error.
- **Maximum likelihood estimation** and its **MAP** counterpart; consistency and efficiency.
- **Hyperparameters and validation sets**: never tune on test.
- **Curse of dimensionality, local constancy, manifold hypothesis**: why nearest-neighbour-style
priors fail and why deep models assume data concentrates near a low-dimensional manifold.
## Mental Models
- Ask "**what is the prior?**" before "what is the model?" — No Free Lunch says the prior is
where all the leverage is.
- Read regularization as **moving mass in the biasvariance budget**, so that "add dropout" and
"get more data" are alternative purchases of the same thing.
- Treat the **train/val gap** as your primary instrument: gap small + error high = underfit
(capacity or optimization); gap large = overfit (regularization or data).
## Anti-patterns
- **Tuning against the test set** — including "just peeking once."
- **Comparing models on different splits**, or reporting a single seed for a small dataset.
- **Believing the U-curve unconditionally.** See below: this is the one place where the 2016
text is now known to be incomplete.
## What changed after 2016
**This is the chapter's one substantive correction.** The classical U-shaped capacity curve is
not the whole picture. In the heavily overparameterized regime, test error can fall again past
the interpolation threshold — "double descent" (Belkin et al. 2019; Nakkiran et al. 2020), which
post-dates the book. Modern large models routinely sit in a regime the 2016 framing predicts
should overfit catastrophically and does not. The biasvariance decomposition remains correct as
algebra; the *managerial advice* "reduce capacity when you overfit" is no longer the only right
move. **Confidence: high** — double descent is widely replicated. Practical consequence: try
"more data / more regularization / train longer" before "smaller model."
## Key Takeaways
1. Write down T, P, E in one sentence before writing any model code.
2. Use the train/val gap to choose your next action; do not guess.
3. Hold the U-curve loosely — check whether you are past the interpolation threshold before
shrinking a model that overfits.
## Connects To
- **Ch 7**: every regularizer named here, in depth.
- **Ch 11**: this chapter's diagnostics turned into a workflow.
- **scripts/capacity_planner.py**: mechanizes the gap-to-action rule, double descent included.

View file

@ -0,0 +1,61 @@
# Chapter 6: Deep Feedforward Networks
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/mlp.html
## Core Idea
An MLP is a composed chain of parametric functions trained by gradient descent, where the choice
of output unit follows from the assumed output distribution and the choice of hidden unit follows
from gradient behaviour. Backpropagation is not learning; it is the chain rule scheduled well.
## Key Concepts
- **Universal approximation**: one sufficiently wide hidden layer can approximate any continuous
function on a compact set. It says nothing about learnability, sample efficiency, or the size
required — depth is how you get the same function with far fewer units.
- **Output units follow the distribution**: linear + MSE → Gaussian; sigmoid + binary
cross-entropy → Bernoulli; softmax + cross-entropy → categorical; mixture density → multimodal.
- **Hidden units**: ReLU as the sane default; leaky/parametric ReLU, ELU, GELU/Swish (post-2016)
for smoothness; sigmoid/tanh only where saturation is desired (gates).
- **Saturation**: sigmoid/tanh gradients vanish in the tails, which is why they are poor hidden
units and fine as gates.
- **Backpropagation**: reverse-mode automatic differentiation over the computation graph. Cost is
roughly one forward pass, memory is the stored activations.
- **Computation graph / autodiff**: the abstraction every framework implements. Forward mode is
cheap in inputs; reverse mode is cheap in outputs — losses are scalar, hence reverse.
## Mental Models
- Pick the output unit from the **likelihood** (Ch 3), then pick the loss as its negative log.
Every "which loss?" question reduces to "which distribution?"
- Read **ReLU's advantage as gradient preservation**, not nonlinearity per se: it is piecewise
linear, so the gradient through an active unit is exactly 1.
- Treat activation memory as the **real** cost of depth in training: the backward pass needs the
forward activations, which is why checkpointing trades compute for memory.
## Anti-patterns
- **Citing universal approximation to justify a shallow model** — the theorem allows an
exponentially wide layer, which is not an engineering plan.
- **Sigmoid hidden layers** in a deep stack.
- **Pairing a sigmoid output with MSE**: gradients vanish exactly where the model is most wrong.
Use cross-entropy.
## What changed after 2016
Smooth activations (GELU, SiLU/Swish) became the default in transformers; gated variants
(GLU, SwiGLU) are now standard in large language model feedforward blocks. Residual connections
(He et al. 2015) are mentioned here only in passing but became the structural default for every
deep stack. Reverse-mode autodiff is unchanged. **Confidence: high.**
## Key Takeaways
1. Derive the loss from the output distribution rather than picking it by habit.
2. Default to ReLU-family hidden units; reserve saturating units for gates.
3. Budget activation memory as a first-class constraint, not an implementation detail.
## Connects To
- **Ch 3**: the distributions that determine output units.
- **Ch 8**: why gradient preservation matters at depth.
- **scripts/model_arithmetic.py**: parameter, FLOP and activation-memory accounting for a stack.

View file

@ -0,0 +1,66 @@
# Chapter 7: Regularization for Deep Learning
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/regularization.html
## Core Idea
Regularization is anything that trades training error for generalization error, and this chapter
is the catalogue: norm penalties, data augmentation, noise, early stopping, parameter sharing,
sparsity, ensembling, dropout, and adversarial training — with their equivalences made explicit.
## Frameworks Introduced
- **L2 / weight decay**: shrinks parameters along low-curvature Hessian directions. Under a
quadratic approximation, it damps each eigen-direction by λᵢ/(λᵢ+α) — directions the loss does
not care about get pulled to zero.
- **L1**: yields genuine sparsity; equivalent to a Laplace prior on parameters.
- **Norm penalty as constraint**: via KKT (Ch 4), a penalty is a soft version of a norm ball.
Explicit projection (max-norm) is sometimes better behaved.
- **Dataset augmentation**: the most reliable regularizer when the invariance is real. Choose
transformations that preserve the label — and check that they do.
- **Noise injection**: on inputs (≈ L2 penalty for some models), on weights (encourages flat
minima), on labels (label smoothing).
- **Early stopping**: the cheapest regularizer; under a quadratic approximation it is
approximately equivalent to L2 with a strength set by the number of steps.
- **Parameter tying / sharing**: the strongest form — it removes parameters instead of penalizing
them. Convolution is parameter sharing (Ch 9).
- **Bagging and ensembles**: variance reduction by averaging independently trained models.
- **Dropout**: approximate ensembling over exponentially many sub-networks at the cost of one.
- **Adversarial training**: penalizing sensitivity to worst-case local perturbation.
## Mental Models
- Order regularizers by **cost per unit of gap closed**: more real data > augmentation > early
stopping > weight decay > dropout > architecture surgery.
- Read weight decay as **"forget the directions the data does not constrain"** — that is exactly
what the eigen-analysis says.
- Treat dropout as an **ensemble**, so its interaction with batch normalization (train/test
statistics mismatch) is expected rather than surprising.
## Anti-patterns
- **Stacking every regularizer at once** and then tuning — you cannot attribute the effect.
- **Augmenting with label-destroying transforms** (horizontal flip on digits, aggressive crops on
fine-grained classes).
- **Dropout inside a residual transformer block plus batch norm plus heavy weight decay** without
measuring; modern stacks regularize far more lightly than 2016 practice.
## What changed after 2016
Weight decay and L2 were shown to be *not* equivalent under adaptive optimizers, which is why
**AdamW** (Loshchilov & Hutter 2017/2019) decouples them — this post-dates the book and is now
the default. Dropout largely left large-scale vision and language models, displaced by
normalization, augmentation and sheer data volume. Label smoothing and stochastic depth became
common. **Confidence: high** for AdamW; **high** for the decline of dropout at scale.
## Key Takeaways
1. Add regularizers one at a time and measure the gap after each.
2. Use decoupled weight decay (AdamW) rather than L2-in-the-loss with an adaptive optimizer.
3. Prefer parameter sharing over penalties when a real invariance exists.
## Connects To
- **Ch 5**: the biasvariance budget these all spend from.
- **Ch 8**: optimizer choice changes what weight decay means.
- **Ch 11**: which regularizer to reach for, given a measured gap.

View file

@ -0,0 +1,67 @@
# Chapter 8: Optimization for Training Deep Models
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/optimization.html
## Core Idea
Training is not pure optimization: you minimize an empirical surrogate to reduce a risk you
cannot measure, on a non-convex landscape, with noisy gradients. The chapter separates the
difficulties (ill-conditioning, saddles, cliffs, long-term dependencies, poor correspondence
between local and global structure) from the algorithms that address them.
## Frameworks Introduced
- **Empirical risk minimization and its surrogates**: you optimize a differentiable proxy, not
the metric you report.
- **Minibatch SGD**: gradient noise scales roughly with 1/√batch, so bigger batches buy accuracy
in the gradient at linear cost — a poor trade past a point.
- **Ill-conditioning**: the dominant obstacle in practice; gradient norm can *grow* while the loss
stalls.
- **Saddle points, not local minima**: in high dimensions, critical points are overwhelmingly
saddles. This reframes the folklore fear of local minima.
- **Cliffs and exploding gradients****gradient clipping**.
- **Momentum** and **Nesterov momentum**: accumulate a velocity to cross ravines.
- **Initialization**: Xavier/Glorot and He scaling to keep activation and gradient variance
roughly constant with depth. Initialization is an algorithm, not a detail.
- **Adaptive methods**: AdaGrad (decaying), RMSProp, **Adam** (RMSProp + momentum + bias
correction).
- **Second-order methods**: Newton, conjugate gradient, BFGS/L-BFGS — and why they rarely survive
contact with minibatch noise and parameter counts.
- **Batch normalization**: reparameterization that stabilizes the scale of layer inputs.
- **Curriculum learning / coordinate descent / Polyak averaging**: the meta-strategies.
## Mental Models
- Diagnose by **what the gradient is doing**: norm exploding = cliff, clip. Norm large but loss
flat = ill-conditioning, use momentum/adaptive/normalization. Norm ~0 with high loss = dead
units or saturation.
- Treat **learning-rate schedule as a first-class hyperparameter** — usually more important than
the choice among SGD/Adam variants.
- Read batch norm as **making the loss surface better conditioned**; whether it does so by
reducing "internal covariate shift" is contested (Santurkar et al. 2018, post-2016).
## Anti-patterns
- **Fearing local minima**: spend the debugging effort on conditioning and learning rate.
- **Tuning the optimizer before the learning rate.**
- **Batch norm with tiny batches** — the batch statistics become noise. Use group/layer norm.
## What changed after 2016
The largest delta in Part II. **AdamW** replaced Adam+L2. Learning-rate **warmup plus cosine
decay** became standard for transformers. **LayerNorm** (and RMSNorm) displaced batch norm in
sequence models; pre-norm residual placement displaced post-norm for deep stacks. Large-batch
training with LARS/LAMB, and the linear-scaling-rule literature, arrived after the book.
**Confidence: high.**
## Key Takeaways
1. Tune learning rate and schedule first; optimizer family second.
2. Read gradient-norm behaviour before changing the architecture.
3. Use He/Xavier-style initialization deliberately — bad init is a common silent failure.
## Connects To
- **Ch 4**: conditioning, Hessians, and step size.
- **Ch 10**: exploding/vanishing gradients as the sequence-model version of these problems.
- **scripts/training_diagnostics.py**: this chapter's triage as an executable decision tree.

View file

@ -0,0 +1,66 @@
# Chapter 9: Convolutional Networks
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/convnets.html
## Core Idea
Convolution is three ideas at once — sparse interactions, parameter sharing, and equivariance to
translation — and each is a prior about grid-structured data. Pooling adds approximate invariance
to small translations. The architecture is a statement about the data, not a trick.
## Frameworks Introduced
- **Sparse interactions**: each output depends on a small receptive field, so cost drops from
O(m·n) to O(k·n).
- **Parameter sharing**: one kernel is reused at every position — the strongest regularizer in
Ch 7's catalogue, applied structurally.
- **Equivariance to translation**: shift the input, the feature map shifts. Convolution is *not*
equivariant to rotation or scale — a fact that motivates augmentation.
- **Pooling**: max/average pooling gives local invariance and downsampling; it is a prior that
small position changes should not matter.
- **Variants**: valid/same/full padding, strided convolution, dilated convolution, tiled
convolution, locally-connected layers (no sharing), transposed convolution for upsampling.
- **Convolution as an infinitely strong prior**: the chapter's sharpest framing — a conv layer is
a fully-connected layer with hard constraints on its weights.
- **Structured outputs**: dense prediction (segmentation) rather than one label per image.
- **Efficiency**: FFT-based and separable convolutions.
## Mental Models
- Ask "**is the statistic I need position-invariant?**" If yes, convolve. If not (a face-aligned
dataset, a tabular grid with meaningful coordinates), the prior is wrong and locally-connected
or attention layers may fit better.
- Compute **receptive field** deliberately: it must cover the evidence needed for the decision.
Depth, stride and dilation are three ways to buy it, with different costs.
- Treat pooling as **throwing away location on purpose**; when location is the answer
(segmentation, detection), pool less and use dilation or skip connections.
## Anti-patterns
- **Using convolution on data with no spatial/temporal locality** (arbitrary tabular columns) —
the sharing prior is simply false there.
- **Ignoring receptive field** and then adding parameters to fix an underfitting model.
- **Aggressive pooling in a dense-prediction task.**
## What changed after 2016
Residual networks (2015) are treated only briefly here but became the default. Since then:
depthwise-separable convolutions (MobileNet/Xception), EfficientNet-style compound scaling,
and — most importantly — **Vision Transformers** (Dosovitskiy et al. 2020), which discard the
convolutional prior in favour of data plus attention, and win at scale while ConvNets remain
competitive at smaller data sizes (ConvNeXt, 2022, closed much of the gap). The chapter's
argument that the conv prior is a *bet on the data* is exactly what ViT's data-hunger confirms.
**Confidence: high.**
## Key Takeaways
1. Justify convolution by the invariance you actually believe in.
2. Size the receptive field before adding depth for its own sake.
3. Expect the conv prior to pay off most when data is limited — this is the modern boundary
between ConvNets and ViTs.
## Connects To
- **Ch 7**: parameter sharing as structural regularization.
- **Ch 12**: computer-vision applications built on this.
- **references/book_to_2026_delta.md**: the ViT/ConvNeXt line.

View file

@ -0,0 +1,70 @@
# Chapter 10: Sequence Modeling — Recurrent and Recursive Nets
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/rnn.html
## Core Idea
Recurrence shares parameters across time the way convolution shares them across space, which lets
one model handle variable-length sequences. The price is that gradients must traverse many
multiplicative steps, producing the vanishing/exploding gradient problem — and gated
architectures exist to pay it.
## Frameworks Introduced
- **Unfolding the computational graph**: a recurrent definition becomes a deep feedforward graph
with tied weights.
- **BPTT (backpropagation through time)** and **truncated BPTT**.
- **Teacher forcing**: train on ground-truth previous tokens; note the train/inference mismatch
(exposure bias) it creates.
- **Vanishing and exploding gradients**: repeated multiplication by the recurrent Jacobian; the
spectral radius decides which.
- **Gradient clipping** for the exploding half; **gating** for the vanishing half.
- **LSTM** (input/forget/output gates plus a cell with an additive path) and **GRU** (a
two-gate simplification). The additive cell path is the mechanism — it makes the gradient path
through time approximately linear.
- **Bidirectional RNNs**; **encoderdecoder / sequence-to-sequence** with a fixed-size context.
- **Attention** appears here as the fix for the encoderdecoder bottleneck.
- **Deep RNNs, recursive (tree-structured) nets, echo state networks, leaky units, skip
connections through time.**
## Mental Models
- Read gating as **learned, data-dependent memory management**: the forget gate decides how long
the additive highway stays open.
- Treat the fixed-size context vector in vanilla seq2seq as a **bottleneck** — the whole reason
attention was invented.
- Expect **exposure bias** whenever you teacher-force: the model has never seen its own mistakes
during training.
## Anti-patterns
- **Reaching for an RNN by default in 2026** for a task where a transformer is the standard
baseline and the sequence fits in context.
- **Training a long-sequence RNN without gradient clipping.**
- **Ignoring the train/inference mismatch** in autoregressive generation.
## What changed after 2016
**The largest single delta in the book.** Attention, described here as an enhancement to
recurrent seq2seq, became the whole architecture with *Attention Is All You Need* (Vaswani et al.
2017) — one year after publication. Transformers replaced RNNs for essentially all large-scale
sequence work: parallel training over sequence positions, direct O(1) path length between any two
tokens, and much better scaling. What survived: gradient clipping, teacher forcing, exposure bias,
and the vanishing/exploding analysis. What returned: linear-time recurrent architectures
(S4/Mamba-style state-space models, 20212024) as a long-context alternative, which makes this
chapter's material relevant again rather than obsolete. **Confidence: high.**
**Read this chapter for the gradient-flow analysis, not for the architecture recommendation.**
## Key Takeaways
1. Learn the vanishing/exploding analysis here — it explains residual connections, LayerNorm
placement, and state-space models alike.
2. Clip gradients whenever a recurrence is in the graph.
3. Treat this chapter's architecture advice as historical; treat its diagnosis as current.
## Connects To
- **Ch 8**: the same optimization pathologies, in the time dimension.
- **Ch 12**: NLP and speech applications built on these.
- **references/book_to_2026_delta.md**: the transformer displacement, in detail.

View file

@ -0,0 +1,63 @@
# Chapter 11: Practical Methodology
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/guidelines.html
## Core Idea
Knowing many algorithms matters less than knowing which one to reach for given a measurement.
This chapter is a workflow: pick a metric, build an end-to-end baseline fast, then let
instrumentation — not intuition — decide whether to add data, capacity, or regularization.
## Frameworks Introduced
- **The design process**: (1) determine goals — the error metric and the target value; (2) build
a working end-to-end pipeline early; (3) instrument it to find bottlenecks; (4) change one
thing at a time based on measurement.
- **Choose the metric before the model**: accuracy, precision/recall, F-score, PR/ROC curves,
coverage. Name the target value and where it came from.
- **Sensible baselines**: pick the standard architecture and optimizer for the data type before
inventing anything.
- **More data or a bigger model?** — the decision procedure: if training error is high, the model
or the optimization is the bottleneck (data will not help). If training error is low and test
error is high, gather more data or regularize.
- **Hyperparameter tuning**: manual (understand what each knob does to effective capacity),
**grid search** (poor scaling in dimensions), **random search** (better — it does not waste
trials on unimportant dimensions; Bergstra & Bengio 2012), and model-based/Bayesian.
- **Debugging strategies**: visualize the model's actual predictions and worst cases; fit a tiny
subset to zero training error; compare backprop against numerical derivatives; monitor
activation and gradient histograms.
## Mental Models
- Use the **train-error-first rule** as the single most valuable heuristic in the book: high
training error means "do not collect data yet."
- Treat "**can it overfit 20 examples?**" as the smoke test that separates a bug from a modelling
limitation. If it cannot, you have a bug.
- Prefer **random search over grid search** whenever the number of hyperparameters exceeds ~2.
## Anti-patterns
- **Tuning many things per experiment** — you learn nothing attributable.
- **Collecting more data to fix underfitting.**
- **Optimizing a proxy metric** whose relationship to the real objective was never checked.
- **Skipping the end-to-end pipeline** in favour of perfecting one component.
## What changed after 2016
The workflow is the most durable material in the book and is now the backbone of MLOps practice.
Additions since: experiment tracking as standard tooling, seeded reproducibility expectations,
Hyperband/ASHA for early-stopping-based search (post-2016), and — for large models — scaling laws
used to *predict* the return on more data or parameters instead of testing empirically at full
size. **Confidence: high.**
## Key Takeaways
1. Write the metric and its target number before writing model code.
2. Ask "is training error high?" before every data or capacity decision.
3. Change one thing per experiment and log it.
## Connects To
- **Ch 5**: the underfit/overfit framing this operationalizes.
- **Ch 7 / Ch 8**: the two toolboxes the workflow selects from.
- **scripts/training_diagnostics.py**: this decision tree, executable.

View file

@ -0,0 +1,62 @@
# Chapter 12: Applications
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/applications.html
## Core Idea
How deep learning was actually deployed circa 2016: large-scale implementation (GPUs,
distributed training, model compression), then computer vision, speech recognition, and NLP.
This is the most time-dated chapter in the book — read the *systems* half, discount the
*state-of-the-art* half.
## Frameworks Introduced
- **Large-scale implementation**: GPU data parallelism, model parallelism, asynchronous SGD
(Hogwild-style), parameter servers.
- **Model compression**: distillation, quantization, pruning — for inference cost.
- **Dynamic structure / conditional computation**: cascades and gating so that not every input
pays the full cost.
- **Preprocessing in vision**: contrast normalization, whitening, dataset augmentation.
- **Speech**: the acoustic-model pipeline and its shift from GMM-HMM to deep networks.
- **NLP**: n-gram models, word embeddings and the curse of dimensionality over vocabularies,
hierarchical softmax and sampling-based approximations for large output vocabularies,
neural machine translation.
- **Recommender systems** and the exploration/exploitation problem.
- **Knowledge representation and relational reasoning.**
## Mental Models
- Separate **capability claims** (perishable) from **systems constraints** (durable). Memory
bandwidth, batch efficiency, and inference cost still shape architecture choices.
- Read the large-vocabulary softmax section as an instance of the general pattern: **when the
normalizing sum is expensive, approximate it** — the same problem Ch 18 attacks head-on.
- Treat conditional computation as the ancestor of **Mixture-of-Experts** routing.
## Anti-patterns
- **Citing this chapter's benchmark numbers or SOTA claims** — they are a decade old.
- **Copying its NLP pipeline**: subword tokenization (BPE/SentencePiece) and pretrained
transformers replaced nearly all of it.
## What changed after 2016
Almost everything at the application layer. Speech moved to end-to-end CTC/attention models and
then to large self-supervised encoders. NLP moved to pretrained transformers (BERT 2018, GPT
family), with subword tokenization and full-softmax over ~30k200k subwords making hierarchical
softmax largely unnecessary. Vision moved to self-supervised pretraining and ViTs. Distillation,
quantization and pruning grew into a mature inference-optimization discipline. Conditional
computation matured into sparse MoE. **Confidence: high.**
## Key Takeaways
1. Read this chapter for the systems reasoning and the approximation techniques, not for what is
state of the art.
2. When your output vocabulary or normalizing constant is huge, recognize it as the recurring
partition-function problem.
3. Plan inference cost as an architecture constraint from the start.
## Connects To
- **Ch 18**: the partition-function problem in its general form.
- **Ch 9 / Ch 10**: the architectures being applied here.
- **references/book_to_2026_delta.md**: what replaced each application pipeline.

View file

@ -0,0 +1,60 @@
# Chapter 13: Linear Factor Models
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/linear_factors.html
## Core Idea
The simplest generative models: sample latent factors from a simple prior, map them linearly to
observations, add noise. Probabilistic PCA, factor analysis, ICA, sparse coding and slow feature
analysis are all this one template with different priors — and they are the scaffolding for
everything in Chapters 1420.
## Key Concepts
- **The template**: h ~ p(h); x = Wh + b + noise. Change p(h) and the noise model, get a
different named method.
- **Factor analysis**: Gaussian latent prior, diagonal (per-feature) observation noise.
- **Probabilistic PCA**: factor analysis with isotropic noise; recovers PCA as noise → 0.
- **Independent component analysis (ICA)**: non-Gaussian independent latents — this is what makes
the factors identifiable, which Gaussian models cannot be (any rotation fits equally well).
- **Sparse coding**: a heavy-tailed (Laplace/Cauchy) prior; inference is an optimization, not a
closed form, which makes encoding expensive.
- **Slow feature analysis**: a prior that useful factors change slowly over time.
- **Manifold interpretation of PCA**: the model concentrates probability near a linear subspace.
## Mental Models
- Read each model as **a prior choice**, and read the prior as the assumption that buys
identifiability. Gaussian latents are rotation-invariant, so a Gaussian model cannot tell you
*which* factors — only which subspace.
- Treat sparse coding as the moment where **inference becomes iterative**; that cost is precisely
what autoencoders (Ch 14) amortize with a learned encoder.
- Use these as the **linear baseline** for any representation-learning claim: if a linear factor
model matches your deep encoder, the depth is not earning its cost.
## Anti-patterns
- **Skipping this chapter and starting at Ch 20** — VAEs read as arbitrary machinery without the
latent-variable template established here.
- **Expecting interpretable factors from a Gaussian-latent model.**
## What changed after 2016
The template survived; the emphasis moved. Nonlinear ICA identifiability results (Hyvärinen et
al., 20162020) clarified when latent factors are recoverable at all, and the disentanglement
literature — notably Locatello et al. (2019) — showed that unsupervised disentanglement is
impossible without inductive biases or supervision, which is a formal statement of this
chapter's identifiability point. Sparse coding returned as a tool for interpreting neural
networks (sparse autoencoders over LLM activations, 20232024). **Confidence: high.**
## Key Takeaways
1. Name the latent prior when you propose any generative model; it determines what is learnable.
2. Use a linear factor model as the baseline before claiming a deep representation helps.
3. Remember that identifiability, not fit quality, is what non-Gaussian priors buy.
## Connects To
- **Ch 14**: autoencoders amortize the inference these models do by optimization.
- **Ch 15**: what makes a representation good.
- **Ch 20**: the VAE is this template with a nonlinear decoder and amortized inference.

View file

@ -0,0 +1,64 @@
# Chapter 14: Autoencoders
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/autoencoders.html
## Core Idea
An autoencoder learns to copy its input imperfectly, and the constraint that prevents perfect
copying is where the learning happens. Undercompleteness, sparsity, denoising and contraction are
four different ways to impose that constraint — each defines a different notion of "useful".
## Frameworks Introduced
- **Undercomplete autoencoder**: bottleneck smaller than the input. With linear units and MSE it
recovers PCA's subspace.
- **Regularized autoencoders**: capacity can exceed the input dimension as long as something else
prevents identity — this is the chapter's key move.
- **Sparse autoencoder**: penalize code activation; interpretable as a latent prior (Ch 13).
- **Denoising autoencoder (DAE)**: corrupt the input, reconstruct the clean version. The learned
map estimates the *score* — it points back toward the data manifold, which is the direct
ancestor of score-based diffusion models.
- **Contractive autoencoder (CAE)**: penalize the Jacobian norm of the encoder, so the
representation resists input perturbation except along the manifold.
- **Manifold learning view**: the encoder is sensitive along tangent directions of the data
manifold and insensitive orthogonal to it.
- **Stochastic encoders and decoders**: autoencoders as p(h|x) and p(x|h).
- **Predictive sparse decomposition**; **applications**: dimensionality reduction, semantic
hashing, pretraining.
## Mental Models
- Ask "**what stops it from learning the identity?**" — the answer names the inductive bias, and
a model with no answer learns nothing useful.
- Read a DAE's learned vector field as **pointing uphill in density**. Once you see that,
diffusion models are the same idea run at many noise levels.
- Treat the encoder as **amortized inference**: it replaces the per-example optimization of
sparse coding with one forward pass.
## Anti-patterns
- **An overcomplete autoencoder with no regularizer** — it can and will learn a copy.
- **Judging representation quality by reconstruction error**: low reconstruction error can mean
the code memorized the input, which is the opposite of useful.
## What changed after 2016
The denoising idea became the foundation of modern generative modelling: denoising score matching
(Vincent 2011) → score-based models (Song & Ermon 2019) → DDPM (Ho et al. 2020) → the diffusion
family. Greedy layerwise autoencoder pretraining, presented here as a live technique, disappeared
— displaced first by better initialization/normalization and then by large-scale supervised and
self-supervised pretraining. The VAE overshadowed the deterministic autoencoders for generation,
while masked autoencoders (He et al. 2021) revived the corruption idea for vision pretraining.
**Confidence: high.**
## Key Takeaways
1. Always name the constraint that prevents identity before training an autoencoder.
2. Do not use reconstruction error as a representation-quality metric; evaluate downstream.
3. Learn the denoising/score connection here — it is the cheapest on-ramp to diffusion models.
## Connects To
- **Ch 13**: sparse coding, amortized.
- **Ch 15**: what a "good" representation means.
- **Ch 20**: VAEs, and the diffusion line that grew from denoising.

View file

@ -0,0 +1,64 @@
# Chapter 15: Representation Learning
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/representation.html
## Core Idea
What makes one representation better than another, and how do you get one without labels? The
chapter names the properties worth wanting — distributed, disentangled, capturing causal factors
— and the transfer mechanisms that let a representation earned on one task pay off on another.
## Frameworks Introduced
- **Greedy layer-wise unsupervised pretraining**: the historically important technique that
restarted the field in 2006; the chapter is already candid that its value had shrunk by 2016.
- **Transfer learning and domain adaptation**: reuse a representation across tasks or
distributions; **one-shot / zero-shot learning** as the limiting cases.
- **Distributed representations**: n binary features describe 2ⁿ regions, versus n regions for a
one-hot/symbolic code. This exponential advantage is the central argument for learned features.
- **Disentangled factors**: separate underlying causes onto separate directions.
- **Exponential gains from depth**: deeper composition of distributed features again multiplies
expressible structure.
- **Causal factors and semi-supervised learning**: unsupervised learning helps supervised learning
exactly when p(x) and p(y|x) share structure — if the factors generating x include y's causes.
- **Regularization priors that define good representations**: smoothness, linearity, multiple
explanatory factors, hierarchy, sparsity, simplicity of factor dependencies, shared factors
across tasks, manifolds, temporal/spatial coherence.
## Mental Models
- Judge a representation by **what becomes linearly separable** in it — that is the operational
version of "good features."
- Use the **shared-cause test** to predict whether unlabeled data will help: if p(x) tells you
nothing about p(y|x), self-supervision will not rescue a supervised task.
- Read distributed-vs-symbolic as **the reason embeddings beat lookup tables**, and note that the
advantage is combinatorial, not merely empirical.
## Anti-patterns
- **Expecting unsupervised pretraining to help unconditionally** — the chapter itself is careful
here, and the 2016-era conclusion (it often does not, for large labeled datasets) was correct
for the methods then available.
- **Claiming disentanglement without a metric or an intervention.**
## What changed after 2016
This chapter aged into relevance rather than out of it. Self-supervised learning became the
dominant paradigm — contrastive methods (SimCLR, MoCo, CLIP), masked prediction (BERT, MAE), and
next-token prediction at scale — vindicating the chapter's core bet while replacing every
specific method it lists. Two corrections: greedy layer-wise pretraining is now purely
historical, and unsupervised disentanglement was proven impossible without inductive bias
(Locatello et al. 2019). Linear-probe evaluation became the standard test of representation
quality. **Confidence: high.**
## Key Takeaways
1. Evaluate representations with linear probes and downstream transfer, not reconstruction.
2. Before investing in self-supervision, argue that p(x) and p(y|x) share causes.
3. Treat "disentangled" as a claim requiring an intervention-based test.
## Connects To
- **Ch 14**: autoencoders as one route to a representation.
- **Ch 1**: the promise made in the introduction, cashed out here.
- **references/book_to_2026_delta.md**: the self-supervised learning line.

View file

@ -0,0 +1,64 @@
# Chapter 16: Structured Probabilistic Models for Deep Learning
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/graphical_models.html
## Core Idea
A joint distribution over n variables is exponentially large; a graph that encodes conditional
independence makes it tractable. Directed models factor into conditionals, undirected models into
unnormalized potentials divided by a partition function — and that partition function is the bill
Chapters 1719 spend their pages paying.
## Frameworks Introduced
- **The challenge of unstructured modelling**: memory, statistical efficiency, and inference cost
all scale with the number of parameters in a full joint.
- **Directed models (Bayesian networks)**: p(x) = ∏ p(xᵢ | parents(xᵢ)). Normalized by
construction — no partition function.
- **Undirected models (Markov random fields)**: p(x) = (1/Z) ∏ φ_c(x_c) over cliques. Z is the
partition function, and it is a sum over all configurations.
- **Energy-based models**: p(x) ∝ exp(E(x)). Any positive distribution can be written this way.
- **Separation / d-separation**: reading conditional independence off the graph.
- **Converting between graph types; factor graphs** for disambiguating factorization.
- **Sampling from graphical models**: ancestral sampling (easy, directed) vs Gibbs sampling
(needed for undirected).
- **Structure learning and latent variables**; the **restricted Boltzmann machine (RBM)** as the
worked example.
## Mental Models
- Use the rule of thumb: **directed = easy sampling, harder inference with explaining-away;
undirected = natural for mutual constraints, hard normalization.**
- Read an energy function as a **soft constraint set**: low energy where constraints are
satisfied. Design E, and p follows.
- Remember that the partition function is not an inconvenience — it is **the** obstacle that
organizes all of Part III.
## Anti-patterns
- **Writing an undirected model and ignoring Z** until training refuses to work.
- **Assuming a graph's missing edge means independence in the data** — it means the *model*
asserts independence.
## What changed after 2016
Deep undirected graphical models (deep Boltzmann machines, RBM stacks) are now largely historical
as generative workhorses. But energy-based modelling did not die: it returned via score matching
and diffusion (which sidestep Z entirely by learning ∇ log p rather than p), and via
energy-based reinterpretations of contrastive learning. Autoregressive factorization — the
directed side of this chapter — became the dominant paradigm through transformer language models,
which are exactly chain-rule factorizations with a huge neural conditional. **Confidence: high.**
## Key Takeaways
1. Classify any generative proposal as directed or undirected first; it predicts which problems
you will have.
2. When Z is intractable, look for a formulation that never needs it (score, ratio, or
autoregressive).
3. Read modern LLMs as ancestral sampling from a directed chain — the framing here still applies.
## Connects To
- **Ch 1719**: the three responses to intractability (sample it, approximate Z, approximate the
posterior).
- **Ch 20**: the models built on these foundations.

View file

@ -0,0 +1,60 @@
# Chapter 17: Monte Carlo Methods
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/monte_carlo.html
## Core Idea
When a sum or integral is intractable, estimate it with samples. The estimator is unbiased and
its error shrinks as 1/√n regardless of dimension — which is why sampling survives where
quadrature does not. The difficulty moves from computing the integral to obtaining the samples.
## Key Concepts
- **Monte Carlo estimation**: approximate E_p[f(x)] by the sample mean; variance falls as 1/n,
standard error as 1/√n.
- **Importance sampling**: sample from a tractable q and reweight by p/q. Variance depends
entirely on how well q matches p·f — a bad proposal gives an estimator that is unbiased and
useless.
- **Markov chain Monte Carlo (MCMC)**: build a chain whose stationary distribution is the target,
then use its states as (correlated) samples.
- **Gibbs sampling**: resample each variable from its conditional given the rest; the natural
MCMC scheme for graphical models.
- **Burn-in / mixing time**: the chain needs time to forget its initialization and to move
between modes.
- **The mixing problem between separated modes**: with well-separated modes, transition
probability between them is tiny and the chain reports a single mode as if it were everything.
- **Tempering / annealing** as remedies: flatten the distribution so the chain can travel.
## Mental Models
- Treat a Monte Carlo estimate as a **measurement with error bars**; report the standard error,
because "the estimate is unbiased" says nothing about whether n was large enough.
- Diagnose a suspiciously confident sampler as a **mixing failure**, not a modelling success.
- Read importance sampling's variance condition as: **you must already know roughly where the
mass is** — this is why proposals matter more than sample counts.
## Anti-patterns
- **Reporting MCMC samples without a mixing diagnostic.**
- **Trusting importance weights with huge dynamic range** — an effective sample size of ~1 is
common and invisible unless measured.
## What changed after 2016
The chapter's methods remain textbook-correct, but their role in deep generative modelling
shrank: diffusion models replaced slow MCMC-based sampling with a fixed, finite denoising chain,
and modern generation is dominated by ancestral sampling from autoregressive models. Where MCMC
is still used — Bayesian deep learning, some energy-based models — HMC/NUTS variants dominate
over plain Gibbs. **Confidence: high.**
## Key Takeaways
1. Always pair a Monte Carlo estimate with its standard error.
2. Check mixing before believing anything an MCMC sampler tells you about multimodality.
3. Recognize the pattern "intractable expectation → sample it" — it recurs throughout Ch 1820.
## Connects To
- **Ch 16**: the undirected models that need sampling in the first place.
- **Ch 18**: sampling as an ingredient in partition-function estimation.
- **Ch 20**: sampling as generation.

View file

@ -0,0 +1,69 @@
# Chapter 18: Confronting the Partition Function
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/partition.html
## Core Idea
For undirected models, the log-likelihood gradient splits into a positive phase (push energy down
on data) and a negative phase (push energy up everywhere the model believes) — and the negative
phase requires samples from the model itself. Every technique in this chapter is a way to afford
that negative phase, or to avoid needing Z at all.
## Frameworks Introduced
- **Positive and negative phase**: the gradient of log Z is an expectation under the *model*.
This is the structural reason undirected models are expensive.
- **Contrastive divergence (CD-k)**: initialize the negative chain at the data and run k steps.
Fast; biased; produces spurious modes in regions the short chain never visits.
- **Stochastic maximum likelihood / persistent CD (PCD)**: keep the chain's state across parameter
updates so it has effectively run for a long time. Better mixing, at the cost of a chain that
can fall behind fast-moving parameters.
- **Pseudolikelihood**: replace the joint with a product of conditionals — Z cancels. Cheap; a
different objective, so it optimizes for a different thing.
- **Score matching**: match ∇_x log p instead of p, which eliminates Z because the gradient of
log Z with respect to x is zero. **Ratio matching** and **denoising score matching** are the
variants.
- **Noise-contrastive estimation (NCE)**: turn density estimation into a classification problem —
real data versus noise — and treat the normalizer as a learned parameter.
- **Annealed importance sampling (AIS)** and **bridge sampling**: estimate Z itself, mainly for
evaluation.
## Mental Models
- Read the whole chapter as **four escape routes from Z**: sample it (CD/PCD), sidestep it
(pseudolikelihood, score matching), learn around it (NCE), or estimate it for evaluation only
(AIS).
- Treat score matching's trick — **differentiate with respect to x, not θ, so Z vanishes** — as
the single most consequential idea in Part III for modern practice.
- Expect **spurious modes** from short-chain training; they are a predictable artifact, not a bug
in your code.
## Anti-patterns
- **Comparing likelihoods across undirected models without estimating Z** — the numbers are not
comparable.
- **Using CD-1 and reporting it as maximum likelihood.**
## What changed after 2016
Score matching's downstream career is the story here. Denoising score matching plus a noise
schedule became score-based generative modelling (Song & Ermon 2019) and DDPM (Ho et al. 2020) —
the diffusion family that now dominates image, audio and video generation. NCE became the
backbone of contrastive representation learning (word2vec's negative sampling, then InfoNCE and
CLIP). AIS remains the standard tool for evaluating likelihoods when Z is unknown. Contrastive
divergence and PCD are largely historical. **Confidence: high.**
**This is the chapter whose ideas travelled furthest — read it even if you never train a
Boltzmann machine.**
## Key Takeaways
1. When a normalizer blocks you, ask which of the four escape routes fits your objective.
2. Learn score matching properly; diffusion models are unintelligible without it.
3. Never compare unnormalized likelihoods.
## Connects To
- **Ch 17**: the sampling machinery the negative phase depends on.
- **Ch 14**: denoising autoencoders as score estimators.
- **Ch 20**: the generative models built from these objectives.

View file

@ -0,0 +1,63 @@
# Chapter 19: Approximate Inference
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/inference.html
## Core Idea
Computing p(h|x) — the posterior over latents — is intractable for most interesting models. The
fix is to reframe inference as optimization: choose a tractable family q, and maximize a lower
bound on the log-likelihood. The gap between the bound and the truth is exactly a KL divergence.
## Frameworks Introduced
- **Inference as optimization**: pick q(h) to maximize the **evidence lower bound (ELBO)**,
L(q) = log p(x) D_KL(q(h) ‖ p(h|x)). Maximizing L both fits the model and tightens the bound.
- **Expectation maximization (EM)**: alternate between setting q to the current posterior
(E-step) and maximizing with respect to parameters (M-step).
- **MAP inference and sparse coding**: taking a point estimate of h is a degenerate q (a Dirac);
sparse coding's inference step is exactly MAP inference.
- **Variational inference and mean field**: restrict q to a factorized family, q(h) = ∏ q(hᵢ),
and derive fixed-point updates. Tractability is bought with an independence assumption.
- **Reverse-KL consequences**: the ELBO uses D(q‖p), which is mode-seeking — variational
posteriors are characteristically **too narrow**, and underestimate uncertainty.
- **Learned approximate inference / amortization**: train a network to output q's parameters
directly, replacing per-example optimization with one forward pass.
## Mental Models
- Read the ELBO as **"log-likelihood minus the cost of your approximation"** — improving q and
improving the model are the same optimization.
- Expect **underestimated variance** from mean-field posteriors, and never report variational
uncertainty as calibrated without checking.
- Treat amortization as the **encoder** of Chapter 14: the VAE is exactly this idea plus the
reparameterization trick.
## Anti-patterns
- **Reporting a mean-field posterior's credible intervals as if they were exact.**
- **Blaming the model for a poor fit** that is actually a too-restrictive q — diagnose the bound
before the model.
## What changed after 2016
Amortized variational inference became routine (VAEs and descendants); normalizing flows and
importance-weighted bounds (IWAE) gave tighter, more expressive posteriors than mean field. But
the strategic picture changed more: modern large generative models largely **avoid latent-variable
posteriors altogether** — autoregressive transformers have no posterior to infer, and diffusion
models use a fixed forward process, so their "inference" is trivial by construction. Variational
inference remains central in Bayesian deep learning and in structured latent-variable modelling.
**Confidence: high.**
## Key Takeaways
1. Write the ELBO down for any latent-variable model you train; it tells you what you are
actually optimizing.
2. Assume a mean-field posterior is over-confident until proven otherwise.
3. Ask whether your problem needs a latent posterior at all — many modern designs are structured
to avoid one.
## Connects To
- **Ch 13 / Ch 14**: the latent-variable models needing inference, and amortization.
- **Ch 20**: the VAE, assembled from this chapter plus the reparameterization trick.
- **Ch 3**: the KL asymmetry that dictates the narrow-posterior failure mode.

View file

@ -0,0 +1,67 @@
# Chapter 20: Deep Generative Models
**Source chapter (free, official):** https://www.deeplearningbook.org/contents/generative_models.html
## Core Idea
The book's capstone: every generative model family circa 2016, organized by how it handles the
intractable quantity. Boltzmann machines and their deep variants pay for the partition function;
VAEs bound the likelihood; GANs avoid likelihood entirely; autoregressive models factor it away.
That taxonomy — **not** the specific models — is what still holds.
## Frameworks Introduced
- **Boltzmann machines, RBMs, deep belief networks, deep Boltzmann machines**: energy-based
models trained with the Ch 18 machinery. Historically pivotal; now largely superseded.
- **Variational autoencoder (VAE)**: an encoder produces q(h|x), a decoder produces p(x|h), and
the **reparameterization trick** makes the sampling step differentiable so the ELBO can be
optimized by backprop. Blurry samples are the predictable consequence of the likelihood
objective plus a limited posterior family.
- **Generative adversarial networks (GANs)**: a generator and a discriminator in a minimax game;
no explicit likelihood, sharp samples, unstable training, and mode collapse as the
characteristic failure.
- **Autoregressive / fully-visible belief networks**: factor p(x) by the chain rule and model each
conditional. Exact likelihood, sequential sampling. (NADE, PixelRNN/PixelCNN, WaveNet era.)
- **Generative stochastic networks; denoising-based generation**: learning a transition operator
rather than a distribution — the direct ancestor of diffusion.
- **Evaluating generative models**: the chapter's warning that likelihood, sample quality and
downstream usefulness are **three different axes** that routinely disagree.
## Mental Models
- Classify any new generative model by **what it does about the intractable term**: bound it,
avoid it, factor it away, or learn a sampler directly. New families are new answers to that one
question.
- Read blurriness vs mode collapse as **the KL asymmetry from Ch 3 made visible**: likelihood-based
models cover modes and blur; adversarial models sharpen and drop modes.
- Never accept a **single** evaluation number for a generative model.
## Anti-patterns
- **Comparing FID across papers with different preprocessing** — the metric is not portable.
- **Treating sample quality as evidence of density estimation quality**, or vice versa.
- **Starting a new project with a Boltzmann machine.**
## What changed after 2016
The most-superseded chapter in the book, and worth reading anyway for its taxonomy.
**Diffusion models** (Ho et al. 2020, built on Ch 18's denoising score matching and Ch 14's
denoising autoencoders) displaced GANs for image, audio and video generation. **Autoregressive
transformers** became the dominant generative model overall — the chain-rule factorization
described here, scaled. VAEs persist mainly as latent-space compressors inside latent diffusion
pipelines rather than as end-user generators. GANs remain useful for fast, low-step generation.
Boltzmann machines are history. Evaluation remains unsolved, exactly as the chapter warned.
**Confidence: high.**
## Key Takeaways
1. Use the taxonomy, not the model list — it classifies architectures invented since.
2. Expect blurring from likelihood objectives and mode-dropping from adversarial ones; pick your
failure mode deliberately.
3. Evaluate generative models on at least likelihood, sample quality, and downstream use.
## Connects To
- **Ch 18**: score matching, whose descendants replaced most of this chapter.
- **Ch 19**: the ELBO the VAE optimizes.
- **references/book_to_2026_delta.md**: the diffusion and autoregressive-transformer lines.

View file

@ -0,0 +1,73 @@
# Cheatsheet
Decision rules and thresholds. One line each; the chapter has the reasoning.
## Loss selection (ch03, ch06)
| Target | Distribution | Output unit | Loss |
|---|---|---|---|
| Real, unbounded | Gaussian | linear | MSE |
| Binary | Bernoulli | sigmoid | binary cross-entropy |
| One of K | Categorical | softmax | cross-entropy |
| Real, heavy-tailed | Laplace | linear | MAE |
| Multimodal real | Mixture | mixture density | NLL of the mixture |
Never pair sigmoid output with MSE — the gradient vanishes where the model is most wrong.
## Underfit vs overfit (ch05, ch11)
| Train error | Val error | Verdict | First action |
|---|---|---|---|
| High | High | Underfit / optimization | Check LR, init, capacity — **not** more data |
| Low | High | Overfit | More data → augmentation → regularization |
| Low | Low | Working | Stop; check the metric is the right one |
| ~0 on 20 examples: fails | — | Bug | Fix the pipeline before anything else |
Past the interpolation threshold, prefer more data / longer training / more regularization over
shrinking the model (double descent, ch05).
## Optimizer defaults (ch08)
| Situation | Reach for |
|---|---|
| Any starting point | AdamW, LR ~1e-3 (small nets) / ~1e-4 (large), warmup + cosine decay |
| Recurrence in the graph | Add gradient clipping, always |
| Tiny batches | Group/layer norm, not batch norm |
| Loss flat, grad norm large | Ill-conditioning — momentum, adaptive, or normalization |
| Loss NaN | Numerics first: log(0), div by ~0, exp overflow, exploding grad |
## Regularization ladder (ch07)
More real data → label-preserving augmentation → early stopping → decoupled weight decay →
label smoothing → dropout → smaller model. One at a time; measure the gap after each.
## Architecture prior (ch09, ch10)
| Data | Prior that fits | Note |
|---|---|---|
| Grid, translation-invariant statistics | Convolution | Cheapest when data is limited |
| Sequence, long-range dependence | Attention/transformer | The 2016 RNN advice is superseded |
| Sequence, very long context | State-space / linear recurrence | Post-2016; ch10's gradient analysis applies |
| Arbitrary tabular columns | Neither | Locality prior is false |
## Generative model taxonomy (ch20)
| Family | Handles Z by | Characteristic failure |
|---|---|---|
| Autoregressive | Chain rule — no Z | Slow sequential sampling |
| VAE | Bounding likelihood (ELBO) | Blurry samples |
| GAN | Avoiding likelihood | Mode collapse, unstable training |
| Diffusion / score-based | Learning ∇ log p | Many sampling steps (mitigable) |
| Boltzmann machines | Sampling the negative phase | Historical; do not start here |
## Numerical hygiene (ch04)
Log-space for probability products · stabilized/fused softmax and cross-entropy · clip gradients
with recurrence · bf16 over fp16 when range matters · check condition number before blaming LR.
## Study-order rule (ch01ch20)
Ch 5 and Ch 11 are the highest-value chapters for a practitioner and can be read early.
Ch 24 are prerequisites for Ch 8 specifically. Ch 13→14→19→20 is the only strict chain in
Part III. Ch 18 is worth reading even if you never train an undirected model — score matching
became diffusion.

View file

@ -0,0 +1,58 @@
# Glossary
Terms as this skill uses them, with the chapter that develops each. Definitions are written for
lookup, not for teaching — read the chapter file for the reasoning.
- **Adam / AdamW** (ch08, ch07) — adaptive optimizer combining momentum with per-parameter scaling. AdamW decouples weight decay from the gradient, which Adam+L2 does not do correctly.
- **Amortized inference** (ch19, ch14) — training a network to predict a posterior's parameters instead of optimizing per example.
- **Ancestral sampling** (ch16) — sampling a directed model by drawing each variable after its parents.
- **Attention** (ch10) — a learned weighted read over a set of positions; introduced here as a fix for the seq2seq bottleneck, later the whole architecture.
- **Backpropagation** (ch06) — reverse-mode automatic differentiation over the computation graph.
- **Batch normalization** (ch08) — reparameterization normalizing layer inputs by batch statistics.
- **Biasvariance decomposition** (ch05) — expected error as bias² + variance + irreducible noise.
- **Capacity, effective vs representational** (ch05) — functions reachable by the optimizer vs functions expressible by the architecture.
- **Condition number** (ch02, ch04) — ratio of largest to smallest singular value; how amplified small perturbations become.
- **Contrastive divergence (CD-k)** (ch18) — biased approximation of the negative phase using a short chain started at the data.
- **Cross-entropy** (ch03) — H(p,q) = H(p) + D_KL(p‖q); minimizing it over q minimizes KL.
- **Curse of dimensionality** (ch05, ch01) — configurations grow exponentially with dimension, defeating local-interpolation methods.
- **Denoising autoencoder (DAE)** (ch14) — reconstructs clean input from a corrupted copy; its learned map estimates the score.
- **Disentangled representation** (ch15) — separate generative factors on separate directions.
- **Distributed representation** (ch15) — n features describing exponentially many regions, versus one-hot's n.
- **d-separation** (ch16) — reading conditional independence off a directed graph.
- **Double descent** (ch05) — test error falling again past the interpolation threshold; post-dates the book and qualifies its U-curve.
- **ELBO** (ch19) — evidence lower bound; log p(x) minus KL(q ‖ posterior).
- **Empirical risk minimization** (ch08) — minimizing training loss as a surrogate for unmeasurable true risk.
- **Energy-based model** (ch16) — p(x) ∝ exp(E(x)).
- **Equivariance** (ch09) — a shift in input produces the corresponding shift in output; convolution's defining property.
- **Exposure bias** (ch10) — train/inference mismatch from teacher forcing.
- **Gradient clipping** (ch08, ch10) — rescaling gradients above a norm threshold to survive cliffs.
- **Ill-conditioning** (ch04, ch08) — wide Hessian eigenvalue spread; loss stalls while gradient norm stays large.
- **Importance sampling** (ch17) — sampling from q and reweighting by p/q.
- **KL divergence** (ch03) — asymmetric divergence between distributions; direction decides mode-covering vs mode-seeking.
- **Manifold hypothesis** (ch05, ch14) — real data concentrates near a low-dimensional manifold.
- **Maximum likelihood estimation (MLE)** (ch05) — parameters maximizing data probability; the justification for standard losses.
- **Mean field** (ch19) — factorized variational family; buys tractability with an independence assumption.
- **Mixing time / burn-in** (ch17) — steps an MCMC chain needs before its samples are usable.
- **Mode collapse** (ch20) — a generator covering only part of the data distribution.
- **Momentum / Nesterov momentum** (ch08) — velocity accumulation across gradient steps.
- **No Free Lunch theorem** (ch05) — averaged over all distributions, all learners tie; priors carry all leverage.
- **Noise-contrastive estimation (NCE)** (ch18) — density estimation recast as data-versus-noise classification.
- **Partition function (Z)** (ch16, ch18) — the normalizer of an undirected model; the central intractability of Part III.
- **Persistent contrastive divergence (PCD)** (ch18) — CD with a chain persisted across updates.
- **Pooling** (ch09) — local aggregation giving approximate invariance to small translations.
- **Positive / negative phase** (ch18) — the two terms of an undirected model's likelihood gradient.
- **Pseudolikelihood** (ch18) — product of conditionals, in which Z cancels.
- **Receptive field** (ch09) — the input region influencing one output unit.
- **Regularization** (ch07, ch05) — any change intended to reduce generalization error but not training error.
- **Reparameterization trick** (ch20) — expressing a sample as a differentiable function of noise, making the ELBO backprop-able.
- **Representation learning** (ch15, ch01) — learning features rather than hand-designing them.
- **Saddle point** (ch08) — critical point that is a minimum in some directions and a maximum in others; the dominant critical point in high dimensions.
- **Score matching** (ch18) — matching ∇_x log p instead of p, so Z vanishes; the basis of diffusion models.
- **SGD, minibatch** (ch08) — gradient descent on noisy gradients from data subsets.
- **Singular value decomposition (SVD)** (ch02) — A = U D Vᵀ for any matrix.
- **Sparse coding** (ch13) — heavy-tailed latent prior with inference by optimization.
- **Teacher forcing** (ch10) — training an autoregressive model on ground-truth history.
- **Universal approximation theorem** (ch06) — one wide hidden layer suffices in principle; silent on width, learnability and sample cost.
- **Vanishing / exploding gradients** (ch10, ch08) — repeated Jacobian multiplication shrinking or growing gradients through depth or time.
- **Variational autoencoder (VAE)** (ch20, ch19) — amortized variational inference plus the reparameterization trick.
- **Weight decay** (ch07) — pulling parameters toward zero; equivalent to L2 for SGD, not for Adam.

View file

@ -0,0 +1,92 @@
# Patterns
Recurring techniques from the book, stated as instruments with their trade-offs. Each names the
chapter that develops it.
## Derive the loss from the output distribution (ch03, ch06)
Choose what p(y|x) is, then take its negative log. Gaussian → MSE, Bernoulli → binary
cross-entropy, categorical → cross-entropy, Laplace → MAE, mixture → mixture density loss.
**Trade-off:** none — this is strictly better than picking a loss by habit. **Failure mode it
prevents:** MSE on bounded, count-valued or heavily skewed targets.
## Work in log-space (ch04)
Sums of logs instead of products of probabilities; stabilized softmax and `log_softmax` rather
than hand-rolled exp/normalize. **Trade-off:** slightly more care at implementation time.
**Prevents:** silent underflow, NaN losses, and inf logits.
## Train-error-first triage (ch11, ch05)
Read training error before deciding anything. High training error → capacity or optimization is
the bottleneck; more data will not help. Low training error with high validation error → data or
regularization. **Trade-off:** requires honest, non-leaky splits. **Prevents:** the most expensive
common mistake, which is collecting data to fix underfitting.
## Overfit a tiny subset as a smoke test (ch11)
Take 1050 examples and drive training loss to ~0. If you cannot, you have a bug — not a hard
problem. **Trade-off:** minutes. **Prevents:** weeks of tuning around a broken data pipeline,
a wrong loss reduction, or a detached gradient.
## Random search over grid search (ch11)
With more than about two hyperparameters, random search finds better configurations for the same
budget because it does not spend trials re-testing unimportant dimensions. **Trade-off:** results
are less tidy to tabulate. **Prevents:** exponential waste in dimensions that do not matter.
## Regularize in cost order (ch07)
More real data → augmentation with label-preserving transforms → early stopping → weight decay →
dropout → architecture change. Add one at a time and measure the train/val gap after each.
**Trade-off:** slower than stacking everything. **Prevents:** an unattributable result you cannot
tune.
## Parameter sharing over parameter penalties (ch07, ch09)
When a real invariance exists, encode it structurally (convolution, weight tying) rather than
penalizing a free parameter into behaving. **Trade-off:** the prior is hard — wrong invariance
means a wrong model, with no way for data to override it. **Prevents:** paying for capacity you
then have to regularize away.
## Diagnose by gradient behaviour (ch08, ch04)
Gradient norm exploding → clip. Norm large, loss flat → ill-conditioning; use momentum, an
adaptive optimizer, or normalization. Norm near zero with high loss → saturation or dead units;
check initialization and activations. Loss NaN → numerics before modelling. **Trade-off:**
requires instrumentation. **Prevents:** changing the architecture to fix an optimizer problem.
## Tune learning rate and schedule before optimizer family (ch08)
The schedule usually dominates the choice among SGD/Adam variants. **Trade-off:** none. **Prevents:**
optimizer-shopping while the real problem is a step size two orders of magnitude off.
## Name what prevents the identity map (ch14)
Every autoencoder needs an answer: bottleneck, sparsity penalty, input corruption, or Jacobian
contraction. **Trade-off:** each constraint defines a different notion of useful.
**Prevents:** an overcomplete autoencoder that learns a copy and reports a low loss.
## Escape the partition function deliberately (ch18, ch16)
Four routes: sample the negative phase (CD/PCD), sidestep Z algebraically (pseudolikelihood,
score matching), learn around it (NCE), or estimate it for evaluation only (AIS). **Trade-off:**
each optimizes a different objective, so they are not interchangeable. **Prevents:** discovering
mid-project that your undirected model cannot be trained or compared.
## Pick your generative failure mode (ch20, ch03)
Likelihood-based objectives cover modes and blur. Adversarial objectives sharpen and drop modes.
This follows from KL direction, so it is a design choice, not bad luck. **Trade-off:** you must
decide which error your application tolerates. **Prevents:** treating blurriness as a bug to be
tuned away.
## Evaluate representations by transfer, not reconstruction (ch15, ch14)
Linear probes and downstream task performance. **Trade-off:** needs a downstream task.
**Prevents:** optimizing reconstruction error into a code that memorized the input.
## Report Monte Carlo estimates with error bars (ch17)
Standard error and a mixing diagnostic, always. **Trade-off:** more reporting.
**Prevents:** a confidently unimodal answer from a chain that never left its starting mode.

View file

@ -0,0 +1,101 @@
# The 2016 → 2026 Delta
The book was published in 2016. *Attention Is All You Need* appeared in 2017. Everything below
tracks what a reader should hold, discount, or replace — per chapter, with a confidence level on
each claim.
Confidence levels: 🟢 well-established and replicated · 🟡 supported but contested or
context-dependent · 🔴 folklore, named as folklore.
---
## Chapters that aged well (read as current)
| Ch | Why it holds |
|---|---|
| 2, 3, 4 | Mathematics does not age. 🟢 |
| 5 | The learning-theory frame is current — with one correction (double descent, below). 🟢 |
| 11 | The practical workflow became the backbone of MLOps practice. 🟢 |
| 16 | The directed/undirected taxonomy classifies models invented since, including transformers as chain-rule factorizations. 🟢 |
| 18 | Score matching became diffusion; NCE became contrastive learning. The chapter's ideas travelled further than its models. 🟢 |
## The five corrections that matter
### 1. Double descent qualifies the U-curve (ch05)
The classical capacity curve — error falls, then rises past the optimum — is incomplete. Past the
interpolation threshold, test error can descend a second time. Belkin et al. (2019) named it;
Nakkiran et al. (2020) showed model-wise, epoch-wise and sample-wise variants in deep networks.
The biasvariance algebra is unchanged; the *advice* "shrink the model when it overfits" is no
longer the only correct move. 🟢
### 2. AdamW: weight decay ≠ L2 under adaptive optimizers (ch07, ch08)
Adding an L2 term to the loss and applying weight decay to the update are equivalent for plain
SGD and **not** equivalent for Adam, because the adaptive denominator rescales the penalty.
Loshchilov & Hutter (2017/2019) decoupled them; AdamW is now the default. The book's Ch 7 treats
the two as interchangeable. 🟢
### 3. Transformers displaced recurrence (ch10, ch12)
Vaswani et al. (2017) removed recurrence entirely: attention gives an O(1) path between any two
positions and parallelizes over sequence length. What survives from Ch 10: the vanishing/exploding
gradient analysis, gradient clipping, teacher forcing, exposure bias. What is superseded: the
architecture recommendation. Note the return of linear-time recurrence in state-space models
(S4, 2021; Mamba, 2023) for long context — which makes Ch 10's analysis live again. 🟢
### 4. Diffusion displaced the Part III generative models (ch14, ch18, ch20)
The line runs directly through the book: denoising autoencoders (Ch 14) → denoising score
matching (Ch 18) → score-based generative models (Song & Ermon, 2019) → DDPM (Ho et al., 2020).
Diffusion now dominates image, audio and video generation; autoregressive transformers dominate
text. VAEs survive mainly as latent-space compressors inside latent-diffusion pipelines. GANs
remain useful for few-step generation. Boltzmann machines are historical. 🟢
### 5. Self-supervised learning vindicated Ch 15 while replacing its methods
The chapter's bet — that unsupervised representation learning would matter — was right, and every
specific method it lists was replaced. Contrastive (SimCLR, MoCo, CLIP), masked prediction (BERT,
MAE) and next-token prediction at scale are the modern routes. Two corrections: greedy layer-wise
pretraining is now purely historical 🟢, and unsupervised disentanglement was shown impossible
without inductive biases or supervision (Locatello et al., 2019) 🟢.
## Additions the book has no chapter for
| Topic | Status |
|---|---|
| **Neural scaling laws** (Kaplan 2020; Hoffmann 2022) | Quantifies Ch 1's "scale matters" and Ch 11's data-vs-capacity decision. 🟢 |
| **Normalization placement** — pre-norm vs post-norm residual, LayerNorm/RMSNorm over BatchNorm | Standard for deep sequence stacks. 🟢 |
| **Warmup + cosine decay schedules** | Standard for transformer training. 🟢 |
| **Calibration** (Guo et al., 2017) | Modern networks are systematically overconfident; temperature scaling is the cheap fix. Ch 3 does not mention it. 🟢 |
| **RLHF / DPO alignment** | Entirely outside the book. 🟢 |
| **Mixture-of-Experts** | The mature form of Ch 12's conditional computation. 🟢 |
| **Mixed precision (fp16 loss scaling, bf16)** | Made Ch 4's numerics an operational daily concern. 🟢 |
| **Lottery-ticket / pruning theory** (Frankle & Carbin, 2019) | Active; the strong form remains contested. 🟡 |
| **"Batch norm works by reducing internal covariate shift"** | The original explanation; challenged by Santurkar et al. (2018), who attribute the effect to smoothing the loss landscape. Treat the mechanism as unsettled. 🟡 |
| **"Local minima are the problem in deep nets"** | 🔴 Folklore the book itself corrects: high-dimensional critical points are overwhelmingly saddles (Ch 8). |
| **"You need a GPU cluster to learn deep learning"** | 🔴 Folklore. Every mechanism in Parts III is observable on a laptop-scale model. |
## How to use this file
When a chapter's advice conflicts with current practice, the conflict is almost always in the
**recommendation**, not the **analysis**. The book explains why things fail; the field has changed
what it reaches for. Keep the diagnosis, replace the prescription.
## Sources
1. Vaswani et al., "Attention Is All You Need," NeurIPS 2017 — arXiv:1706.03762.
2. Loshchilov & Hutter, "Decoupled Weight Decay Regularization," ICLR 2019 — arXiv:1711.05101.
3. Belkin, Hsu, Ma & Mandal, "Reconciling modern machine-learning practice and the classical
biasvariance trade-off," PNAS 116(32), 2019; Nakkiran et al., "Deep Double Descent," ICLR 2020.
4. Ho, Jain & Abbeel, "Denoising Diffusion Probabilistic Models," NeurIPS 2020 — arXiv:2006.11239;
Song & Ermon, "Generative Modeling by Estimating Gradients of the Data Distribution,"
NeurIPS 2019.
5. Kaplan et al., "Scaling Laws for Neural Language Models," 2020 — arXiv:2001.08361;
Hoffmann et al., "Training Compute-Optimal Large Language Models," 2022 — arXiv:2203.15556.
6. Locatello et al., "Challenging Common Assumptions in the Unsupervised Learning of Disentangled
Representations," ICML 2019 (best paper) — arXiv:1811.12359.
7. Guo, Pleiss, Sun & Weinberger, "On Calibration of Modern Neural Networks," ICML 2017;
Santurkar et al., "How Does Batch Normalization Help Optimization?," NeurIPS 2018.
8. Dosovitskiy et al., "An Image is Worth 16x16 Words" (ViT), ICLR 2021 — arXiv:2010.11929;
Liu et al., "A ConvNet for the 2020s" (ConvNeXt), CVPR 2022.

View file

@ -0,0 +1,93 @@
# Prerequisite Map
The book's part structure is not its dependency structure. Readers who go strictly front-to-back
spend weeks in Chapters 24 before touching a network, and a large fraction stop there. This file
gives the actual graph.
---
## The real dependencies
```
ch01 ──────────────────────────────────► (context only; no hard dependents)
ch02 (linear algebra) ──┬──► ch04 ──┬──► ch08 ──► ch09, ch10
│ │
ch03 (probability) ─────┴──► ch05 ──┴──► ch06 ──► ch07 ──► ch11
└──► ch13 ──► ch14 ──► ch15
ch03 ──► ch16 ──► ch17 ──► ch18 ──► ch19 ──► ch20
```
**Hard prerequisites** (skipping these makes the target chapter unreadable, not merely harder):
| To read | You need | Specifically |
|---|---|---|
| ch08 | ch02, ch04 | eigenvalues, condition number, Hessian, Taylor expansion |
| ch06 | ch03 | the output distributions that determine output units and losses |
| ch07 | ch05, ch04 | biasvariance; KKT for the constraint view of penalties |
| ch18 | ch16, ch17 | the partition function; sampling |
| ch19 | ch03 | KL divergence, and its asymmetry |
| ch20 | ch13, ch19 | the latent-variable template; the ELBO |
**Soft prerequisites** — helpful, not blocking: ch02 before ch13 (PCA), ch09 before ch12,
ch10 before ch12.
## Chapters you can read early, out of order
- **ch05** — the single highest-value chapter for a practitioner. Needs only basic probability.
- **ch11** — readable on day one and immediately actionable. Depends on ch05's vocabulary only.
- **ch01** — context; skim it.
- **ch09** — comprehensible with ch06 alone if you accept the optimization details on faith.
## Chapters you can defer or skip, by goal
| Goal | Skip or defer |
|---|---|
| Applied practitioner shipping models | Part III entirely (ch1320), except ch14's denoising section |
| Preparing for modern generative modelling | Nothing in Part III — but read ch18 before ch20 |
| Interview / fundamentals refresher | ch12 (dated), ch1719 (unless the role is probabilistic ML) |
| Understanding transformers | ch10 for the gradient analysis; then leave the book for the 2017 paper |
| Research in probabilistic ML | Everything; Part III is the reason this book has no substitute |
## The Part I wall, and how to get through it
Chapters 24 are compressed reference material, not pedagogy. Three viable strategies:
1. **Read-on-demand** (recommended for applied readers): skim ch24 once for vocabulary, start at
ch05, and return to a specific section when ch08 uses it. The prerequisite table above tells
you exactly which section.
2. **Front-load** (recommended if you intend to read Part III): work ch24 properly with a
separate linear algebra source alongside. Budget 23× the page count in time.
3. **Substitute**: use a dedicated linear algebra or probability text for Part I and treat these
chapters purely as a notation reference for the rest of the book.
Strategy 1 is right for most readers and is what `scripts/reading_path_planner.py` recommends by
default. Strategy 2 is right when Part III is the destination — its chapters compound, and gaps
compound with them.
## Time budgeting
Reported reading times vary by an order of magnitude, so treat any figure as a planning
assumption, not a fact. As a planning heuristic used by the reading-path planner: a Part I or
Part III chapter is roughly 1.52× the time of a Part II chapter of the same length, because the
derivation density is higher. The planner exposes its per-chapter assumptions in
`--output json` so you can recalibrate them against your own first chapter.
## Sources
1. Goodfellow, Bengio & Courville, *Deep Learning*, MIT Press 2016 — table of contents and part
structure: https://www.deeplearningbook.org/
2. Sweller, van Merriënboer & Paas, "Cognitive Architecture and Instructional Design," *Educational
Psychology Review* 10(3), 1998 — element interactivity and intrinsic load, which is what makes
ch24 expensive.
3. Sweller & Cooper, "The Use of Worked Examples as a Substitute for Problem Solving," *Cognition
and Instruction* 2(1), 1985 — the worked-example effect for novices.
4. Bjork & Bjork, "Making Things Hard on Yourself, But in a Good Way: Creating Desirable
Difficulties to Enhance Learning," 2011.
5. Roediger & Karpicke, "Test-Enhanced Learning," *Psychological Science* 17(3), 2006.
6. Ericsson, Krampe & Tesch-Römer, "The Role of Deliberate Practice in the Acquisition of Expert
Performance," *Psychological Review* 100(3), 1993.
7. Chi, Bassok, Lewis, Reimann & Glaser, "Self-Explanations: How Students Study and Use Examples
in Learning to Solve Problems," *Cognitive Science* 13(2), 1989.

View file

@ -0,0 +1,80 @@
# Why This Is a Companion, Not a Compiled Copy
This repository ships `engineering/book-to-skill`, which compiles a document on disk into a
knowledge-base skill. This skill was **not** produced that way, and the reason is worth stating
plainly, because the same reasoning applies to every future request of the form "turn this book
into a skill."
---
## The three facts that decided it
1. **The book is copyrighted.** *Deep Learning* (Goodfellow, Bengio & Courville) is published by
MIT Press, 2016. Free-to-read is not free-to-redistribute; the two are unrelated.
2. **The publisher's position is explicit.** deeplearningbook.org states that the HTML-only
presentation exists as a deliberate friction against copying and editing, required by the
authors' contract with MIT Press, and that PDF distribution is not permitted.
3. **This repository is public.** `book-to-skill`'s own rights gate refuses a `shareable`
distribution without one of `public-domain`, `open-license`, `internal-docs`, or
`author-permission`. None applies here. Its `references/rights_and_provenance.md` lists
"publish a compiled skill of a copyrighted book to a public marketplace" under **Do not**.
`book-to-skill` also has a hard rule that it converts files already on disk and never scrapes a
book from the web — so the requested pipeline could not have been run against a URL regardless.
## What was built instead
An **original companion**: every chapter file is written from domain knowledge, states what the
chapter establishes, how to use it, and where it has aged, and links to the official free
chapter. The organizing structure — 20 chapters in 3 parts — is the book's published table of
contents, which is factual metadata, not expression.
Concretely, this skill contains:
- **No passages, paragraphs, sentences, or figures from the book.**
- **No paraphrase-per-paragraph** — the compression ratio is roughly a whole chapter to a page,
which is a synthesis, not a substitute.
- **Links to the official chapters**, so the skill sends readers *to* the book rather than
replacing it.
- **Original material the book does not contain**: the 2016→2026 delta layer, the prerequisite
graph, the study method, and four executable tools.
Under the idea/expression line (17 U.S.C. §102(b); *Baker v. Selden*), what this skill carries —
the names of methods, the structure of an argument, decision rules stated plainly, and terms
defined in other words — sits on the ideas side. The chapters themselves, in the authors' prose,
sit on the expression side, and stay at deeplearningbook.org.
**Not legal advice.** This is the posture and its reasoning. Where money or publication is
involved, ask a lawyer.
## The rule this establishes for the repository
> When a user asks to convert a copyrighted work into a shareable skill, build a **companion**
> that indexes and updates the source, not a **compilation** that reproduces it. Compile only
> when the rights gate clears — and keep compiled output local when it does not.
A companion is often the better artifact anyway. A compilation freezes a source at its
publication date; a companion can say which parts of a ten-year-old text are still true, which
is precisely what a reader of a 2016 deep learning book needs most.
## Use this skill correctly
- **Do** read the book at deeplearningbook.org; this navigates it.
- **Do** use the delta reference before acting on any 2016-era recommendation.
- **Don't** treat the chapter files as a substitute for reading the chapters — they are the
answer key for retrieval practice, not the material.
- **Don't** extend this skill by pasting book text into it. That converts a companion into the
thing this file exists to avoid.
## Sources
1. Goodfellow, Bengio & Courville, *Deep Learning*, MIT Press, 2016 — https://www.deeplearningbook.org/
2. deeplearningbook.org — the site's own statement on its HTML-only format and PDF distribution.
3. 17 U.S.C. §102(b) — ideas, procedures, processes and methods of operation are outside
copyright.
4. *Baker v. Selden*, 101 U.S. 99 (1879) — the idea/expression dichotomy.
5. 17 U.S.C. §107 — fair use as a four-factor defence, assessed case by case.
6. *Authors Guild v. Google, Inc.*, 804 F.3d 202 (2d Cir. 2015) — indexing that does not
substitute for the original held transformative.
7. This repository: `engineering/book-to-skill/skills/book-to-skill/references/rights_and_provenance.md`
(the rights gate) and its SKILL.md hard rules 1 and 6.

View file

@ -0,0 +1,99 @@
# Studying a Hard Technical Text
This book defeats more readers than it teaches, and the reason is rarely ability. It is a
reference text with textbook page counts, high element interactivity, and no exercises. The
methods below are the evidence-based ones that apply specifically to that shape of material.
---
## The five that matter here
### 1. Retrieval practice beats re-reading
Testing yourself on material produces markedly better long-term retention than reviewing it,
even when re-reading feels more productive at the time (Roediger & Karpicke, 2006). For this
book, the cheap version: after each chapter, close it and write the chapter's core idea, three
concepts, and one thing you could not explain. The chapter files in this skill are structured to
be *checked against*, not read first — use them as the answer key.
### 2. Spacing beats massing
Distributed practice outperforms cramming for durable retention (Cepeda et al., 2006). Practical
rule: revisit ch05 and ch11 at one week and one month. They are the chapters whose vocabulary
every later chapter reuses, so spaced review of those two pays across the whole book.
### 3. Worked examples before problem-solving, for novices
For learners without domain schemas, studying worked examples is more effective than solving
equivalent problems — the expertise-reversal effect means this flips once you *have* the schemas
(Sweller & Cooper, 1985; Kalyuga et al., 2003). Consequence for this book: in Ch 8 and Ch 18, work
the derivations the text presents before attempting your own; in Ch 11, do the opposite — you
already have the schema, so run the workflow on a real project.
### 4. Self-explanation
Students who explain each step to themselves while studying examples learn substantially more than
those who do not (Chi et al., 1989). The highest-yield prompt for this book: after every
equation, answer "what would change if this term were removed?" It converts symbol-tracking into
understanding, and it is exactly how the book's own arguments are structured.
### 5. Desirable difficulties
Conditions that slow acquisition often improve retention and transfer (Bjork & Bjork, 2011).
Interleaving Part II chapters with attempts to apply them beats reading Part II straight through,
even though it feels slower. This is the empirical case for the reading-path planner's
"read one chapter, then implement something" cadence.
---
## Managing cognitive load in Chapters 24 and 1620
High **element interactivity** — where symbols cannot be understood one at a time because they
only make sense in relation to each other — is what makes these chapters expensive (Sweller, van
Merriënboer & Paas, 1998). Intrinsic load cannot be reduced by better presentation; it can only be
sequenced. Two consequences:
- **Do not skim a high-interactivity derivation.** Skimming works for prose and fails for
Chapter 18. Either work it or defer it explicitly.
- **Chunk by named object.** "Score matching" as one unit is cheaper than seven equations. Every
chapter file in this skill names its objects for exactly this reason.
## A cadence that works for this book
1. **Skim** the chapter's section headings and the summary. Five minutes.
2. **Read** with a pen, working every derivation you intend to keep.
3. **Close the book** and write, from memory: the core idea, three concepts, one confusion.
4. **Check** against this skill's chapter file — it is deliberately written as a synthesis, so a
mismatch is informative.
5. **Apply** something small before moving on (a five-line implementation, a diagnosis of a real
training run, a re-derivation).
6. **Revisit** at one week for ch05, ch08, ch11, ch18.
Step 5 is the one most readers skip and the one that decides whether any of it survives.
## What not to do
- **Reading front-to-back through Part I as a first pass.** See `prerequisite_map.md`.
- **Highlighting.** It produces a strong feeling of learning and among the weakest measured
effects of the common study techniques (Dunlosky et al., 2013).
- **Taking notes that restate the text.** Restatement is transcription. Write the answer to
"when would I use this?" instead — that is the note that gets read again.
- **Waiting to "finish the math" before touching a model.** The book's own Ch 11 argues against
it: build the end-to-end pipeline early.
## Sources
1. Roediger & Karpicke, "Test-Enhanced Learning: Taking Memory Tests Improves Long-Term
Retention," *Psychological Science* 17(3), 2006.
2. Cepeda, Pashler, Vul, Wixted & Rohrer, "Distributed Practice in Verbal Recall Tasks: A Review
and Quantitative Synthesis," *Psychological Bulletin* 132(3), 2006.
3. Sweller & Cooper, "The Use of Worked Examples as a Substitute for Problem Solving in Learning
Algebra," *Cognition and Instruction* 2(1), 1985; Kalyuga, Ayres, Chandler & Sweller, "The
Expertise Reversal Effect," *Educational Psychologist* 38(1), 2003.
4. Chi, Bassok, Lewis, Reimann & Glaser, "Self-Explanations," *Cognitive Science* 13(2), 1989.
5. Bjork & Bjork, "Making Things Hard on Yourself, But in a Good Way," in *Psychology and the Real
World*, 2011.
6. Sweller, van Merriënboer & Paas, "Cognitive Architecture and Instructional Design,"
*Educational Psychology Review* 10(3), 1998.
7. Dunlosky, Rawson, Marsh, Nathan & Willingham, "Improving Students' Learning With Effective
Learning Techniques," *Psychological Science in the Public Interest* 14(1), 2013.

View file

@ -0,0 +1,292 @@
#!/usr/bin/env python3
"""capacity_planner.py — capacity, the generalization gap, and what to spend next.
Chapter 5 gives the bias-variance budget and the classical U-shaped capacity curve.
Chapter 7 gives the regularizers you spend from that budget. This tool combines them
into one recommendation: given a measured gap and a parameters-per-example ratio, what
is the cheapest next purchase?
It carries one correction the 2016 text predates. The classical advice "shrink the
model when it overfits" assumed the underparameterized side of the U-curve. Past the
interpolation threshold, test error can fall again (double descent; Belkin et al. 2019,
Nakkiran et al. 2020), so in the overparameterized regime this tool ranks *more data,
more regularization, longer training* above *smaller model* and says why.
Standard library only. No network calls.
Exit codes:
0 a plan was produced and the fit looks balanced
1 a plan was produced and an action is recommended
2 usage error (argparse)
4 inputs are inconsistent (e.g. validation error below training error by a wide
margin, which usually means a leaky split rather than a good model)
"""
from __future__ import annotations
import argparse
import json
import sys
# Regularization ladder in cost order (ch07). Cost is effort+risk, not compute.
LADDER = [
("more-real-data", "Collect more real labelled data",
"The only intervention that reduces variance without adding bias. Everything below "
"is a substitute for it.", "ch05, ch07"),
("augmentation", "Label-preserving data augmentation",
"Cheapest substitute for real data where a real invariance exists. Verify the "
"transform preserves the label — a flip destroys the label on digits.", "ch07"),
("early-stopping", "Early stopping on a validation metric",
"Approximately equivalent to L2 under a quadratic approximation, at near-zero cost. "
"Usually the first thing to try.", "ch07"),
("weight-decay", "Decoupled weight decay (AdamW)",
"Damps directions the data does not constrain. Use AdamW, not Adam with an L2 term "
"in the loss — they are not equivalent under an adaptive optimizer.", "ch07, ch08"),
("label-smoothing", "Label smoothing",
"Reduces over-confidence on the training targets; cheap and usually harmless.",
"ch07 (noise injection on labels)"),
("dropout", "Dropout",
"Approximate ensembling. Note the interaction with batch norm, and that modern "
"large stacks regularize far more lightly than 2016 practice.", "ch07"),
("parameter-sharing", "Structural parameter sharing",
"The strongest regularizer: remove parameters rather than penalize them. Only valid "
"when a real invariance exists (convolution, weight tying).", "ch07, ch09"),
("smaller-model", "Reduce model capacity",
"Classical advice from the underparameterized side of the U-curve. In the "
"overparameterized regime this is ranked last, not first.", "ch05"),
]
# Parameters-per-example ratio bands. Approximate regime markers, not a threshold
# theorem — the interpolation threshold depends on the task, the architecture and the
# label noise, and cannot be read off a parameter count alone.
UNDERPARAMETERIZED_MAX = 1.0
OVERPARAMETERIZED_MIN = 10.0
def classify_regime(params: int, examples: int,
under_max: float = UNDERPARAMETERIZED_MAX,
over_min: float = OVERPARAMETERIZED_MIN) -> tuple[str, float, str]:
ratio = params / examples
if ratio < under_max:
regime = "underparameterized"
note = ("Fewer parameters than training examples. The classical U-curve applies "
"directly here: reducing capacity is a legitimate response to overfitting.")
elif ratio < over_min:
regime = "near-interpolation"
note = ("Roughly at the interpolation threshold, where the classical curve peaks "
"and double descent begins. This is the worst place to sit: both more "
"capacity and less capacity can improve test error, so measure rather "
"than reason.")
else:
regime = "overparameterized"
note = ("Many more parameters than examples. The classical 'shrink the model' "
"advice is not reliable here — double descent means a larger model with "
"more data or stronger regularization often generalizes better.")
return regime, ratio, note
def plan(params: int, examples: int, train_error: float, val_error: float,
applied: set[str], target_error: float | None,
overfit_rel_gap: float,
under_max: float = UNDERPARAMETERIZED_MAX,
over_min: float = OVERPARAMETERIZED_MIN) -> dict:
regime, ratio, regime_note = classify_regime(params, examples, under_max, over_min)
denom = max(abs(train_error), 1e-6)
gap = val_error - train_error
rel_gap = gap / denom
if target_error is not None and train_error > target_error * 1.15:
verdict = "UNDERFIT"
headline = ("Training error is above target — capacity or optimization is the "
"bottleneck. More data cannot help yet.")
actions = [
("tune-lr-schedule", "Tune learning rate and schedule first",
"Usually dominates the choice of optimizer family. Warmup plus cosine decay "
"is the modern default for deep stacks.", "ch08"),
("check-init", "Check initialization scale (He / Xavier)",
"Bad initialization is a common silent cause of a model that will not fit.",
"ch08"),
("remove-regularization", "Remove regularization you already added",
"Every regularizer you applied is buying variance reduction you cannot "
"currently afford.", "ch07"),
("add-capacity", "Add capacity (width or depth)",
"Only after the three above — an optimization problem does not respond to "
"more parameters.", "ch05, ch06"),
]
elif rel_gap > overfit_rel_gap:
verdict = "OVERFIT"
headline = (f"Validation error exceeds training error by {rel_gap:.0%} of the "
"training error — spend from the regularization budget.")
ladder = [item for item in LADDER if item[0] not in applied]
if regime == "underparameterized":
actions = ladder
else:
# Push smaller-model to the end and say why.
actions = ([item for item in ladder if item[0] != "smaller-model"]
+ [item for item in ladder if item[0] == "smaller-model"])
else:
verdict = "BALANCED"
headline = ("The gap is within tolerance. Neither more capacity nor more "
"regularization is indicated by these numbers.")
actions = [
("verify-metric", "Verify the metric is the one you care about",
"A balanced fit on the wrong proxy is still the wrong model.", "ch11"),
("check-splits", "Confirm the split is clean and the result holds across seeds",
"A small dataset with one seed is not a measurement.", "ch05, ch11"),
]
return {
"verdict": verdict,
"headline": headline,
"regime": regime,
"regime_note": regime_note,
"params": params,
"train_examples": examples,
"params_per_example": round(ratio, 3),
"train_error": train_error,
"val_error": val_error,
"gap": round(gap, 6),
"relative_gap": round(rel_gap, 4),
"target_error": target_error,
"already_applied": sorted(applied),
"actions": [
{"id": a[0], "action": a[1], "why": a[2], "chapter": a[3]}
for a in actions
],
"thresholds": {
"overfit_rel_gap": overfit_rel_gap,
"underparameterized_max": under_max,
"overparameterized_min": over_min,
},
"double_descent_caveat": (
regime != "underparameterized" and verdict == "OVERFIT"
),
}
def render(result: dict) -> str:
lines = [
"CAPACITY & REGULARIZATION PLAN",
"=" * 70,
f"Verdict : {result['verdict']}",
f" {result['headline']}",
"",
f"Regime : {result['regime']} "
f"({result['params_per_example']} params per training example)",
f" {result['regime_note']}",
"",
f"Train err : {result['train_error']} Val err: {result['val_error']} "
f"gap: {result['gap']} ({result['relative_gap']:.0%} of train error)",
]
if result["already_applied"]:
lines.append(f"Applied : {', '.join(result['already_applied'])} (excluded below)")
lines += ["", "Do these in order:", "-" * 70]
for index, action in enumerate(result["actions"], start=1):
lines.append(f"{index}. {action['action']} [{action['chapter']}]")
lines.append(f" {action['why']}")
lines.append("-" * 70)
if result["double_descent_caveat"]:
lines.append(
"Double-descent caveat: 'reduce capacity' is ranked LAST here because this "
"model is at or past the interpolation threshold, where the classical "
"U-curve advice is unreliable (Belkin 2019, Nakkiran 2020 — both post-date "
"the book). See references/book_to_2026_delta.md."
)
lines.append("Change one thing per experiment and re-measure the gap. (ch11)")
return "\n".join(lines)
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(
description="Turn a measured generalization gap into an ordered action plan.",
epilog="Exit codes: 0 balanced · 1 action recommended · 4 inconsistent inputs.",
)
parser.add_argument("--params", type=int, help="trainable parameter count")
parser.add_argument("--train-examples", type=int, help="number of training examples")
parser.add_argument("--train-error", type=float,
help="training error or loss (same units as --val-error)")
parser.add_argument("--val-error", type=float, help="validation error or loss")
parser.add_argument("--target-error", type=float,
help="the value that would count as success; without it, "
"underfitting cannot be distinguished from convergence")
parser.add_argument("--applied", default="",
help="comma-separated regularizers already in use, from: "
+ ",".join(item[0] for item in LADDER))
parser.add_argument("--overfit-rel-gap", type=float, default=0.30,
help="relative gap above which the fit counts as overfitting "
"(default: 0.30)")
parser.add_argument("--underparameterized-max", type=float,
default=UNDERPARAMETERIZED_MAX,
help="params-per-example below which the classical U-curve "
f"applies directly (default: {UNDERPARAMETERIZED_MAX})")
parser.add_argument("--overparameterized-min", type=float,
default=OVERPARAMETERIZED_MIN,
help="params-per-example above which double descent makes "
"'shrink the model' unreliable "
f"(default: {OVERPARAMETERIZED_MIN}). These are heuristic "
"bands, not a threshold theorem — the interpolation point "
"depends on task, architecture and label noise.")
parser.add_argument("--output", choices=("text", "json"), default="text")
parser.add_argument("--sample", action="store_true",
help="run against a built-in overparameterized example")
args = parser.parse_args(argv)
if args.sample:
args.params, args.train_examples = 12_000_000, 50_000
args.train_error, args.val_error = 0.01, 0.22
args.applied = "early-stopping"
required = (args.params, args.train_examples, args.train_error, args.val_error)
if any(value is None for value in required):
parser.error("--params, --train-examples, --train-error and --val-error are all "
"required (or use --sample)")
if args.params <= 0 or args.train_examples <= 0:
parser.error("--params and --train-examples must be positive")
if args.underparameterized_max >= args.overparameterized_min:
# Overlapping bands silently mis-class the regime, and the cost is not
# cosmetic: an overparameterized model reported as underparameterized ranks
# "shrink the model" FIRST, inverting the double-descent correction this
# tool exists to apply.
parser.error(
f"--underparameterized-max ({args.underparameterized_max}) must be less "
f"than --overparameterized-min ({args.overparameterized_min}); the bands "
"are ordered and must not overlap"
)
known = {item[0] for item in LADDER}
applied = {token.strip() for token in args.applied.split(",") if token.strip()}
unknown = applied - known
if unknown:
parser.error(f"unknown --applied value(s): {', '.join(sorted(unknown))}; "
f"choose from {', '.join(sorted(known))}")
if args.val_error < args.train_error - 0.05 * max(abs(args.train_error), 1e-6):
payload = {
"status": "inconsistent_input",
"reason": "validation error is materially below training error",
"explanation": "This usually means a leaky split, a validation set that is "
"easier than the training set, or regularization active at "
"train time but not at eval (dropout, augmentation). Fix the "
"measurement before acting on it.",
"chapter": "ch05, ch11",
}
if args.output == "json":
print(json.dumps(payload, indent=2))
else:
print("INCONSISTENT INPUT — " + payload["reason"])
print(payload["explanation"])
return 4
result = plan(args.params, args.train_examples, args.train_error, args.val_error,
applied, args.target_error, args.overfit_rel_gap,
args.underparameterized_max, args.overparameterized_min)
if args.output == "json":
print(json.dumps(result, indent=2))
else:
print(render(result))
return 0 if result["verdict"] == "BALANCED" else 1
if __name__ == "__main__":
sys.exit(main())

View file

@ -0,0 +1,420 @@
#!/usr/bin/env python3
"""model_arithmetic.py — parameters, FLOPs and activation memory for a layer stack.
Chapter 6 makes the point that the real cost of depth in training is activation memory:
the backward pass needs the forward activations, which is why gradient checkpointing
trades compute for memory. Chapter 9 makes the receptive-field and parameter-sharing
arithmetic explicit. This tool does that arithmetic for a declared stack, and the part
that catches real bugs refuses to continue when one layer's output shape cannot feed
the next.
Shapes are per example, excluding the batch dimension. FLOPs are per example, per
forward pass; a training step costs roughly 3x a forward pass (forward + backward).
Layer types: input, linear, conv2d, pool2d, flatten, embedding, layernorm, activation,
dropout, mha (multi-head self-attention), lstm, gru.
A linear layer on a 2-D (seq, features) input is treated as position-wise: one weight
matrix shared across all positions, as in a transformer feedforward block. Parameters do
not scale with sequence length; compute does. Flatten first only when you really mean a
dense layer over the whole flattened sequence that is a different layer, and its
parameter count is seq_len times larger.
conv2d "same" padding follows TensorFlow/Keras SAME: output is ceil(H / stride), with
any needed padding split across the two sides (and the extra pixel going to the bottom
and right at even kernel sizes). PyTorch's padding='same' is symmetric-only and rejects
a stride other than 1, so a strided PyTorch layer will not match this row declare it
as "valid" with the padding you actually apply if you need that case exactly.
Standard library only. No frameworks, no network calls.
Exit codes:
0 the stack is consistent and the report was produced
2 usage error (argparse)
4 the spec could not be parsed (bad JSON, unknown layer type, missing field)
5 shape mismatch between consecutive layers the offending layer is named
"""
from __future__ import annotations
import argparse
import json
import math
import sys
BYTES_PER_ELEMENT = {"fp32": 4, "tf32": 4, "fp16": 2, "bf16": 2, "fp8": 1}
# A multiply-accumulate is counted as 2 FLOPs. --convention mac reports MACs instead.
FLOPS_PER_MAC = 2
class SpecError(ValueError):
"""The spec is malformed: bad JSON, unknown layer, or a missing field."""
class ShapeError(ValueError):
"""A layer cannot consume the shape the previous layer produced."""
def _require(layer: dict, key: str, index: int):
if not isinstance(layer, dict):
raise SpecError(f"layer {index} is {type(layer).__name__}, not an object")
if key not in layer:
raise SpecError(f"layer {index} ({layer.get('type', '?')}) is missing '{key}'")
return layer[key]
def _positive_int(layer: dict, key: str, index: int, default: int | None = None) -> int:
"""Read an integer field, rejecting non-numeric and non-positive values.
Without this, a non-numeric "filters" raised ValueError and a zero "stride" or
"groups" raised ZeroDivisionError both escaping as tracebacks rather than the
documented exit 4.
"""
raw = layer.get(key, default) if isinstance(layer, dict) else default
if raw is None:
raise SpecError(f"layer {index} ({layer.get('type', '?')}) is missing '{key}'")
try:
value = int(raw)
except (TypeError, ValueError):
raise SpecError(
f"layer {index} ({layer.get('type', '?')}): '{key}' must be an integer, "
f"got {raw!r}"
) from None
if value <= 0:
raise SpecError(
f"layer {index} ({layer.get('type', '?')}): '{key}' must be positive, got {value}"
)
return value
def _prod(shape: tuple[int, ...]) -> int:
total = 1
for dim in shape:
total *= dim
return total
def step(layer: dict, shape: tuple[int, ...], index: int) -> tuple[tuple[int, ...], int, int]:
"""Return (output_shape, parameters, macs) for one layer given its input shape."""
kind = _require(layer, "type", index)
if kind == "input":
raw_shape = _require(layer, "shape", index)
if not isinstance(raw_shape, (list, tuple)) or not raw_shape:
raise SpecError(f"layer {index} (input): 'shape' must be a non-empty list")
dims = []
for dim in raw_shape:
try:
dim = int(dim)
except (TypeError, ValueError):
raise SpecError(
f"layer {index} (input): shape entries must be integers, got {dim!r}"
) from None
if dim <= 0:
raise SpecError(f"layer {index} (input): shape entries must be positive")
dims.append(dim)
return tuple(dims), 0, 0
if kind == "linear":
units = _positive_int(layer, "units", index)
bias = bool(layer.get("bias", True))
if len(shape) == 2:
# Per-token (position-wise) linear over a (seq, features) sequence: one
# weight matrix shared across positions, exactly like a transformer FFN
# projection. Parameters do NOT scale with sequence length; compute does.
# Flattening instead would multiply the parameter count by seq_len, which
# is a different layer and almost never the intended one.
seq, features = shape
params = features * units + (units if bias else 0)
return (seq, units), params, seq * features * units
if len(shape) != 1:
raise ShapeError(
f"layer {index} (linear) needs a 1-D or 2-D input, got {shape}. "
"Insert a flatten layer to collapse a feature map into one vector."
)
params = shape[0] * units + (units if bias else 0)
return (units,), params, shape[0] * units
if kind == "conv2d":
filters = _positive_int(layer, "filters", index)
kernel = _positive_int(layer, "kernel", index)
stride = _positive_int(layer, "stride", index, 1)
padding = layer.get("padding", "same")
if len(shape) != 3:
raise ShapeError(
f"layer {index} (conv2d) needs a 3-D input (C, H, W), got {shape}"
)
channels, height, width = shape
if padding == "same":
# TensorFlow/Keras SAME convention; see the module docstring for how this
# differs from PyTorch's stride-1-only padding='same'.
out_h, out_w = math.ceil(height / stride), math.ceil(width / stride)
elif padding == "valid":
out_h = (height - kernel) // stride + 1
out_w = (width - kernel) // stride + 1
else:
raise SpecError(f"layer {index} (conv2d): padding must be 'same' or 'valid'")
if out_h <= 0 or out_w <= 0:
raise ShapeError(
f"layer {index} (conv2d) with kernel {kernel} and stride {stride} "
f"reduces {height}x{width} to {out_h}x{out_w} — the kernel is larger "
"than the feature map."
)
groups = _positive_int(layer, "groups", index, 1)
if channels % groups or filters % groups:
raise SpecError(
f"layer {index} (conv2d): groups={groups} does not divide "
f"in_channels={channels} and filters={filters}"
)
bias = bool(layer.get("bias", True))
params = (kernel * kernel * (channels // groups) * filters) + (filters if bias else 0)
macs = kernel * kernel * (channels // groups) * filters * out_h * out_w
return (filters, out_h, out_w), params, macs
if kind == "pool2d":
size = _positive_int(layer, "size", index, 2)
stride = _positive_int(layer, "stride", index, size)
if len(shape) != 3:
raise ShapeError(f"layer {index} (pool2d) needs a 3-D input, got {shape}")
channels, height, width = shape
out_h = (height - size) // stride + 1
out_w = (width - size) // stride + 1
if out_h <= 0 or out_w <= 0:
raise ShapeError(
f"layer {index} (pool2d) reduces {height}x{width} to {out_h}x{out_w}"
)
return (channels, out_h, out_w), 0, 0
if kind == "flatten":
return (_prod(shape),), 0, 0
if kind == "embedding":
vocab = _positive_int(layer, "vocab", index)
dim = _positive_int(layer, "dim", index)
seq = _positive_int(layer, "seq_len", index,
default=shape[0] if shape else 1)
return (seq, dim), vocab * dim, 0 # a lookup, not a matmul
if kind == "layernorm":
features = shape[-1]
return shape, 2 * features, 0
if kind in ("activation", "dropout"):
return shape, 0, 0
if kind == "mha":
# Multi-head self-attention over a (seq, d_model) input.
if len(shape) != 2:
raise ShapeError(
f"layer {index} (mha) needs a 2-D input (seq_len, d_model), got {shape}"
)
seq, d_model = shape
heads = _positive_int(layer, "heads", index, 8)
if d_model % heads:
raise SpecError(
f"layer {index} (mha): d_model={d_model} is not divisible by heads={heads}"
)
# 4 projections (Q, K, V, O), each d_model x d_model.
params = 4 * d_model * d_model + (4 * d_model if layer.get("bias", True) else 0)
proj_macs = 4 * seq * d_model * d_model
# Scores (seq x seq x d_model) and the weighted value sum, both quadratic in seq.
attn_macs = 2 * seq * seq * d_model
return shape, params, proj_macs + attn_macs
if kind in ("lstm", "gru"):
if len(shape) != 2:
raise ShapeError(
f"layer {index} ({kind}) needs a 2-D input (seq_len, features), got {shape}"
)
seq, features = shape
units = _positive_int(layer, "units", index)
gates = 4 if kind == "lstm" else 3
params = gates * (features * units + units * units + 2 * units)
macs = seq * gates * (features * units + units * units)
out = (seq, units) if layer.get("return_sequences", True) else (units,)
return out, params, macs
raise SpecError(f"layer {index}: unknown layer type {kind!r}")
def analyse(spec: dict, dtype: str, convention: str) -> dict:
if not isinstance(spec, dict):
raise SpecError(f"spec must be a JSON object, got {type(spec).__name__}")
layers = spec.get("layers")
if not isinstance(layers, list) or not layers:
raise SpecError("spec must contain a non-empty 'layers' list")
for index, layer in enumerate(layers):
if not isinstance(layer, dict):
raise SpecError(f"layer {index} is {type(layer).__name__}, not an object")
if layers[0].get("type") != "input":
raise SpecError("the first layer must be of type 'input'")
width = BYTES_PER_ELEMENT[dtype]
shape: tuple[int, ...] = ()
rows = []
total_params = 0
total_macs = 0
total_activations = 0
for index, layer in enumerate(layers):
shape, params, macs = step(layer, shape, index)
activations = _prod(shape)
total_params += params
total_macs += macs
# The input layer's tensor is not a stored intermediate activation.
if index > 0:
total_activations += activations
rows.append({
"index": index,
"type": layer["type"],
"name": layer.get("name", layer["type"]),
"output_shape": list(shape),
"parameters": params,
"macs": macs,
"flops": macs * FLOPS_PER_MAC,
"activation_elements": activations,
})
compute = total_macs if convention == "mac" else total_macs * FLOPS_PER_MAC
return {
"dtype": dtype,
"convention": convention,
"layers": rows,
"totals": {
"parameters": total_params,
"parameter_bytes": total_params * width,
"forward_macs": total_macs,
"forward_flops": total_macs * FLOPS_PER_MAC,
"reported_compute": compute,
"activation_elements_per_example": total_activations,
"activation_bytes_per_example": total_activations * width,
},
"notes": [
"Shapes and costs are per example; the batch dimension is excluded.",
"A training step costs roughly 3x the forward FLOPs (forward + backward).",
"Activation memory is the training-time cost of depth (ch06). Gradient "
"checkpointing trades compute for it.",
"Optimizer state is extra: Adam/AdamW holds two moments per parameter, so "
"budget ~3x parameter bytes for weights plus state in fp32.",
"Attention cost is quadratic in sequence length — visible in the mha row.",
],
}
SAMPLE_SPEC = {
"name": "small convnet, CIFAR-shaped",
"layers": [
{"type": "input", "shape": [3, 32, 32]},
{"type": "conv2d", "filters": 32, "kernel": 3, "padding": "same"},
{"type": "activation", "name": "relu"},
{"type": "pool2d", "size": 2},
{"type": "conv2d", "filters": 64, "kernel": 3, "padding": "same"},
{"type": "activation", "name": "relu"},
{"type": "pool2d", "size": 2},
{"type": "flatten"},
{"type": "linear", "units": 128},
{"type": "activation", "name": "relu"},
{"type": "dropout"},
{"type": "linear", "units": 10},
],
}
def human(value: int) -> str:
for unit, scale in (("G", 1e9), ("M", 1e6), ("K", 1e3)):
if value >= scale:
return f"{value / scale:.2f}{unit}"
return str(value)
def render(result: dict) -> str:
lines = [
"MODEL ARITHMETIC",
"=" * 78,
f"{'#':>2} {'layer':<12} {'output shape':<18} {'params':>12} "
f"{'MFLOPs':>10} {'act.elts':>10}",
"-" * 78,
]
for row in result["layers"]:
shape = "x".join(str(dim) for dim in row["output_shape"])
lines.append(
f"{row['index']:>2} {row['type']:<12} {shape:<18} "
f"{row['parameters']:>12,} {row['flops'] / 1e6:>10.2f} "
f"{row['activation_elements']:>10,}"
)
totals = result["totals"]
lines += [
"-" * 78,
f"Parameters : {totals['parameters']:,} "
f"({human(totals['parameter_bytes'])}B at {result['dtype']})",
f"Forward FLOPs/ex : {human(totals['forward_flops'])} "
f"({human(totals['forward_macs'])} MACs)",
f"Training step (~3x) : {human(totals['forward_flops'] * 3)} FLOPs/ex",
f"Activations/ex : {totals['activation_elements_per_example']:,} elements "
f"({human(totals['activation_bytes_per_example'])}B at {result['dtype']})",
"",
]
lines.append(f"At batch 128: activations ≈ "
f"{human(totals['activation_bytes_per_example'] * 128)}B")
lines.append("")
for note in result["notes"]:
lines.append(f"· {note}")
return "\n".join(lines)
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(
description="Compute parameters, FLOPs and activation memory for a layer stack.",
epilog="Exit codes: 0 ok · 4 bad spec · 5 shape mismatch.",
)
parser.add_argument("--spec", help="path to a JSON layer spec")
parser.add_argument("--spec-sample", action="store_true",
help="print the built-in sample spec and exit")
parser.add_argument("--dtype", choices=sorted(BYTES_PER_ELEMENT), default="fp32")
parser.add_argument("--convention", choices=("flop", "mac"), default="flop",
help="report FLOPs (1 MAC = 2 FLOPs) or raw MACs")
parser.add_argument("--output", choices=("text", "json"), default="text")
parser.add_argument("--sample", action="store_true",
help="analyse the built-in sample spec")
args = parser.parse_args(argv)
if args.spec_sample:
print(json.dumps(SAMPLE_SPEC, indent=2))
return 0
if args.sample:
spec = SAMPLE_SPEC
elif args.spec:
try:
with open(args.spec, encoding="utf-8") as handle:
spec = json.load(handle)
except OSError as error:
print(f"cannot read spec: {error}", file=sys.stderr)
return 4
except json.JSONDecodeError as error:
print(f"spec is not valid JSON: {error}", file=sys.stderr)
return 4
else:
parser.error("--spec is required (or use --sample / --spec-sample)")
try:
result = analyse(spec, args.dtype, args.convention)
except ShapeError as error:
print(f"SHAPE MISMATCH — {error}", file=sys.stderr)
print("A shape mismatch is a modelling error, not a typing error (ch02).",
file=sys.stderr)
return 5
except SpecError as error:
print(f"BAD SPEC — {error}", file=sys.stderr)
return 4
if args.output == "json":
print(json.dumps(result, indent=2))
else:
print(render(result))
return 0
if __name__ == "__main__":
sys.exit(main())

View file

@ -0,0 +1,459 @@
#!/usr/bin/env python3
"""reading_path_planner.py — turn a goal into an ordered, prerequisite-closed reading path.
The book's part order is not its dependency order. Read front-to-back and you spend
weeks in Chapters 2-4 before touching a network; skip Part I entirely and Chapter 8
becomes unreadable. This tool takes a goal and a background, resolves the *hard*
prerequisites of the chapters that goal needs, orders them, and prices the result
in weeks at your stated pace.
It refuses two things rather than guessing:
* a goal whose subject the 2016 book does not cover at all (exit 3) it names what
covers it instead, rather than inventing the book's position on RLHF;
* a goal too vague to route (exit 4) it prints the questions that would fix it.
Deterministic keyword scoring. Standard library only. No network calls.
Exit codes:
0 a path was produced
2 usage error (argparse)
3 goal is outside the book's scope
4 goal could not be routed forcing questions printed
"""
from __future__ import annotations
import argparse
import json
import re
import sys
# --------------------------------------------------------------------------- data
# Hard prerequisites only: skipping one makes the target unreadable, not merely
# harder. Soft prerequisites live in references/prerequisite_map.md and are
# deliberately not enforced here.
PREREQS: dict[int, tuple[int, ...]] = {
1: (),
2: (),
3: (),
4: (2,),
5: (3,),
6: (3,),
7: (4, 5),
8: (2, 4),
9: (6,),
10: (6,),
11: (5,),
12: (6,),
13: (5,),
14: (13,),
15: (14,),
16: (3,),
17: (16,),
18: (16, 17),
19: (3,),
20: (13, 19),
}
TITLES: dict[int, str] = {
1: "Introduction",
2: "Linear Algebra",
3: "Probability and Information Theory",
4: "Numerical Computation",
5: "Machine Learning Basics",
6: "Deep Feedforward Networks",
7: "Regularization for Deep Learning",
8: "Optimization for Training Deep Models",
9: "Convolutional Networks",
10: "Sequence Modeling: Recurrent and Recursive Nets",
11: "Practical Methodology",
12: "Applications",
13: "Linear Factor Models",
14: "Autoencoders",
15: "Representation Learning",
16: "Structured Probabilistic Models for Deep Learning",
17: "Monte Carlo Methods",
18: "Confronting the Partition Function",
19: "Approximate Inference",
20: "Deep Generative Models",
}
# Planning assumptions, not measurements. Part I and Part III chapters carry higher
# derivation density per page, which is why they cost more than their length suggests.
# Exposed in --output json so a reader can recalibrate against their own first chapter.
BASE_HOURS: dict[int, float] = {
1: 1.5, 2: 5.0, 3: 6.0, 4: 4.5, 5: 9.0,
6: 6.0, 7: 6.0, 8: 8.0, 9: 6.0, 10: 7.0, 11: 4.0, 12: 5.0,
13: 4.0, 14: 4.5, 15: 5.0, 16: 6.0, 17: 5.0, 18: 7.0, 19: 6.0, 20: 8.0,
}
# Background multipliers on the hour estimate.
BACKGROUNDS: dict[str, tuple[float, str]] = {
"none": (1.6, "little linear algebra or probability — Part I is real work, not review"),
"math": (0.8, "comfortable with linear algebra and probability, new to ML"),
"applied": (1.0, "ships models, wants the theory underneath"),
"research": (0.7, "reads papers in the field; the book is filling gaps"),
}
# Destination lanes. Each is (label, target chapters, note). Scored by keyword hits.
LANES: dict[str, dict] = {
"practitioner": {
"label": "Applied practitioner — train models that work",
"targets": (5, 6, 7, 8, 11),
"keywords": ("train", "training", "practical", "ship", "production", "apply",
"applied", "practitioner", "debug", "tune", "tuning", "improve",
"overfit", "underfit", "hyperparameter", "baseline", "workflow"),
"note": "Chapters 5 and 11 first; they pay off before you finish Part I.",
},
"vision": {
"label": "Computer vision — convolutional models",
"targets": (6, 7, 8, 9, 12),
"keywords": ("vision", "image", "convolution", "convolutional", "cnn", "conv",
"segmentation", "detection", "pooling", "receptive"),
"note": "Ch 9's prior-vs-data argument is what explains ViT's data hunger later.",
},
"sequence": {
"label": "Sequence modelling — recurrence, gradients through time, attention",
"targets": (6, 8, 10, 12),
"keywords": ("sequence", "rnn", "lstm", "gru", "recurrent", "time series",
"timeseries", "nlp", "language", "text", "speech", "translation",
"transformer", "attention"),
"note": "Read Ch 10 for the gradient analysis, not the architecture advice — "
"see references/book_to_2026_delta.md before applying it.",
},
"generative": {
"label": "Generative modelling — the Part III chain",
"targets": (13, 14, 16, 17, 18, 19, 20),
"keywords": ("generative", "vae", "gan", "diffusion", "autoencoder", "sampling",
"mcmc", "boltzmann", "latent", "variational", "elbo", "density",
"score matching", "partition"),
"note": "Ch 18 is the chapter whose ideas became diffusion. Do not skip it to "
"reach Ch 20.",
},
"representation": {
"label": "Representation and self-supervised learning",
"targets": (5, 13, 14, 15),
"keywords": ("representation", "embedding", "feature", "features", "transfer",
"pretrain", "pretraining", "self-supervised", "unsupervised",
"disentangle", "disentangled", "probe"),
"note": "The bet in Ch 15 was right; every method it lists was replaced. "
"Read it with the delta reference open.",
},
"foundations": {
"label": "Mathematical foundations — the machinery under everything else",
"targets": (2, 3, 4, 5),
"keywords": ("math", "mathematics", "foundation", "foundations", "linear algebra",
"probability", "statistics", "theory", "fundamentals", "basics",
"prerequisite", "prerequisites", "refresher", "interview"),
"note": "Pair with a dedicated linear algebra text; Part I is reference "
"material, not pedagogy.",
},
"optimization": {
"label": "Optimization — why training stalls, diverges, or crawls",
"targets": (2, 4, 8, 11),
"keywords": ("optimization", "optimizer", "sgd", "adam", "momentum", "gradient",
"converge", "convergence", "diverge", "learning rate", "saddle",
"initialization", "batch norm", "normalization", "clipping"),
"note": "Ch 8 is unreadable without Ch 2 and 4. This is the one place the "
"prerequisite is genuinely hard.",
},
"complete": {
"label": "Complete read — all twenty chapters",
"targets": tuple(range(1, 21)),
"keywords": ("everything", "whole book", "entire book", "all chapters",
"cover to cover", "complete", "full read", "read the book",
"start to finish"),
"note": "Even here, read Ch 5 and Ch 11 early rather than in numeric order.",
},
}
# Subjects the 2016 book does not cover. Naming these beats improvising its position.
OUT_OF_SCOPE: dict[str, str] = {
"rlhf": "RLHF / preference tuning — published 2017+; nothing in this book covers it.",
"dpo": "Direct preference optimization — 2023; outside the book entirely.",
"llm": "Large language model training and serving — the book predates it; see "
"engineering/llm-cost-optimizer and references/book_to_2026_delta.md.",
"prompt": "Prompting and in-context learning — post-dates the book.",
"agent": "Agentic systems — outside the book; see engineering/agent-harness.",
"mlops": "MLOps tooling and deployment — see engineering-team/senior-ml-engineer.",
"fine-tun": "Fine-tuning of pretrained foundation models — the book's transfer "
"learning section (ch15) is the nearest thing, and it is not the same.",
"lora": "Parameter-efficient fine-tuning (LoRA and relatives) — 2021+.",
"rag": "Retrieval-augmented generation — outside the book.",
"mamba": "State-space models — 2021+; ch10's gradient analysis is the relevant "
"background the book does provide.",
"fairness": "Fairness, bias auditing and model governance — not treated.",
"reinforcement": "Reinforcement learning — mentioned only in passing (ch12).",
}
# Tokens whose real surface forms a word-boundary match would otherwise miss.
# Everything else matches itself, optionally pluralized.
SURFACE_FORMS: dict[str, tuple[str, ...]] = {
"fine-tun": ("fine-tuning", "fine-tune", "fine-tuned", "finetuning", "finetune"),
"prompt": ("prompt", "prompting", "prompts"),
"agent": ("agent", "agents", "agentic"),
}
def _matches(token: str, text: str) -> bool:
"""True when token appears in text as a whole word (optionally pluralized).
Substring matching is wrong here and was a real defect: "rag" appears inside
"storage", "lora" inside "exploratory", "conv" inside "converge", and "text"
inside "context" each one producing a confident false refusal or a wrong lane.
"""
for form in SURFACE_FORMS.get(token, (token,)):
# Plain -s only. An -es branch collided with unrelated words: "rag" + "es"
# matches the standalone word "rages", so a goal about overfitting was
# refused as out-of-scope RAG work. No token here needs an -es plural —
# every one ending in s/x/z/ch/sh is already plural or non-count — so any
# irregular form belongs in SURFACE_FORMS, spelled out.
if re.search(rf"\b{re.escape(form)}s?\b", text):
return True
return False
# --------------------------------------------------------------------------- logic
def close_prerequisites(targets: tuple[int, ...]) -> list[int]:
"""Return targets plus every hard prerequisite, in ascending chapter order."""
needed: set[int] = set()
stack = list(targets)
while stack:
chapter = stack.pop()
if chapter in needed:
continue
needed.add(chapter)
stack.extend(PREREQS.get(chapter, ()))
return sorted(needed)
def order_path(chapters: list[int]) -> list[int]:
"""Order chapters so every hard prerequisite precedes its dependent.
Among chapters whose prerequisites are already satisfied, the cheapest
high-value chapter goes first: ch05 and ch11 are promoted because their
vocabulary is reused everywhere and they are actionable immediately.
"""
promoted = {5: -2, 11: -1}
remaining = set(chapters)
placed: list[int] = []
while remaining:
ready = [c for c in remaining if all(p in placed for p in PREREQS.get(c, ()))]
if not ready: # unreachable with the current acyclic table; fail loudly if it changes
raise RuntimeError("prerequisite cycle in PREREQS")
ready.sort(key=lambda c: (promoted.get(c, 0), c))
nxt = ready[0]
placed.append(nxt)
remaining.discard(nxt)
return placed
def score_lanes(goal: str) -> list[tuple[str, int]]:
"""Score every lane by keyword hits in the goal text, best first.
Ties are broken by keyword specificity the lane whose longest matched
keyword is longest wins because an equal hit count between a generic term
and a discriminating one should not be settled by luck. "train a transformer"
hits `practitioner` on "train" and `sequence` on "transformer", one each; the
longer, more specific match is the one that names the subject. Lane key is the
final tie-break so the ordering stays deterministic.
"""
text = goal.lower()
scored = []
for key, lane in LANES.items():
matched = [kw for kw in lane["keywords"] if _matches(kw, text)]
if matched:
scored.append((key, len(matched), max(len(kw) for kw in matched)))
scored.sort(key=lambda row: (-row[1], -row[2], row[0]))
return [(key, hits) for key, hits, _ in scored]
def out_of_scope_hits(goal: str) -> list[str]:
text = goal.lower()
return [note for token, note in OUT_OF_SCOPE.items() if _matches(token, text)]
def plan(goal: str, background: str, hours_per_week: float,
include_intro: bool) -> dict:
lane_key, _ = score_lanes(goal)[0]
lane = LANES[lane_key]
targets = lane["targets"]
chapters = close_prerequisites(targets)
if include_intro and 1 not in chapters:
# ch01 is context, not a prerequisite of anything, so it never arrives via
# closure — the flag is the only way to reach it outside the complete lane.
# (An earlier form of this filtered ch01 *out*, which was inert: nothing
# depends on ch01, and the one lane that targets it skipped the filter.)
chapters.append(1)
ordered = order_path(chapters)
multiplier, background_note = BACKGROUNDS[background]
entries = []
for chapter in ordered:
hours = round(BASE_HOURS[chapter] * multiplier, 1)
entries.append({
"chapter": chapter,
"title": TITLES[chapter],
"role": "target" if chapter in targets else "prerequisite",
"hours": hours,
"file": f"chapters/ch{chapter:02d}-*.md",
"url": "https://www.deeplearningbook.org/",
})
total_hours = round(sum(e["hours"] for e in entries), 1)
weeks = round(total_hours / hours_per_week, 1) if hours_per_week > 0 else None
skipped = [c for c in range(1, 21) if c not in ordered]
return {
"goal": goal,
"lane": lane_key,
"lane_label": lane["label"],
"background": background,
"background_note": background_note,
"hours_per_week": hours_per_week,
"path": entries,
"total_hours": total_hours,
"estimated_weeks": weeks,
"skipped_chapters": skipped,
"note": lane["note"],
"assumptions": {
"base_hours_per_chapter": BASE_HOURS,
"background_multiplier": multiplier,
"basis": "planning heuristic, not measurement — recalibrate after chapter one",
},
"hard_prerequisites_applied": {
str(c): list(PREREQS[c]) for c in ordered if PREREQS.get(c)
},
}
# --------------------------------------------------------------------------- output
def render(result: dict) -> str:
lines = [
"READING PATH",
"=" * 64,
f"Goal : {result['goal']}",
f"Lane : {result['lane_label']}",
f"Background : {result['background']}{result['background_note']}",
f"Budget : {result['total_hours']} h at {result['hours_per_week']} h/week"
f"{result['estimated_weeks']} weeks",
"",
f"{'#':>3} {'ch':>4} {'hrs':>5} role title",
"-" * 64,
]
for index, entry in enumerate(result["path"], start=1):
lines.append(
f"{index:>3} ch{entry['chapter']:02d} {entry['hours']:>5} "
f"{entry['role']:<12} {entry['title']}"
)
lines.append("-" * 64)
if result["hard_prerequisites_applied"]:
lines.append("Hard prerequisites pulled in:")
for chapter, prereqs in result["hard_prerequisites_applied"].items():
names = ", ".join(f"ch{p:02d}" for p in prereqs)
lines.append(f" ch{int(chapter):02d} needs {names}")
if result["skipped_chapters"]:
skipped = ", ".join(f"ch{c:02d}" for c in result["skipped_chapters"])
lines.append(f"Not in this path: {skipped}")
lines.append("")
lines.append(f"Note: {result['note']}")
lines.append("Hours are a planning heuristic. Recalibrate after your first chapter.")
lines.append("Read the chapters free at https://www.deeplearningbook.org/")
return "\n".join(lines)
SAMPLE_GOAL = "I want to train convolutional models for image classification and debug them"
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(
description="Plan a prerequisite-closed reading path through the Deep Learning book.",
epilog="Exit codes: 0 ok · 3 goal outside the book · 4 goal too vague to route.",
)
parser.add_argument("--goal", help="what you want to be able to do afterwards")
parser.add_argument("--background", default="applied", choices=sorted(BACKGROUNDS),
help="your starting point (default: applied)")
parser.add_argument("--hours-per-week", type=float, default=5.0,
help="study hours available per week (default: 5)")
parser.add_argument("--include-intro", action="store_true",
help="add ch01 to the path; it is context rather than content, "
"so no lane pulls it in on its own (the complete read "
"already includes it)")
parser.add_argument("--output", choices=("text", "json"), default="text")
parser.add_argument("--sample", action="store_true",
help="run against a built-in example goal")
args = parser.parse_args(argv)
goal = SAMPLE_GOAL if args.sample else args.goal
if not goal:
parser.error("--goal is required (or use --sample)")
if args.hours_per_week <= 0:
parser.error("--hours-per-week must be positive")
scoped_out = out_of_scope_hits(goal)
lane_scores = score_lanes(goal)
top_score = lane_scores[0][1] if lane_scores else 0
# An out-of-scope subject wins over a weak lane match: "LoRA fine-tuning" hits the
# practitioner lane on the word "tuning" while being entirely outside the book.
if scoped_out and (len(scoped_out) >= 2 or top_score < 2):
payload = {
"status": "out_of_scope",
"goal": goal,
"reasons": scoped_out,
"pointer": "references/book_to_2026_delta.md",
}
if args.output == "json":
print(json.dumps(payload, indent=2))
else:
print("OUT OF SCOPE — the 2016 book does not cover this goal.\n")
for reason in scoped_out:
print(f" - {reason}")
print("\nSee references/book_to_2026_delta.md for what replaced the book's "
"position, and route to the skills named above.")
return 3
if not lane_scores:
payload = {
"status": "unroutable",
"goal": goal,
"questions": [
"What do you want to be able to DO afterwards — train, diagnose, "
"derive, or evaluate?",
"Which data type: images, sequences, tabular, or generative modelling?",
"Is this a refresher over known material or a first pass?",
],
"lanes": {key: lane["label"] for key, lane in LANES.items()},
}
if args.output == "json":
print(json.dumps(payload, indent=2))
else:
print("CANNOT ROUTE — the goal does not name a subject in the book.\n")
print("Answer one of these and re-run:")
for question in payload["questions"]:
print(f" - {question}")
print("\nOr name a lane directly:")
for key, label in payload["lanes"].items():
print(f" {key:<15} {label}")
return 4
result = plan(goal, args.background, args.hours_per_week, args.include_intro)
if scoped_out:
result["scope_warnings"] = scoped_out
if args.output == "json":
print(json.dumps(result, indent=2))
else:
print(render(result))
if scoped_out:
print("\nPartly outside the book — these parts are not covered:")
for reason in scoped_out:
print(f" - {reason}")
return 0
if __name__ == "__main__":
sys.exit(main())

View file

@ -0,0 +1,306 @@
#!/usr/bin/env python3
"""training_diagnostics.py — Chapter 11's triage as an executable decision tree.
Chapter 11 argues that knowing many algorithms matters less than knowing which one a
measurement calls for, and gives the rule most teams get backwards: *read training
error first*. High training error means the model or the optimizer is the bottleneck,
and collecting more data will not help.
This tool takes the measurements you already have from a run and returns a ranked
diagnosis, the specific next action, and the chapter that justifies it. Rules fire in
priority order, so a NaN is never diagnosed as overfitting.
The thresholds are documented defaults, not physics every one is overridable, and
--output json prints the values actually used.
Standard library only. No network calls, no model loading.
Exit codes:
0 a diagnosis was produced and training looks healthy
1 a diagnosis was produced and something needs fixing
2 usage error (argparse)
4 not enough measurements to diagnose the missing ones are named
"""
from __future__ import annotations
import argparse
import json
import math
import sys
# Documented defaults. Every one is overridable from the command line.
DEFAULTS = {
# Relative gap = (val - train) / max(train, floor). Above this, overfitting.
"overfit_rel_gap": 0.30,
# Below this relative gap, the run is not overfitting in any actionable sense.
"healthy_rel_gap": 0.10,
# Gradient norm above this is a cliff (ch08); clip before anything else.
"grad_explode": 100.0,
# Gradient norm below this with non-trivial loss means saturation or dead units.
"grad_vanish": 1e-6,
# Divisor floor so a near-zero training loss does not produce an infinite ratio.
"loss_floor": 1e-6,
# Training loss above target * this multiple counts as underfitting.
"underfit_multiple": 1.15,
}
class Finding:
def __init__(self, rank: int, code: str, verdict: str, evidence: str,
action: str, chapter: str) -> None:
self.rank = rank
self.code = code
self.verdict = verdict
self.evidence = evidence
self.action = action
self.chapter = chapter
def as_dict(self) -> dict:
return {
"rank": self.rank,
"code": self.code,
"verdict": self.verdict,
"evidence": self.evidence,
"action": self.action,
"chapter": self.chapter,
}
def diagnose(train_loss: float | None, val_loss: float | None,
grad_norm: float | None, target_loss: float | None,
tiny_subset_fits: str, nan_seen: bool,
epochs: int | None, thresholds: dict) -> tuple[list[Finding], dict]:
"""Return (findings, metrics). Rules fire in priority order; rank 1 acts first."""
findings: list[Finding] = []
metrics: dict = {}
non_finite = (
nan_seen
or (train_loss is not None and not math.isfinite(train_loss))
or (val_loss is not None and not math.isfinite(val_loss))
)
# --- Rule 1: numerics before modelling (ch04) -------------------------------
if non_finite:
findings.append(Finding(
len(findings) + 1, "NUMERICS",
"Loss is NaN or infinite — this is a numerics failure, not a modelling one",
"a non-finite loss was reported",
"Check in this order: log(0) or log of a negative, division by a near-zero "
"denominator, exp of a large logit, then an exploding gradient. Use fused "
"log_softmax / cross-entropy rather than hand-rolled exp-then-normalize, and "
"work in log-space for probability products.",
"ch04 (Numerical Computation)",
))
# A non-finite loss makes every downstream ratio meaningless.
return findings, metrics
# --- Rule 2: is it a bug at all? (ch11) -------------------------------------
if tiny_subset_fits == "no":
findings.append(Finding(
len(findings) + 1, "BUG",
"The model cannot overfit a tiny subset — this is a bug, not a hard problem",
"--tiny-subset-fits no",
"Stop tuning. Check the data pipeline (labels aligned with inputs?), the loss "
"reduction, whether gradients actually reach the parameters (a detached tensor "
"or a frozen module), and the learning rate. Compare backprop against numerical "
"derivatives on one layer if it is still unclear.",
"ch11 (Practical Methodology — debugging strategies)",
))
# --- Rule 3: gradient behaviour (ch08, ch10, ch06) --------------------------
if grad_norm is not None:
metrics["grad_norm"] = grad_norm
if grad_norm > thresholds["grad_explode"]:
findings.append(Finding(
len(findings) + 1, "EXPLODING_GRADIENT",
"Gradient norm is in cliff territory",
f"grad_norm {grad_norm:g} > {thresholds['grad_explode']:g}",
"Clip gradients by global norm before changing anything else. If a "
"recurrence is in the graph, clipping is not optional. Then re-check the "
"learning rate and the initialization scale.",
"ch08 (Optimization — cliffs), ch10 (exploding gradients through time)",
))
elif grad_norm < thresholds["grad_vanish"]:
findings.append(Finding(
len(findings) + 1, "VANISHING_GRADIENT",
"Gradient norm is effectively zero — units are saturated or dead",
f"grad_norm {grad_norm:g} < {thresholds['grad_vanish']:g}",
"Check for saturating hidden units (sigmoid/tanh in a deep stack), dead "
"ReLUs from a too-large learning rate, and initialization scale "
"(He/Xavier). Add residual connections or normalization if the stack is "
"deep.",
"ch08 (initialization), ch06 (hidden units), ch10 (vanishing gradients)",
))
# --- Rule 4/5: the fit verdict (ch05, ch07, ch11) ---------------------------
if train_loss is not None and val_loss is not None:
denom = max(abs(train_loss), thresholds["loss_floor"])
gap = val_loss - train_loss
rel_gap = gap / denom
metrics.update({
"train_loss": train_loss,
"val_loss": val_loss,
"gap": round(gap, 6),
"relative_gap": round(rel_gap, 4),
})
underfitting = None
if target_loss is not None:
metrics["target_loss"] = target_loss
underfitting = train_loss > target_loss * thresholds["underfit_multiple"]
if underfitting:
findings.append(Finding(
len(findings) + 1, "UNDERFIT",
"Training error is above target — the bottleneck is capacity or optimization",
f"train_loss {train_loss:g} > target {target_loss:g} × "
f"{thresholds['underfit_multiple']}",
"Do NOT collect more data — it cannot help while training error is high. "
"In order: tune learning rate and schedule, check initialization, add "
"capacity, remove regularization you added earlier, train longer.",
"ch11 (the data-vs-capacity rule), ch08 (Optimization), ch05 (capacity)",
))
elif rel_gap > thresholds["overfit_rel_gap"]:
findings.append(Finding(
len(findings) + 1, "OVERFIT",
"Validation error substantially exceeds training error",
f"relative gap {rel_gap:.2f} > {thresholds['overfit_rel_gap']}",
"Work the regularization ladder in cost order, one change at a time: more "
"real data → label-preserving augmentation → early stopping → decoupled "
"weight decay (AdamW, not Adam+L2) → label smoothing → dropout. Shrink the "
"model LAST: past the interpolation threshold, double descent means a "
"bigger model with more data can generalize better.",
"ch07 (Regularization), ch05 (capacity and the U-curve's caveat)",
))
elif rel_gap < thresholds["healthy_rel_gap"] and target_loss is None:
findings.append(Finding(
len(findings) + 1, "GAP_SMALL_TARGET_UNKNOWN",
"The train/val gap is small — but without a target loss this cannot "
"distinguish 'converged' from 'underfitting equally on both splits'",
f"relative gap {rel_gap:.2f} < {thresholds['healthy_rel_gap']}, "
"no --target-loss supplied",
"Supply --target-loss (a human baseline, a published number, or the "
"irreducible-error estimate for the task) and re-run. Chapter 11's first "
"step is naming the metric and its target value, and this is why.",
"ch11 (determine goals: error metric and target value)",
))
if not findings:
findings.append(Finding(
1, "HEALTHY",
"No rule fired — the measurements supplied look healthy",
"; ".join(f"{k}={v}" for k, v in metrics.items()) or "measurements within thresholds",
"Confirm the metric you are optimizing is the one you care about, then change "
"one thing per experiment and keep the log.",
"ch11 (Practical Methodology)",
))
if epochs is not None:
metrics["epochs"] = epochs
return findings, metrics
def render(findings: list[Finding], metrics: dict, thresholds: dict) -> str:
lines = ["TRAINING DIAGNOSIS", "=" * 68]
if metrics:
lines.append("Measurements: " + " ".join(f"{k}={v}" for k, v in metrics.items()))
lines.append("")
for finding in findings:
lines.append(f"[{finding.rank}] {finding.code}{finding.verdict}")
lines.append(f" evidence : {finding.evidence}")
lines.append(f" action : {finding.action}")
lines.append(f" chapter : {finding.chapter}")
lines.append("")
lines.append("Thresholds used: " + ", ".join(f"{k}={v}" for k, v in thresholds.items()))
lines.append("Rules fire in priority order — act on [1] before anything below it.")
return "\n".join(lines)
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(
description="Diagnose a training run against Chapter 11's decision tree.",
epilog="Exit codes: 0 healthy · 1 something needs fixing · 4 not enough input.",
)
parser.add_argument("--train-loss", type=float, help="final or current training loss")
parser.add_argument("--val-loss", type=float, help="matching validation loss")
parser.add_argument("--target-loss", type=float,
help="the loss value that would count as success — a human "
"baseline, a published number, or an irreducible-error "
"estimate. Without it, underfitting cannot be detected.")
parser.add_argument("--grad-norm", type=float, help="observed global gradient norm")
parser.add_argument("--epochs", type=int, help="epochs trained so far (recorded only)")
parser.add_argument("--nan", action="store_true",
help="the loss went NaN or inf at any point")
parser.add_argument("--tiny-subset-fits", choices=("yes", "no", "unknown"),
default="unknown",
help="can the model drive training loss to ~0 on 10-50 examples? "
"(ch11's smoke test; default: unknown)")
parser.add_argument("--overfit-rel-gap", type=float, default=DEFAULTS["overfit_rel_gap"])
parser.add_argument("--healthy-rel-gap", type=float, default=DEFAULTS["healthy_rel_gap"])
parser.add_argument("--grad-explode", type=float, default=DEFAULTS["grad_explode"])
parser.add_argument("--grad-vanish", type=float, default=DEFAULTS["grad_vanish"])
parser.add_argument("--underfit-multiple", type=float,
default=DEFAULTS["underfit_multiple"])
parser.add_argument("--output", choices=("text", "json"), default="text")
parser.add_argument("--sample", action="store_true",
help="run against a built-in overfitting example")
args = parser.parse_args(argv)
if args.sample:
args.train_loss, args.val_loss = 0.02, 1.90
args.grad_norm, args.epochs = 0.4, 30
args.tiny_subset_fits = "yes"
thresholds = {
"overfit_rel_gap": args.overfit_rel_gap,
"healthy_rel_gap": args.healthy_rel_gap,
"grad_explode": args.grad_explode,
"grad_vanish": args.grad_vanish,
"loss_floor": DEFAULTS["loss_floor"],
"underfit_multiple": args.underfit_multiple,
}
have_losses = args.train_loss is not None and args.val_loss is not None
if not have_losses and not args.nan and args.grad_norm is None \
and args.tiny_subset_fits == "unknown":
missing = {
"status": "insufficient_input",
"need_at_least_one_of": [
"--train-loss with --val-loss",
"--grad-norm",
"--nan",
"--tiny-subset-fits yes|no",
],
"note": "Chapter 11's first instruction is to instrument the run. This tool "
"reads instruments; it does not guess.",
}
if args.output == "json":
print(json.dumps(missing, indent=2))
else:
print("NOT ENOUGH INPUT — supply at least one of:")
for item in missing["need_at_least_one_of"]:
print(f" {item}")
print(f"\n{missing['note']}")
return 4
findings, metrics = diagnose(
args.train_loss, args.val_loss, args.grad_norm, args.target_loss,
args.tiny_subset_fits, args.nan, args.epochs, thresholds,
)
if args.output == "json":
print(json.dumps({
"findings": [f.as_dict() for f in findings],
"metrics": metrics,
"thresholds": thresholds,
}, indent=2))
else:
print(render(findings, metrics, thresholds))
return 0 if findings[0].code == "HEALTHY" else 1
if __name__ == "__main__":
sys.exit(main())

View file

@ -0,0 +1,22 @@
{
"source": {
"spec": "generated by engineering/book-to-skill",
"build_pattern": "book-to-skill conversion: extract -> analyze -> chapter files + glossary + patterns + cheatsheet -> master SKILL.md",
"distinct_from": "not a hand-authored skill; every claim traces to the source document named below",
"source_document": "Spinning Up in Deep RL by Joshua Achiam (OpenAI)",
"chapters": 20,
"distribution": "shareable",
"license_scope": "plugin.json's top-level `license` covers this package's scaffolding only. The compiled notes under skills/ are derived from the source document and carry that work's terms; see source.rights_basis.",
"rights_basis": "open-license",
"rights_note": "the source work carries a licence permitting derivative distribution"
},
"attribution": {
"derived_from": "https://github.com/openai/spinningup",
"upstream_docs": "https://spinningup.openai.com/",
"upstream_path": "docs/ (reStructuredText tree, 38 files)",
"original_author": "Joshua Achiam, OpenAI",
"original_license": "MIT",
"original_copyright": "Copyright (c) 2018 OpenAI (http://openai.com)",
"derivation_note": "No upstream code or prose is reproduced. The compiled skill is structured study notes -- named frameworks, key concepts, decision rules and per-chapter summaries -- generated by engineering/book-to-skill from the source's docs/ tree, with chapter structure taken from the source's own toctree. Upstream's MIT notice is reproduced in full in this package's LICENSE, which is where the licence obligation is met; this file is authoring metadata and is not a licence notice. Coverage is pinned to the source's final (January 2020 PyTorch) update."
}
}

View file

@ -0,0 +1,15 @@
{
"name": "spinning-up-deep-rl",
"description": "Knowledge base from \"Spinning Up in Deep RL\" by Joshua Achiam (OpenAI, MIT-licensed). Use when applying Achiam's frameworks for RL fundamentals and MDPs, the model-free algorithm taxonomy, policy gradient derivations, the six reference algorithms (VPG, TRPO, PPO, DDPG, TD3, SAC), debugging silently-failing RL code, or running rigorous multi-seed RL experiments.",
"version": "1.0.0",
"author": {
"name": "Alireza Rezvani",
"url": "https://github.com/alirezarezvani"
},
"homepage": "https://github.com/alirezarezvani/claude-skills/tree/main/engineering/spinning-up-deep-rl",
"repository": "https://github.com/alirezarezvani/claude-skills",
"license": "MIT",
"skills": [
"./skills/spinning-up-deep-rl"
]
}

View file

@ -0,0 +1,58 @@
This package has two layers with two different terms.
------------------------------------------------------------------------------
1. Package scaffolding — plugin manifest, agent, command, README
------------------------------------------------------------------------------
MIT License
Copyright (c) 2026 Alireza Rezvani
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
------------------------------------------------------------------------------
2. Compiled notes under skills/spinning-up-deep-rl/
------------------------------------------------------------------------------
Derived from OpenAI's "Spinning Up in Deep RL" documentation
(https://spinningup.openai.com/ · https://github.com/openai/spinningup),
primarily developed by Joshua Achiam. Distributed under the same MIT terms,
whose notice is reproduced below in full as that licence requires.
The MIT License
Copyright (c) 2018 OpenAI (http://openai.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -0,0 +1,49 @@
# Spinning Up in Deep RL
Knowledge-base plugin compiled from **Spinning Up in Deep RL by Joshua Achiam (OpenAI)** by
[`engineering/book-to-skill`](../book-to-skill/). 20 chapters indexed.
## What is in here
| File | Contents |
|------|----------|
| `skills/spinning-up-deep-rl/SKILL.md` | Core frameworks, chapter index, topic index (resident, under 4k tokens) |
| `skills/spinning-up-deep-rl/chapters/` | One summary per chapter — loaded on demand, never all at once |
| `skills/spinning-up-deep-rl/glossary.md` | Every significant term, alphabetized, with its chapter |
| `skills/spinning-up-deep-rl/patterns.md` | Techniques and design patterns with trade-offs |
| `skills/spinning-up-deep-rl/cheatsheet.md` | Decision rules, thresholds and trade-off matrices |
## Use
```
/cs:spinning-up-deep-rl # core frameworks + chapter index
/cs:spinning-up-deep-rl <topic> # resolve via topic index, read one chapter
/cs:spinning-up-deep-rl ch05 # read one chapter summary
```
Or invoke the `cs-spinning-up-deep-rl` agent for a working session anchored to this source.
## Provenance and limits
**Source:** OpenAI's [Spinning Up in Deep RL](https://spinningup.openai.com/)
([openai/spinningup](https://github.com/openai/spinningup)), primarily developed by
**Joshua Achiam**. Compiled from the `docs/` reStructuredText tree at the January 2020
PyTorch update.
**Rights basis:** `open-license`. The source is **MIT, Copyright (c) 2018 OpenAI**, which
permits derivative distribution. The full upstream notice is reproduced in
[`LICENSE`](LICENSE) alongside this package's own; the top-level `license` field in
`plugin.json` covers the scaffolding only.
Generated, not hand-authored: every claim traces to the source document. It carries that source's
blind spots, and it is a set of structured notes — **not a copy of the work and not a substitute
for reading it**.
**What it does not cover:** DQN and the discrete-action value-learning family, recurrent or
convolutional architectures, partially-observed settings, model-based implementations, and any
deep RL work after early 2020. The six implementations documented are educational; `ch13` records
which are research-grade (DDPG, TD3, SAC) and which are not (VPG, TRPO, PPO).
Distribution: `shareable`. Regenerate or extend with
`python3 engineering/book-to-skill/skills/book-to-skill/scripts/extract_document.py`, then re-run
`book_skill_validator.py` before loading the result.

View file

@ -0,0 +1,37 @@
---
name: cs-spinning-up-deep-rl
description: Answers from the knowledge base compiled from Spinning Up in Deep RL by Joshua Achiam (OpenAI). Loads the master frameworks first and reads a single chapter file on demand rather than the whole source. Refuses to answer beyond what the source covers.
skills: engineering/spinning-up-deep-rl/skills/spinning-up-deep-rl
domain: engineering
model: opus
tools: [Read, Grep, Glob]
---
# Spinning Up in Deep RL — Knowledge Agent
## Voice
**Opening:** "Which framework or chapter are you reaching for?"
**Forcing question:** "Is this something the source actually covers, or are you asking me to
extrapolate past it?"
**Closing:** "That is the author's formulation, from ch<N>. Anything past it is my inference, not theirs."
## Purpose
Applies the frameworks compiled from **Spinning Up in Deep RL by Joshua Achiam (OpenAI)** (20 chapters
indexed) while the user works. Answers with the author's exact naming, then cites the chapter.
## How it navigates
1. Read `skills/spinning-up-deep-rl/SKILL.md` — Core Frameworks and both indexes.
2. Match the question against the Topic Index; read **only** the chapter files it points to.
3. Reach for `glossary.md` for a term, `patterns.md` for a technique, `cheatsheet.md` for a decision.
4. Never load every chapter — that is the cost this skill exists to avoid.
## Hard rules
- **Cite the chapter.** Every framework claim names the chapter it came from.
- **Do not extrapolate silently.** If the source does not cover it, say so before answering from
general knowledge, and label which is which.
- **Preserve exact naming.** The author's term is the interface; a paraphrase breaks lookup.
- **Do not reproduce the source at length.** These are structured notes, not a copy of the work.

View file

@ -0,0 +1,30 @@
---
name: "cs-spinning-up-deep-rl"
description: "/cs:spinning-up-deep-rl [topic | framework | chNN] — query the knowledge base compiled from Spinning Up in Deep RL by Joshua Achiam (OpenAI). Use when applying its frameworks while working, looking up a term, or reading one chapter's summary."
---
# /cs:spinning-up-deep-rl — Spinning Up in Deep RL
**Command:** `/cs:spinning-up-deep-rl [topic | framework name | chNN]`
## When to run
- Applying a framework from this source to work in progress
- Looking up the author's exact formulation of a term
- Reading one chapter's compiled summary without opening the source
- Checking whether the source covers a question at all
## What it does
1. Loads `engineering/spinning-up-deep-rl/skills/spinning-up-deep-rl/SKILL.md` — Core Frameworks plus the Chapter and Topic indexes.
2. **No argument** → reports the core frameworks and the chapter index.
3. **A topic or framework name** → resolves it through the Topic Index and reads only the
matching chapter file.
4. **`chNN`** → reads that chapter's summary directly.
5. Answers with the author's naming and cites the chapter.
## Boundary
This command answers from **one source** (20 chapters indexed). Anything it does not
cover gets said out loud rather than filled in — and hands-on work in your codebase belongs to the
engineering skills, not here.

View file

@ -0,0 +1,192 @@
---
name: spinning-up-deep-rl
description: "Knowledge base from \"Spinning Up in Deep RL\" by Joshua Achiam (OpenAI, MIT-licensed). Use when applying Achiam's frameworks for RL fundamentals and MDPs, the model-free algorithm taxonomy, policy gradient derivations, the six reference algorithms (VPG, TRPO, PPO, DDPG, TD3, SAC), debugging silently-failing RL code, or running rigorous multi-seed RL experiments."
---
# Spinning Up in Deep RL
**Author**: Joshua Achiam (OpenAI) | **Source**: spinningup.readthedocs.io, MIT | **Chapters**: 20 | **Generated**: 2026-08-25
## How to Use This Skill
- **No argument** — load the core frameworks below
- **A topic** — ask about `advantage function`, `target networks`, `entropy regularization`;
I resolve it through the Topic Index and read that chapter file
- **`chNN`** — I load that chapter's summary
- **"what chapters do you have?"** — the full index
```
/cs:spinning-up-deep-rl # core frameworks + chapter index
/cs:spinning-up-deep-rl entropy regularization # topic index -> ch19, read that chapter
/cs:spinning-up-deep-rl ch09 # one chapter summary
```
When you ask about something not in Core Frameworks, I read the relevant chapter file before
answering rather than guessing from the index.
---
## Core Frameworks & Mental Models
### The RL problem
`pi* = argmax_pi J(pi)`, where `J(pi) = E_{tau~pi}[R(tau)]`. Every algorithm approximates
this; where it substitutes a different objective (a Bellman residual, a surrogate), that
substitution is the source of its failure modes. Four value functions — `V^pi`, `Q^pi`, `V*`,
`Q*` — all obey Bellman self-consistency, and `a*(s) = argmax_a Q*(s,a)` is why Q-learning
is a viable family at all. Advantage `A^pi(s,a) = Q^pi(s,a) - V^pi(s)` is the relative-quality
signal policy gradients run on. (ch07)
### The two branching questions
Place any algorithm by asking: **does it have or learn a model**, and **what does it learn**
(policy, Q-function, value function, model). That generates the whole landscape. (ch08)
### Policy optimization vs Q-learning — the central trade-off
- **Policy optimization** is *principled: you directly optimize the thing you want.* Stable
and reliable. On-policy, so it cannot reuse data, so it is sample-hungry.
- **Q-learning** only *indirectly* optimizes performance, by training `Q_theta` to satisfy a
self-consistency equation. Many failure modes, so less stable. But substantially more
sample efficient when it works, because it reuses everything.
- **Satisfying the Bellman equations well carries no guarantee of good policy performance.**
- The two are not exclusive — DDPG and SAC live between them deliberately. (ch08)
### The policy gradient template
`grad J = E[ sum_t grad log pi_theta(a_t|s_t) * Phi_t ]`. Five valid choices of `Phi_t`:
full return, reward-to-go, reward-to-go minus a baseline, `Q^pi`, and `A^pi`. All share an
expectation and differ in variance. Two rules get you from the first to the last:
- **Don't let the past distract you** — drop rewards obtained before the action. Those terms
had zero mean and nonzero variance: pure noise.
- **Baselines** — by the EGLP lemma, any state-only `b(s)` can be added or subtracted freely.
The standard choice is `V^pi(s_t)`, learned by MSE regression onto reward-to-go. (ch09)
### The policy-gradient loss is not a loss function
Its data distribution depends on the parameters, and it does not measure performance even in
expectation. Only at the current parameters, with data from those parameters, does it have
the negative gradient of performance. **You can send it to negative infinity while performance
craters, and it usually will. Only average return means anything.** (ch09)
### Broken RL code almost always fails silently
It runs fine; the agent just never learns. Usually something is computed with the wrong
equation, on the wrong distribution, or piped to the wrong place. **If it doesn't work, assume
there's a bug** before touching hyperparameters. Debug by measuring everything and reading the
code critically. The archetype is one missing `squeeze`: a `[N]` vs `[N,1]` shape mismatch is
broadcast-compatible, raises nothing, and silently turns the Bellman backup into an `[N,N]`
matrix. (ch10, ch12)
### Learn by doing
Write your own implementations, **shortest correct version** of each, **simplest algorithms
first**. VPG, DQN, A2C, PPO, DDPG, roughly in that order; ~250-300 lines each. Single-threaded
before parallel. **Iterate fast in simple environments — under 5 minutes turnaround at the
debug stage.** Do not attempt Atari or Humanoid before the toy task works. Read papers for
their ablations and supplementary material, but **do not overfit to paper details** (the
original DDPG's architecture, init scheme and batch norm are not strictly necessary) **or to
existing implementations** (their abstractions serve reuse, not your single use case). (ch10)
### Rigor: four standards
1. **Fair comparisons** — tune the baseline as hard as your method; never handicap it.
2. **Remove stochasticity as a confounder** — at least 3 seeds, 10 or more to be thorough.
Two seed groups can produce curves that look like different distributions.
3. **High-integrity experiments** — launch fresh final runs and precommit to reporting them.
Tuning produces hypotheses; final runs produce conclusions.
4. **Check each claim separately** — ablate every design decision. (ch10)
### The safe-step family (on-policy)
VPG takes an unconstrained gradient step, so a single bad step can collapse performance.
**TRPO** constrains the step in **KL-divergence between policies, not distance in parameter
space**, then backtracking-line-searches until the exact constraint holds. **PPO** drops the
constraint and instead **clips the objective so the policy gains nothing by moving far**,
which is first-order, far simpler, and empirically at least as good. (ch14, ch15, ch16)
### The overestimation family (off-policy)
DDPG amortizes the intractable continuous `max_a Q(s,a)` into a learned policy:
`max_a Q(s,a) ~= Q(s, mu(s))`. It needs a **replay buffer** (licensed because the Bellman
equation is indifferent to how data was collected) and **target networks** (because the target
otherwise depends on the parameters being trained). Its failure mode is **Q-value
overestimation, which the policy actively exploits**. **TD3** answers with clipped double-Q,
delayed policy updates and target policy smoothing. **SAC** adds **entropy regularization**,
making the explore-exploit trade-off an explicit coefficient `alpha`. (ch17, ch18, ch19)
---
## Chapter Index
| # | Title | Key Frameworks |
|---|-------|----------------|
| [ch01](chapters/ch01-introduction.md) | Introduction | The missing middle step, Code Design Philosophy |
| [ch02](chapters/ch02-installation.md) | Installation | Install-then-verify, MuJoCo optionality |
| [ch03](chapters/ch03-algorithm-lineup.md) | Algorithms: What's Included and Why | The two lineages, on/off-policy trade-off, code template |
| [ch04](chapters/ch04-running-experiments.md) | Running Experiments | One flag per kwarg, ExperimentGrid, save-dir suffixes |
| [ch05](chapters/ch05-experiment-outputs.md) | Experiment Outputs | Tools not files, watch-then-measure |
| [ch06](chapters/ch06-plotting-results.md) | Plotting Results | `Performance` alias, prefix autocompletion, seed averaging |
| [ch07](chapters/ch07-key-concepts-in-rl.md) | Part 1: Key Concepts in RL | MDPs, four value functions, Bellman equations, advantage |
| [ch08](chapters/ch08-kinds-of-rl-algorithms.md) | Part 2: Kinds of RL Algorithms | Taxonomy, model bias, policy-opt vs Q-learning |
| [ch09](chapters/ch09-intro-to-policy-optimization.md) | Part 3: Intro to Policy Optimization | Log-derivative trick, EGLP lemma, reward-to-go, baselines |
| [ch10](chapters/ch10-spinning-up-as-a-researcher.md) | Spinning Up as a Deep RL Researcher | Learn by doing, three idea frames, four rigor standards |
| [ch11](chapters/ch11-key-papers-in-deep-rl.md) | Key Papers in Deep RL | 13-section topic map |
| [ch12](chapters/ch12-exercises.md) | Exercises | Problem Set 1 and 2, the silent DDPG bug |
| [ch13](chapters/ch13-benchmarks.md) | Benchmarks | The parity disclosure, family-specific metrics |
| [ch14](chapters/ch14-vpg.md) | Vanilla Policy Gradient | The six-step loop |
| [ch15](chapters/ch15-trpo.md) | Trust Region Policy Optimization | KL trust region, line search, conjugate gradient |
| [ch16](chapters/ch16-ppo.md) | Proximal Policy Optimization | PPO-Clip, KL early stopping |
| [ch17](chapters/ch17-ddpg.md) | Deep Deterministic Policy Gradient | MSBE, replay buffers, target networks, polyak |
| [ch18](chapters/ch18-td3.md) | Twin Delayed DDPG | Clipped double-Q, delayed updates, target smoothing |
| [ch19](chapters/ch19-sac.md) | Soft Actor-Critic | Entropy regularization, reparameterization, squashed Gaussian |
| [ch20](chapters/ch20-logger-and-utilities.md) | Logger, MPI Tools and Run Utils | EpochLogger pattern, MPI PyTorch order |
## Topic Index
- **Advantage function** ch07, ch09, ch14
- **Baselines** ch09
- **Bellman equations** ch07, ch17
- **Benchmarks / parity** ch13, ch01
- **Clipped double-Q** ch18, ch19
- **Continuous action spaces** ch07, ch17
- **Debugging / silent failure** ch10, ch12
- **DDPG** ch17, ch03, ch08
- **Entropy regularization** ch19
- **Exploration vs exploitation** ch14, ch17, ch19
- **GAE** ch09, ch14
- **Installation** ch02
- **KL divergence / trust region** ch15, ch16
- **Logging** ch20, ch05
- **MDPs** ch07
- **Model-based RL** ch08
- **MPI / parallelization** ch20, ch02, ch04
- **MSBE** ch17
- **Off-policy** ch03, ch08, ch17
- **On-policy** ch03, ch08, ch14
- **Papers / literature** ch11, ch10
- **Plotting** ch06, ch13
- **Policies (categorical, Gaussian, squashed)** ch07, ch19
- **Policy gradient derivation** ch09
- **PPO** ch16, ch03
- **Q-learning** ch08, ch07
- **Replay buffer** ch17
- **Reparameterization trick** ch19, ch10
- **Research process / rigor** ch10, ch13
- **Reward-to-go** ch09
- **Running experiments** ch04, ch05
- **SAC** ch19, ch03, ch08
- **Seeds / variance** ch10, ch13, ch04
- **Target networks / polyak** ch17, ch18
- **TD3** ch18, ch12
- **TRPO** ch15, ch03
- **Value functions** ch07, ch09
- **VPG** ch14, ch09
## Supporting Files
- [glossary.md](glossary.md) · [patterns.md](patterns.md) · [cheatsheet.md](cheatsheet.md)
## Scope & Limits
Covers the Spinning Up documentation only, as of the January 2020 PyTorch update. It does
**not** cover: DQN and the discrete-action value-learning family (referenced, never
implemented here), recurrent or convolutional architectures, partially-observed settings,
model-based implementations, exploration/meta-RL/hierarchy beyond ch11's reading list, or any
deep RL work after early 2020. The six implementations are educational; ch13 says which are
research-grade. For topics beyond this source, I say so rather than improvising.
---
*Compiled from OpenAI's Spinning Up in Deep RL documentation (MIT, Copyright (c) 2018 OpenAI),
primarily developed by Joshua Achiam. Structured study notes, not a reproduction of the source.*

View file

@ -0,0 +1,102 @@
# Chapter 1: Introduction
## Core Idea
Spinning Up exists to be the missing middle step between "I want to work on deep RL"
and "I can implement and evaluate a deep RL algorithm" — the field has no standard
textbook, papers omit the design details that decide whether code works, and production
RL libraries hide the algorithm inside framework abstractions.
## Frameworks Introduced
- **The missing middle step**: the gap Spinning Up fills, between high-level awareness
(what topics exist, why they matter) and the ability to transmute an algorithm into code.
- When to use: deciding whether a resource teaches you deep RL or merely describes it.
- How: judge a resource on whether it closes the theory-to-code gap. Papers give theory
and omit details; libraries give code that hides the algorithm. Neither closes it alone.
- **Code Design Philosophy** (the four rules the implementations obey):
- **As simple as possible while still being reasonably good.** Not state of the art;
good enough to reach roughly the intended performance.
- **Highly consistent with each other**, so understanding one makes the next painless.
- **Almost completely self-contained** — virtually no shared code between algorithms
except logging, saving, loading and MPI utilities. You can study one algorithm without
following a chain of dependencies.
- **Patterned to come as close to pseudocode as possible**, minimizing the theory-code gap.
- How: when reading or writing RL code, prefer the version you can read top to bottom
over the version that reuses the most code. Reuse is an engineering virtue that is a
pedagogical cost.
- **Minimize tricks and minimize differences**: the implementations deliberately omit
tricks present in the original papers (e.g. the regularization terms in the original
Soft Actor-Critic code, observation normalization in all algorithms) and deliberately
remove gratuitous differences between similar algorithms (DDPG, TD3 and SAC all run
gradient updates after fixed intervals of environment interaction, so they compare cleanly).
- When to use: any time you are comparing two algorithms and want the comparison to be
about the algorithms rather than about their implementation choices.
## Key Concepts
- **Deep RL**: reinforcement learning (learning to solve tasks by trial and error) combined
with deep learning.
- **Reasonably good**: achieves roughly the intended performance but does not necessarily
match the best reported results in the literature on every task.
- **Maintenance mode**: Spinning Up's current status. Breaking bugs get repaired; no major
new features are planned.
- **The Rosetta Stone goal**: the motivation for the January 2020 PyTorch update — the same
algorithm expressed in two neural network libraries so the algorithm is separable from the
library.
## Mental Models
- Think of an RL library's abstraction layer as a **tax on learning**: good for code reuse
between algorithms, unnecessary if you are writing one algorithm for one use case.
- Use "**can I read this algorithm without opening another file?**" as the test of whether
an implementation is written to be learned from.
- Think of the resource landscape as **two failure modes**: papers that obscure key design
details, and public implementations that are hard to read. Spinning Up targets both.
## Anti-patterns
- **Using Spinning Up's implementations for scientific benchmarking comparisons**: they are
"reasonably good," not best-reported. See ch13 for which ones are at parity (DDPG, TD3, SAC)
and which are not (VPG, TRPO, PPO). Use OpenAI Baselines for TRPO/PPO research comparisons.
- **Assuming an educational implementation is a research implementation**: the omitted tricks
(observation normalization, normalized value regression targets) are exactly what separates
the two.
- **Treating deep RL as engineering-only**: the material explicitly serves people from
professions with no connection to engineering or computer science who nonetheless need to
make informed decisions about the technology.
## Worked Example
Support history, read as a record of what the community actually asked for after release:
| Date | Event |
|------|-------|
| Nov 8, 2018 | Initial release, followed by three weeks of high-bandwidth support |
| April 2019 | Six-month internal review of community feedback |
| Jan 2020 | The PyTorch update ships |
| Future | No major updates planned |
The April 2019 review surfaced exactly three requests, in priority order:
1. **Implementations in other neural network libraries** — enough people had written their
own PyTorch ports (Fired Up, Spinning Up Basic, Torching Up) that a "Rosetta Stone for
deep RL" became the top priority. This one shipped.
2. **Open source RL environments** (e.g. PyBullet) for benchmarks, examples and exercises,
to avoid the proprietary MuJoCo dependency. Did not ship.
3. **More algorithms**, especially Deep Q-Networks. Did not ship.
The lesson for anyone building an educational resource: the community's top request was not
more content, it was the same content expressed in the framework they already use.
## Key Takeaways
1. The barrier to entry in deep RL is not intelligence or math; it is that theory and code
are documented in separate places and neither is written to connect to the other.
2. Self-contained beats DRY when the reader is trying to learn the algorithm.
3. Consistency across implementations is a teaching feature: differences that remain are
real algorithmic differences.
4. "Reasonably good" is a deliberate, stated performance target — check ch13 before citing
any Spinning Up number as a benchmark.
5. Deep RL is central to AI safety work in OpenAI's framing; the resource exists partly as
a recruiting and capability-building pipeline for that.
## Connects To
- **Ch 3**: which algorithms were chosen and why, and the code template they all share.
- **Ch 10**: the essay on becoming a researcher — the practice counterpart to this chapter's
philosophy.
- **Ch 13**: the benchmark numbers that qualify "reasonably good."

View file

@ -0,0 +1,88 @@
# Chapter 2: Installation
## Core Idea
Spinning Up needs Python 3, OpenAI Gym and OpenMPI, on Linux or OSX; MuJoCo is optional
but is the de facto benchmarking standard, and everything in the book works without it on
the free Classic Control and Box2D environments.
## Frameworks Introduced
- **Install then immediately verify with a real training run**: the install is not confirmed
by a successful `pip install`, it is confirmed by an agent visibly learning.
- When to use: every fresh environment, before debugging anything else.
- How: run the install test below, then watch the policy and plot the curve. Three
commands, three different subsystems (training, rendering, plotting) verified.
## Key Concepts
- **OpenMPI**: the message-passing library used for the parallelized (on-policy) algorithms.
Installed with `apt-get install libopenmpi-dev` on Ubuntu, `brew install openmpi` on Mac.
- **MuJoCo**: a proprietary physics engine; free to trial and free for full-time students,
otherwise paid. The de facto standard for benchmarking continuous-control deep RL.
- **mujoco-py**: the Python bindings that let Gym use MuJoCo.
- **Classic Control / Box2D**: Gym environment families that are completely free and
sufficient to get started.
- **Editable install**: `pip install -e .` from the cloned repo, so edits to the algorithm
files take effect without reinstalling — the intended workflow for a repo you are meant
to read and modify.
## Code Examples
Environment and dependencies:
```bash
conda create -n spinningup python=3.6
conda activate spinningup
# Ubuntu
sudo apt-get update && sudo apt-get install libopenmpi-dev
# Mac OS X (requires Homebrew)
brew install openmpi
git clone https://github.com/openai/spinningup.git
cd spinningup
pip install -e .
```
Verify the install (roughly 10 minutes; leave it running and keep reading):
```bash
python -m spinup.run ppo --hid "[32,32]" --env LunarLander-v2 \
--exp_name installtest --gamma 0.999
python -m spinup.run test_policy data/installtest/installtest_s0
python -m spinup.run plot data/installtest/installtest_s0
```
Optional MuJoCo, after following the mujoco-py README and obtaining a license:
```bash
pip install gym[mujoco,robotics]
python -m spinup.run ppo --hid "[32,32]" --env Walker2d-v2 --exp_name mujocotest
```
## Reference Tables
| Requirement | Status | Notes |
|-------------|--------|-------|
| Python 3 | Required | Anaconda recommended; the docs pin 3.6 |
| OpenAI Gym | Required | Installed by `pip install -e .`, MuJoCo envs excluded |
| OpenMPI | Required | Needed for the MPI-parallelized on-policy algorithms |
| Linux / OSX | Required | Windows unsupported and untested; one community workaround exists |
| MuJoCo | Optional | Proprietary, licensed; preferred because of benchmarking convention |
## Anti-patterns
- **Skipping the install test** and then debugging an algorithm that was never installed
correctly. The install test costs ten unattended minutes.
- **Treating a MuJoCo licence as a prerequisite for learning RL**: Classic Control and Box2D
are free and adequate for everything up to benchmarking.
- **Fighting package management ad hoc**: the docs go out of their way to point at conda
explainers, because "I just installed this thing but it says it's not found" is the
predicted failure, not an unusual one.
## Key Takeaways
1. Install is Python 3 + Gym + OpenMPI, plus optional MuJoCo; Linux or OSX only.
2. `pip install -e .` (editable) because you are expected to modify the code.
3. Verification means an actual short PPO run, a rendered policy and a plot.
4. Not having MuJoCo blocks benchmarking, not learning.
## Connects To
- **Ch 4**: `python -m spinup.run` is the entry point every later chapter uses.
- **Ch 13**: the benchmarks that make MuJoCo the convention.
- **Ch 20**: the MPI utilities that OpenMPI enables.

View file

@ -0,0 +1,101 @@
# Chapter 3: Algorithms — What's Included and Why
## Core Idea
The six algorithms (VPG, TRPO, PPO, DDPG, TD3, SAC) are not a survey; they are two
lineages of ideas, each starting from a foundational algorithm and progressively fixing
its defining weakness, culminating in PPO and SAC.
## Frameworks Introduced
- **The two lineages**:
- **On-policy line: VPG to TRPO to PPO.** Each step buys back sample efficiency without
giving up the stability that comes from directly optimizing the objective you care about.
- **Off-policy line: DDPG to TD3 and SAC.** Each step mitigates the brittleness that comes
from optimizing a Bellman self-consistency condition instead of performance itself.
- When to use: placing any new algorithm you read about. Ask which line it is on and which
weakness of its predecessor it claims to fix.
- **The central trade-off the lineup exposes**: on-policy algorithms *directly optimize the
objective you care about* — policy performance — and it works out mathematically that
you need on-policy data to compute the updates, so they cannot reuse old data. Off-policy
algorithms exploit the Bellman optimality equations, which hold for *any* transition data,
so they reuse everything — but satisfying Bellman's equations well carries **no guarantee**
of good policy performance.
- How: choose the family by which risk you can afford. Stability with a sample budget, or
sample efficiency with a tuning budget.
- **The standard two-file code template**: every implementation splits into an *algorithm
file* (experience buffer class, then one function that runs the algorithm) and a *core
file* (utilities, the actor-critic constructors, the MLP actor-critic).
- When to use: reading any Spinning Up algorithm, or structuring your own.
## Key Concepts
- **On-policy**: each update uses only data collected by the most recent version of the policy.
- **Off-policy**: each update can use data collected at any point in training, however the
agent was exploring at the time.
- **MLP actor-critic**: all six use non-recurrent multi-layer-perceptron actor-critics, which
makes them suitable for fully-observed, non-image-based environments (e.g. Gym MuJoCo) and
unsuitable, as shipped, for partial observability or pixels.
- **Sample efficiency**: how much environment interaction is needed to reach a performance level.
- **Deterministic policy gradients**: the theory (2014) that made DDPG possible — much younger
than the policy gradient theory behind VPG, whose core elements go back to the late 80s.
## Reference Tables
| Algorithm | Family | Policy | Action spaces | Parallel (MPI) | PyTorch | TF1 |
|-----------|--------|--------|---------------|----------------|---------|-----|
| VPG | On-policy | Stochastic | Discrete + continuous | Yes | Yes | Yes |
| TRPO | On-policy | Stochastic | Discrete + continuous | Yes | No | Yes |
| PPO | On-policy | Stochastic | Discrete + continuous | Yes | Yes | Yes |
| DDPG | Off-policy | Deterministic | Continuous only | No | Yes | Yes |
| TD3 | Off-policy | Deterministic | Continuous only | No | Yes | Yes |
| SAC | Off-policy | Stochastic | Continuous only (as shipped) | No | Yes | Yes |
## Code Examples
The PyTorch algorithm function, in order — the template every implementation follows:
```
1) Logger setup
2) Random seed setting
3) Environment instantiation
4) Build the actor-critic module via the `actor_critic` function passed in as an argument
5) Instantiate the experience buffer
6) Set up callable loss functions that also return algorithm-specific diagnostics
7) Make PyTorch optimizers
8) Set up model saving through the logger
9) Set up an update function: one epoch of optimization, or one step of descent
10) Main loop: a) run the agent in the environment
b) periodically update parameters per the algorithm's main equations
c) log key performance metrics and save the agent
```
The TF1 version is the same shape with four graph-construction steps inserted (placeholders,
actor-critic graph, loss/diagnostic graph, training ops) and a session step.
## Mental Models
- Read the lineup as **"progressions of ideas from the recent history of the field"**, not as
a menu. VPG predates deep RL entirely; DDPG's theory is from 2014.
- Treat **PPO and SAC as the two defaults** — they are close to state of the art on
reliability and sample efficiency among policy-learning algorithms.
- Think of the `actor_critic` argument as the seam: the algorithm function is fixed, the
network construction is injected. That is also where the ch12 silent bug lives.
## Anti-patterns
- **Reaching for DDPG on a discrete action space.** DDPG, TD3 and the shipped SAC are
continuous-only. The max over actions is why (see ch17).
- **Expecting these to work on Atari or partially-observed tasks as shipped**: MLP,
non-recurrent, non-image.
- **Picking an algorithm by recency**: TD3 and SAC were published roughly concurrently; SAC
is not a successor to TD3, it is a parallel branch that borrowed the clipped double-Q trick.
## Key Takeaways
1. Two families, one trade-off: directly optimize performance (on-policy, stable, sample-hungry)
or exploit Bellman (off-policy, sample-efficient, no performance guarantee).
2. PPO and SAC are the practical end points of each line.
3. Continuous-only for the whole off-policy line, as implemented here.
4. Every implementation is two files and the same ten-step function; learn the template once.
5. TRPO has no PyTorch implementation in Spinning Up.
## Connects To
- **Ch 8**: the full taxonomy this lineup is a slice of.
- **Ch 14-19**: one chapter per algorithm, in lineage order.
- **Ch 12**: the exercises that make the on-policy/off-policy distinction concrete.

View file

@ -0,0 +1,133 @@
# Chapter 4: Running Experiments
## Core Idea
`spinup/run.py` turns every keyword argument of every algorithm into a command-line flag,
and turns a list of values for a flag into a series of experiments — so hyperparameter
sweeps and multi-seed runs are one command, not a script.
## Frameworks Introduced
- **One flag per kwarg**: if `kwarg` is a valid keyword argument of an algorithm function,
`--kwarg` sets it. `python -m spinup.run [algo] --help` prints the docstring readout.
- How: `python -m spinup.run [algo name] [experiment flags]`.
- **Multiple values means multiple experiments**: providing more than one value for an
argument launches one experiment per combination, **in series**. They do not run in
parallel because a single experiment already soaks up enough resources that concurrency
buys no speedup.
- When to use: seed sweeps (the ch10 rigor requirement) and hyperparameter ablations.
- **ExperimentGrid**: the in-script equivalent, based on but simpler than rllab's
VariantGenerator. `spinup.run` uses one under the hood.
- How: `eg.add(param_name, values, shorthand, in_name)` then `eg.run(thunk, **run_kwargs)`.
`in_name` forces a parameter into the experiment name even when it does not vary.
- Difference from the CLI: no shortcut kwargs — you must write `ac_kwargs:hidden_sizes`,
not `hid`.
- **Shorthand-driven save directories**: results land in
`data_dir/[outer_prefix]exp_name[suffix]/[inner_prefix]exp_name[suffix]_s[seed]`.
The suffix encodes only the hyperparameters that *differ across the launched experiments*,
and never the seed — so runs that differ only by seed group into the same folder, which is
exactly what the plotter needs to average over seeds.
## Key Concepts
- **`--env` / `--env_name`**: a Gym environment name, converted internally into the `env_fn`
callable every algorithm actually takes.
- **`--hid` / `--act`**: shortcut flags for `ac_kwargs:hidden_sizes` and `ac_kwargs:activation`,
valid for all current algorithms.
- **`--cpu` / `--num_cpu`**: launch with this many MPI-connected processes; `auto` uses all
available. Raises an error for algorithms that do not support parallelization.
- **`--dt` / `--datestamp`**: put timestamps in the save directory names.
- **User-supplied shorthand**: square brackets after a flag, e.g. `--hid[h]`, control the
directory-name abbreviation. Without one, a shorthand is derived automatically
(`clip_ratio` becomes `cli`).
- **`eval()` passthrough**: flag values pass through `eval()` before use, so you can name
functions and objects directly, e.g. `--act torch.nn.ELU`.
- **Dict kwargs**: `--key:v1 value_1 --key:v2 value_2` instead of `--key dict(v1=..., v2=...)`.
## Code Examples
The quickstart, with every flag doing something distinct:
```bash
python -m spinup.run ppo --exp_name ppo_ant --env Ant-v2 --clip_ratio 0.1 0.2 \
--hid[h] [32,32] [64,32] --act torch.nn.Tanh --seed 0 10 20 --dt \
--data_dir path/to/data
```
Choosing the backend explicitly:
```bash
python -m spinup.run ppo_pytorch --env Walker2d-v2 --exp_name walker
python -m spinup.run ppo_tf1 --env Walker2d-v2 --exp_name walker
# bare `ppo` reads spinup/user_config.py for the default backend
```
From a script:
```python
from spinup import ppo_pytorch as ppo
import gym
env_fn = lambda: gym.make('LunarLander-v2')
ac_kwargs = dict(hidden_sizes=[64, 64])
logger_kwargs = dict(output_dir='path/to/output_dir', exp_name='experiment_name')
ppo(env_fn=env_fn, ac_kwargs=ac_kwargs, steps_per_epoch=5000, epochs=250,
logger_kwargs=logger_kwargs)
```
ExperimentGrid, from `spinup/examples/pytorch/bench_ppo_cartpole.py`:
```python
from spinup.utils.run_utils import ExperimentGrid
from spinup import ppo_pytorch
import torch
eg = ExperimentGrid(name='ppo-pyt-bench')
eg.add('env_name', 'CartPole-v0', '', True)
eg.add('seed', [10*i for i in range(args.num_runs)])
eg.add('epochs', 10)
eg.add('steps_per_epoch', 4000)
eg.add('ac_kwargs:hidden_sizes', [(32,), (64,64)], 'hid')
eg.add('ac_kwargs:activation', [torch.nn.Tanh, torch.nn.ReLU], '')
eg.run(ppo_pytorch, num_cpu=args.cpu)
```
## Worked Example
`python -m spinup.run ddpg_tf1 --env Hopper-v2 --hid[h] [300] [128,128] --act tf.nn.tanh tf.nn.relu`
Two `hid` values times two `act` values is four experiments, run in series, producing four
suffixes:
```
_h128-128_ac-actrelu
_h128-128_ac-acttanh
_h300_ac-actrelu
_h300_ac-acttanh
```
`h` came from the user-supplied `[h]`; `ac-act` was derived automatically from the true flag
name `ac_kwargs:activation`. Add `--seed 0 10 20` and you get twelve runs in four folders —
three seeds grouped per configuration, which is the grouping the plotter averages over.
## Anti-patterns
- **Running the per-algorithm files directly** (`spinup/algos/BACKEND/ALGO/ALGO.py`). The
command-line support there is vestigial, takes a different argument set, and is explicitly
not the recommended way to run experiments.
- **Using ZShell without escaping square brackets**: ZShell treats them as special characters
and Spinning Up uses them for both list values and shorthands.
- **One seed.** RL algorithms have high variance; the flag exists so you use it (ch10 asks
for at least 3, ideally 10 or more).
- **Expecting parallel experiment launches.** Sweeps run in series by design.
## Key Takeaways
1. Every kwarg is a flag; every list of flag values is a sweep.
2. Sweeps run in series; MPI parallelism is per-experiment via `--cpu`, and only for
algorithms that support it.
3. Save-directory suffixes encode only the varying hyperparameters, never the seed — that
grouping is what makes multi-seed plotting work.
4. `ExperimentGrid` is the scripted form and loses only the shortcut kwargs.
5. Values go through `eval()`, so activations and other objects can be named on the command line.
## Connects To
- **Ch 5**: what the directories those flags create actually contain.
- **Ch 6**: the plotter, which consumes this directory structure and its autocompletion.
- **Ch 10**: why multi-seed runs are a rigor requirement, not a convenience.
- **Ch 20**: `ExperimentGrid`, `call_experiment` and `setup_logger_kwargs` in Run Utils.

View file

@ -0,0 +1,97 @@
# Chapter 5: Experiment Outputs
## Core Idea
Every run saves four things — a config record, a TSV of training metrics, the trained
model, and a pickled copy of the environment — and only one of them (`config.json`) is
ever meant to be read by hand.
## Frameworks Introduced
- **Tools, not files**: `test_policy` loads from `pyt_save/` or `tf1_save/`, the plotter
interprets `progress.txt`. Those are the correct interfaces. `config.json` is the only
file you should ever open yourself, and only to remember what you ran.
- When to use: any time you are tempted to parse a save directory manually.
- **Watch, then measure**: `test_policy` renders the agent so you can see behavior that no
scalar metric would have shown you; `-nr` drops rendering when you only want the numbers.
## Key Concepts
- **`progress.txt`**: tab-separated records of every metric the logger recorded, e.g. `Epoch`,
`AverageEpRet`.
- **`config.json`**: as-complete-as-possible dict of the args and kwargs used to launch the run.
Record-keeping only — launching an experiment from a config file is not supported.
- **`vars.pkl`**: algorithm state; currently used only to save a copy of the environment.
- **`pyt_save/model.pt`**: a pickled PyTorch `nn.Module`; loading restores an ActorCritic
object with an `act` method.
- **`tf1_save/`**: `variables/`, `model_info.pkl` (key-to-tensor-name map) and `saved_model.pb`.
Renamed from `simple_save/` on 2020-01-30.
- **`DEFAULT_DATA_DIR`**: set in `spinup/user_config.py`; defaults to `spinningup/data`.
## Reference Tables
| File | Contents |
|------|----------|
| `pyt_save/` | PyTorch only. Everything needed to restore the agent and value functions |
| `tf1_save/` | TF1 only. SavedModel plus the key-to-tensor map |
| `config.json` | The launch args and kwargs. Non-serializable values become strings |
| `progress.txt` | TSV of logged metrics across training |
| `vars.pkl` | Pickled environment copy; may be empty if the env cannot be pickled |
`test_policy` flags:
| Flag | Default | Does |
|------|---------|------|
| `-l L`, `--len=L` | 0 | Max episode length; 0 means no maximum |
| `-n N`, `--episodes=N` | 100 | Number of test episodes |
| `-nr`, `--norender` | off | Print returns and lengths only; much faster |
| `-i I`, `--itr=I` | -1 | Which saved snapshot; -1 is latest (see below) |
| `-d`, `--deterministic` | off | **SAC only.** Use the deterministic mean policy |
## Code Examples
```bash
python -m spinup.run test_policy path/to/output_directory
```
When the environment failed to pickle and `test_policy` raises `AssertionError: Environment
not found!`, rebuild it by hand:
```python
from spinup.utils.test_policy import load_policy_and_env, run_policy
import your_env
_, get_action = load_policy_and_env('/path/to/output_directory')
env = your_env.make()
run_policy(env, get_action)
```
To keep snapshots from many points in training (off by default — algorithms overwrite the
most recent one), change the line present in every algorithm:
```python
logger.save_state({'env': env}, None) # default: one snapshot, overwritten
logger.save_state({'env': env}, epoch) # keep per-epoch snapshots
```
and then set `save_freq` to something reasonable — at the default of 1 you flood the output
directory with one folder per epoch.
## Anti-patterns
- **Forgetting `-d` when evaluating SAC.** SAC trains a stochastic policy but the correct
evaluation policy is the deterministic mean. Without the flag you are measuring the wrong
thing, and the flag is used for no other algorithm.
- **Expecting to resume training.** Spinning Up implementations have no way to resume a
partially-trained agent.
- **Trying to relaunch from `config.json`.** It is a record, not an input.
- **Assuming `vars.pkl` has your environment.** Gym Box2D environments in older Gym versions
are known to fail to pickle, leaving it empty.
## Key Takeaways
1. Four artifacts per run; use the tools for three of them and read only `config.json` by hand.
2. SAC evaluation requires `--deterministic`; every other algorithm ignores it.
3. Multi-snapshot saving is a two-line change plus a `save_freq` you must set deliberately.
4. Environment pickling can silently fail — the recovery path is rebuilding the env in Python.
5. No resume support; a killed run is a lost run.
## Connects To
- **Ch 4**: the flags that create these directories.
- **Ch 6**: `progress.txt` is what the plotter reads.
- **Ch 19**: why SAC's evaluation policy differs from its training policy.
- **Ch 20**: the EpochLogger that writes all of this.

View file

@ -0,0 +1,79 @@
# Chapter 6: Plotting Results
## Core Idea
The plotter reads a directory prefix, autocompletes every matching run beneath it, averages
across seeds by default, and resolves the pseudo-metric `Performance` to the *correct*
performance measure for each algorithm family — so a fair on-policy versus off-policy
comparison is one command.
## Frameworks Introduced
- **`Performance` as a family-aware alias**: `Performance` is not a real output of any
algorithm. The plotter resolves it per logdir to `AverageEpRet` for on-policy algorithms
and `AverageTestEpRet` for off-policy ones.
- When to use: always, unless you specifically want one raw column. It is the default `-y`.
- Why it matters: on-policy performance is the average return of the batch just collected;
off-policy performance is measured by separate deterministic test rollouts. Plotting the
same raw column for both would compare two different quantities.
- **Prefix autocompletion**: logdirs are searched recursively and prefixes expand. Give the
plotter `data/bench_algo` and it finds `bench_algo1` and `bench_algo2` with all their seeds.
- How: name experiments with a shared prefix at launch and comparison becomes free.
- **Average by default, `--count` to disaggregate**: by default, y-values are averaged across
all results sharing an `exp_name` — typically identical experiments differing only in seed.
`--count` shows each curve separately.
## Key Concepts
- **`--xaxis` / `-x`**: which column is the x-axis. Default `TotalEnvInteracts`, i.e. sample
efficiency is the default framing, not wall-clock or epochs.
- **`--value` / `-y`**: which columns to graph; multiple values produce multiple graphs.
- **`--smooth S`**: average over a fixed window of width S. The book's own benchmark plots
use a window of 11 epochs (ch13).
- **`--legend` / `-l`**: overrides the automatic legend, which uses `exp_name` from
`config.json`. One string per *matched* directory, which may exceed the number of logdir
arguments you passed.
- **`--select` / `--exclude`**: keep or drop curves whose logdir contains all of / any of
these substrings. The way to narrow an over-eager autocomplete.
## Code Examples
```bash
python -m spinup.run plot [path/to/output_directory ...] [--legend [LEGEND ...]] \
[--xaxis XAXIS] [--value [VALUE ...]] [--count] [--smooth S] \
[--select [SEL ...]] [--exclude [EXC ...]]
```
Comparing two algorithms across all their seeds, relying on autocompletion:
```
data/
bench_algo1/
bench_algo1-seed0/
bench_algo1-seed10/
bench_algo2/
bench_algo2-seed0/
bench_algo2-seed10/
```
```bash
python spinup/utils/plot.py data/bench_algo
```
## Anti-patterns
- **Passing one legend string per logdir argument.** Autocompletion may match several
directories per argument; you need one legend entry per match, unless you narrowed the
set with `--select` / `--exclude`.
- **Plotting `AverageEpRet` for an off-policy algorithm** and calling it performance — that
is the behavior policy with exploration noise, not the evaluated policy. Use `Performance`.
- **Heavy smoothing to make a result look clean.** Smoothing is a display parameter; it does
not change what the seeds did, and ch10 asks you to show seed variance rather than hide it.
## Key Takeaways
1. `Performance` is the correct default because it is algorithm-family aware.
2. Prefix autocompletion plus shared `exp_name` prefixes is the intended comparison workflow.
3. Seed averaging is on by default; `--count` reveals the individual curves that average hides.
4. The default x-axis is environment interactions — sample efficiency is the default question.
## Connects To
- **Ch 5**: `progress.txt`, the plotter's input.
- **Ch 4**: the suffix rules that group seeds into one folder for averaging.
- **Ch 13**: the benchmark plots, produced with 10 seeds and an 11-epoch smoothing window.

Some files were not shown because too many files have changed in this diff Show more