This repository was archived by the owner on Nov 8, 2026. It is now read-only.
Repository navigation
Add Microcosm's regime-gated QRF to the MOOP imputation experiment - #223
Merged
Merged
Conversation
Fit Microcosm's RegimeGatedQRF (microcosm-fit at PolicyEngine/microcosm 7080ba8), the model that imputes PolicyEngine's microdata, on the same five household-grouped folds: once with the ASEC SPM unit weights, as Microcosm weights its fits by default, and once without weights, like the other methods. The note and tables report both fits beside microimpute's QRF and ZI-QRF. run.py records the commit each Microcosm package came from, hashes Microcosm's source into the cache key and caps Microcosm's threads at --n-jobs. Microcosm installs from git and needs Python 3.13, so the experiment imports it only inside the Microcosm method and its tests skip without it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
- README: describe microimpute's draw grid as its code works (it rounds each quantile q to k/100 and reads the forest's (k + 1)/102 quantile), and limit Microcosm's full leaf retention to targets with more than 32 distinct values; it caps leaves at 4,096 samples for 2 to 32. - methods.py: Microcosm's fit asks for design weights by default; a DataFrame fit must name its weights or pass NO_WEIGHTS. - run.py: installed_source reads the version through metadata.get and raises when the metadata names none. - tests: spy on the gate's fit to check each donor's weight in donor order, and add a versionless-metadata case. - results.json: a full rerun under cache tag 541e509d20712573 changed only the two source hashes, the tag and six timings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- README: Microcosm caps a forest's leaves at 4,096 samples only when the donors that forest trains on hold 2 to 32 distinct values. MOOP's forest trains on the donor spenders, whose amounts take 7,830 to 7,880 distinct values in each fold. - methods.py: a caller fitting a DataFrame must pass a weight column's name, a weight vector or NO_WEIGHTS. - run.py: environment() raises when a Microcosm package imports without distribution metadata, and a new test covers that without Microcosm. - tests: the gate spy checks each fit's features and labels against the donors' rows as well as the weights, and the module docstring's skip note moves out of the bullet list. - Reword participial passives in the README, the note template, the changelog fragment and the docstrings. - A full rerun refit every fold under cache tag 6ca09058c0101fce. In results.json only the two source hashes, the tag and six timings changed; TABLE.md renders unchanged, and NOTE.md changes only in the reworded template phrase. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The note template now says "a forest Microcosm grows on donor spenders", since "it" could mean the gate's classifier. NOTE.md re-renders with that one phrase changed. - The README now says Microcosm counts a forest's distinct donor values before any weighted resample, as _fit_forest does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The README now says the donors hold 2 to 32 distinct values before any weighted resample. In a weighted fit, Microcosm's _fit_forest draws the resample first and then counts the values of the rows it receives, so "counts before" gave the wrong order. - The property test now checks that each weighted draw equals zero or lies between the smallest and largest spender that keeps its weight, and that n_jobs=2 leaves the weighted draws unchanged, as the test module's docstring says. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch was successfully deployed
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Why
Microcosm builds the microdata that PolicyEngine's app loads by default in both countries, and its
microcosm-fitpackage imputes withRegimeGatedQRF. The app still offers the enhanced FRS for the UK, and policyengine-uk-data imputes several of that dataset's variables with microimpute's QRF. The MOOP experiment from #222 measured microimpute's QRF and ZI-QRF, so its forest results describe a model that no longer imputes PolicyEngine's default microdata. This PR adds the model that does.What changes
methods.pyaddsmicrocosm_qrf, which fitsRegimeGatedQRFon the same five folds of whole households, with the same predictors, draws and seed as the other methods. It also addsmicrocosm_threads, which caps Microcosm's fit and predict threads, and its gate's OpenMP threads, at--n-jobs.microcosm_qrfpasses each donor SPM unit's weight (SPM_WEIGHT / 100), since Microcosm weights its fits by default.microcosm_qrf_unweightedpassesNO_WEIGHTS, so it fits without weights, like every other method here.run.pyrecords the commit each Microcosm package came from (its PEP 610direct_url.json), hashes Microcosm'sfit,frameandgraphsources into the cache key, and stops with a message when Microcosm is missing, unless--skip-forests. It raises when a Microcosm distribution's metadata names no version, and when a Microcosm package imports without distribution metadata.render.py,NOTE.template.mdandREADME.mdreport both fits beside microimpute's, andrender.pyguards the note's claims (below).results/results.json,NOTE.mdandTABLE.md(cache tag6ca09058c0101fce), with microcosm-graph, microcosm-frame and microcosm-fit 0.1.0 at PolicyEngine/microcosm@7080ba8 on Python 3.13.13.Results
On the 2026 CPS ASEC, the SPM rate with reported MOOP comes to 13.11%, and subtracting MOOP raises it by 2.25 points.
Invariants and tests
With Microcosm in the environment,
tests/test_moop_spm_experiment.pypasses all 19 tests.n_jobs=1andn_jobs=2give identical draws.HistGradientBoostingClassifier.fitchecks that Microcosm fits the gate on each donor's predictors and on whether that donor spends, row by row in donor order. It also checks that the weighted fit hands the gate each donor's weight (up to one scale factor), and that the unweighted fit hands it none. Shuffling the rows, reversing the labels, or permuting or dropping the weights fails it.microcosm_threadssets the widths that Microcosm's own_fit_n_jobsand_predict_workersread, and restores the environment afterwards.installed_sourceraises when a distribution's metadata names no version, andinstalled_package_sha256raises when a package exists but fails to import.environment()recordsNonefor a Microcosm package only when the package neither imports nor has distribution metadata, and raises when it imports without metadata.render.pyrefuses to write the note if any QRF fit moves the national rate by 0.1 point or more, if any forest's total reaches the reported total, or if cell means, donor draws, PMM or Microcosm's weighted fit fail to raise poverty in the 1.0 to 1.25 band.Reproducibility
methods.pyandrun.py, two of the files the cache key hashes, so a full run after each round refit every fold. Each time, of the 1,613 fields inresults.json, only the two source hashes, the tag and six timings changed, andTABLE.mdrendered unchanged. No run logged Microcosm's near-discrete leaf cap.NOTE.mdand leftresults.jsonandTABLE.mdas they were.results.json,NOTE.mdandTABLE.mdstay as they were.Changes after review
First review
An independent Codex review of
1eea236asked for changes: two blocking README errors, three should-fixes and one false sentence in this description. Commite8030a5answered each one.e8030a5limited that to targets with more than 32 distinct values, a rule the second review found still counted the wrong values (below).microcosm_qrfdocstring now says Microcosm'sfitasks for design weights by default and raises when a frame carries another kind.installed_sourcenow reads the version throughmetadata.get("Version")and raises when the metadata names none; a new test case builds such a distribution.fitand checks the weights in donor order.Second review
An independent Claude Opus review of
e8030a5verified five of those six answers and found one blocking error, one should-fix and four nits. Commit959ab7danswers each one.microcosm_qrfdocstring now says a caller fitting a DataFrame must pass a weight column's name, a weight vector orNO_WEIGHTS;microcosm_qrfpasses a vector.installed_sourcereturnsNonefor a package that imports without distribution metadata, soenvironment()now raises in that case for Microcosm's packages. A new test covers it and runs without Microcosm.Third review
An independent Claude Opus review of
959ab7dapproved and raised two nits. Commit1f9fd7fanswers both.Fourth review
An independent Claude Opus review of
1f9fd7ffound two false sentences and one overbroad sentence in this description, and three nits. Commit1e75f7eand this description answer each one.run.pyraises on a versionless distribution only for Microcosm's three packages, so therun.pybullet now says "a Microcosm distribution"._fit_forestdraws its resample first and then counts the distinct values of the rows Microcosm handed it, so the README's "which it counts before any weighted resample" gave the wrong order. It now says the donors hold 2 to 32 distinct values before any weighted resample.n_jobs=2leaves the weighted draws unchanged. A mutant that ignores the weights fails it.CI
CI's Python 3.14 job installs
.[dev,matching]and runs every test (make test); its 3.12 job installs.[dev]and runs onlytests/test_smoke_qrf.pyandtests/test_basic.py. Neither installs Microcosm, which needs Python 3.13 or later and installs from git. The experiment imports Microcosm only inside its method and its run checks, so on 3.14 this test file passes 16 tests and skips the three Microcosm tests.Merging releases a patch version (
changelog.d/moop-spm-microcosm-qrf.changed.md).🤖 Generated with Claude Code