Restore the classical-fit notebook, ported to the 0.4 syntax - #45
Merged
Conversation
notebooks/classical_fit_tram_dag.py was deleted with notebooks/stale/ in 2a7327d. Its ordinal half went to experiments/misc/validate_ls.py and its warm-start lesson to docs/fitting.md, but nothing else walks fit_classical through end to end, so it comes back rather than staying scattered. The port drops the tramdag.simulations import (the VACA triangle is written inline, as the other notebooks do), reads the stroke cohort from its new home under experiments/misc/data/, uses positional terms and CausalFlowDAG(seed=), and replaces a hand-rolled one-hot design with flow.design_matrix(drop_first=) -- which did not exist when the notebook was written. Two sections are new: - Section 0 opens on plain logistic regression, because a two-level OrdinalNode with LS terms *is* one: logit P(Y=1) = -theta_0 + w_0 + sum_p w_p x_p. It runs on MASS::birthwt so the reader can re-fit it in R, and agrees with statsmodels.Logit and R glm to ~1e-8 on every coefficient, on the log-likelihood, and on the fitted probabilities to 9e-8. It makes two conventions concrete on the simplest possible model: an ordinal node subtracts its shift, and an ordinal parent's one-hot level-0 column is part of the intercept, so R's (Intercept) is -theta_0 + w_0. - Section 1 reproduces the continuous fit outside the flow, in R (tram::Colr, shown with its real output) and in Python. statsmodels has no continuous transformation model, but it does not need one: such a model is the limit of an ordered logit, so binning the outcome into K quantile bins and fitting OrderedModel converges to the flow's shift coefficients. Both are labelled consistency checks, not identities -- they compare two sieve approximations of h and agree to ~0.1%, not to 1e-8. The cell also shows the sign flip that Sections 0 and 2 do not need: a continuous node adds its shift. notebooks/data/ is new, with a README recording provenance. birthwt.csv is four columns exported verbatim from MASS and is an input. vaca.csv is an output the notebook rewrites each run, tracked so the R snippet reads the identical rows the flow was fitted on, and so a changed n or seed shows up as a diff that flags the pinned Colr coefficients as stale. The notebook joins the docs workflow's NOTEBOOKS list and the pdoc nav, per the rule in notebooks/README.md that a notebook not executed by CI does not belong in that directory. statsmodels joins the notebooks dependency group, since that job runs --group notebooks --group docs. codespell learns "lik", which R prints in "'log Lik.'". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pqkmo7dKBep1cvkHUfEH6i
Both CHANGELOG sides are 0.4.0 Added bullets — kept both; .gitignore keeps scratch/, .DS_Store and site/. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three cells still used the pre-0.4 arguments: fit_classical(verbose=), fit(schedule="plateau", plateau_patience=, freeze_patience=, verbose=) — now callbacks.PerNodePlateau over per_node_adam — and fit(restore_best=False), which is the default behavior. Executed end to end under the merged 0.4 API. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Restores
notebooks/classical_fit_tram_dag.py, deleted withnotebooks/stale/in 2a7327d, ported to the 0.4 term syntax and extended.Merge note
This change needs the 0.4 API and the new data paths. It uses
SIandflow.design_matrix, and it readsexperiments/misc/data/. None of these exist onmain. Therefore do not merge it intomainon its own. It goes intomainwithdev-marcel.What it contains
Four worked examples, each checked against classical software:
MASS::birthwtstatsmodels.Logit, Rglmbwttram::ColrColr, binnedOrderedModellsstroke DAGstatsmodels.OrderedModelSection 0 makes the point that a two-level
OrdinalNodewithLSterms is logistic regression. Section 1 addsbwttobirthwt.csvand shows the proportional-odds property directly: thesmokelog-odds ratio is +0.664 from the flow, +0.669 fromColrand +0.671 from the dichotomizedglm.Sections 1 and 2 also prototype standard errors from the observed Fisher information. The information matrix is singular in both, so the helper uses a pseudo-inverse and reports how far each contrast leaks into the flat subspace. This is deliberately a notebook prototype and not API: a
flow.conf_intwith one row per parameter would be mostly nonsense, because 13 of 24 rows onbwthave no curvature behind them.Section 2 corrects a claim the old notebook made. The treatment effect
Tis not weakly identified: it sits 6.6 standard errors from zero. The weak coefficient ismRS_prelevel 5, carried by 7 of 1275 rows, which is whatexperiments/misc/validate_ls.pyalready recorded in its docstring.Two things reviewers should look at
--mathin the docs build.pdocrenders formulae only with--math, which defaults to false, so every$...$in the notebooks and guides has been publishing as literal LaTeX -- around 110 of them before this branch. The one-word fix in.github/workflows/docs.yamlchanges how existing pages render, not only the new one. This is intended.statsmodelsjoins thenotebooksdependency group. The docs job runs--group notebooks --group docs, and the new notebook needs it.R companion
notebooks/classical_fit_tram_dag.Rfits every classical reference the notebook pins, so the numbers can be re-checked instead of trusted. It needstram, which CI does not install, so it is run by hand.birthwtships with MASS, so Sections 0 and 1 read no file at all.Verification
tests/test_flow.pypasses; no test readsnotebooks/🤖 Generated with Claude Code
https://claude.ai/code/session_01Pqkmo7dKBep1cvkHUfEH6i