You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Enhanced CPS, when its income_tax_positive is summed and compared against the CBO target it is meant to calibrate to (calibration.gov.cbo.income_tax), overshoots by ~1.86× in every year tested:
The HF file was uploaded 2026-05-20 (Promote 493 files from staging to production for candidate 1.115.4-patch), so this isn't stale-data — the latest production build misses by the same margin.
Root cause
From reading policyengine_us_data/datasets/cps/enhanced_cps.py and policyengine_us_data/utils/loss.py:
The reweight() function in enhanced_cps.py minimises:
Every national target gets the same 1 / N_national weight. With roughly 500 national targets in the loss matrix (mostly IRS SOI by AGI band × filing status × variable, plus the handful of CBO aggregates from CBO_PROGRAMS, plus EITC by child count, plus Census age populations), the single CBO income_tax_positive target gets ~0.2% of the national loss weight. A 1.86× miss contributes (0.86)² / 500 ≈ 0.0015 to total loss — well below what Adam at lr=0.2 will keep pushing on.
So the optimizer converges to a local minimum where most of the small SOI cells fit reasonably well, and the big aggregate sits 86% off. Moving weights to fit the aggregate would push many small-cell targets out of fit, which is a net loss increase under the current uniform target weighting.
What's not the problem
The CBO target value is correct — matches CBO's published projection for federal individual income tax receipts.
The simulator-side variable is correct since Address PR #505 review feedback #519's Use income_tax_positive for CBO calibration in loss.py (2026-02-02).
The HF dataset isn't stale (uploaded 2026-05-20 from 1.115.4-patch).
cps_2024 (no reweight) undershoots by ~22%, consistent with CPS top-coding very high incomes. That's the data-limit floor; the reweight is supposed to lift it but instead overshoots by ~86%.
Suggested fixes (any of which should help; first is cheapest)
Importance weights per target. Scale each target's loss contribution by something like log10(target_magnitude) or sqrt(target_magnitude) so large aggregates aren't drowned out. Uniform weighting currently treats a $2.75T aggregate and a $1M SOI bucket as equally important.
Two-stage fit. Optimize first against only the CBO aggregate targets (income_tax_positive, snap, social_security, ssi, unemployment_compensation), then add the SOI cells with the aggregate-fit weights as a warm start.
Hard aggregate-consistency constraint. Add sum_over_AGI_bands(income_tax) == CBO_total as an equality (Lagrangian) rather than letting it compete with bucket targets.
A quick check on whether the other CBO aggregates (snap, social_security, ssi, unemployment_compensation) are also missing would help decide between (1) — a structural under-weighting that hits all aggregates — and (3) — possibly an income-tax-specific interaction with the cap-gains/dividends per-AGI-bracket targets added recently (#868).
Discovered while building https://github.com/PolicyEngine/bottom-50-tax-analysis. That repo currently defaults to cps_2024 because of this regression; happy to switch back to enhanced_cps_2024 once the calibration is fixed.
The Enhanced CPS, when its
income_tax_positiveis summed and compared against the CBO target it is meant to calibrate to (calibration.gov.cbo.income_tax), overshoots by ~1.86× in every year tested:enhanced_cps_2024cps_2024(no PUF clone / reweight)Repro
The HF file was uploaded 2026-05-20 (
Promote 493 files from staging to production for candidate 1.115.4-patch), so this isn't stale-data — the latest production build misses by the same margin.Root cause
From reading
policyengine_us_data/datasets/cps/enhanced_cps.pyandpolicyengine_us_data/utils/loss.py:The
reweight()function inenhanced_cps.pyminimises:Every national target gets the same
1 / N_nationalweight. With roughly 500 national targets in the loss matrix (mostly IRS SOI by AGI band × filing status × variable, plus the handful of CBO aggregates fromCBO_PROGRAMS, plus EITC by child count, plus Census age populations), the single CBOincome_tax_positivetarget gets ~0.2% of the national loss weight. A 1.86× miss contributes(0.86)² / 500 ≈ 0.0015to total loss — well below what Adam atlr=0.2will keep pushing on.So the optimizer converges to a local minimum where most of the small SOI cells fit reasonably well, and the big aggregate sits 86% off. Moving weights to fit the aggregate would push many small-cell targets out of fit, which is a net loss increase under the current uniform target weighting.
What's not the problem
income_tax_positivefor CBO calibration in loss.py (2026-02-02).1.115.4-patch).cps_2024(no reweight) undershoots by ~22%, consistent with CPS top-coding very high incomes. That's the data-limit floor; the reweight is supposed to lift it but instead overshoots by ~86%.Suggested fixes (any of which should help; first is cheapest)
log10(target_magnitude)orsqrt(target_magnitude)so large aggregates aren't drowned out. Uniform weighting currently treats a $2.75T aggregate and a $1M SOI bucket as equally important.income_tax_positive,snap,social_security,ssi,unemployment_compensation), then add the SOI cells with the aggregate-fit weights as a warm start.sum_over_AGI_bands(income_tax) == CBO_totalas an equality (Lagrangian) rather than letting it compete with bucket targets.A quick check on whether the other CBO aggregates (
snap,social_security,ssi,unemployment_compensation) are also missing would help decide between (1) — a structural under-weighting that hits all aggregates — and (3) — possibly an income-tax-specific interaction with the cap-gains/dividends per-AGI-bracket targets added recently (#868).Discovered while building https://github.com/PolicyEngine/bottom-50-tax-analysis. That repo currently defaults to
cps_2024because of this regression; happy to switch back toenhanced_cps_2024once the calibration is fixed.