feat(dml): replicate-weight survey designs via IF-reweighting (per-cell + aggregate) - #807
Conversation
…ll + aggregate) Lift DMLDiD's blanket replicate-weight NotImplementedError. Replicate SurveyDesigns (BRR / Fay / JK1 / JKn / SDR) now compute per-cell AND aggregate variances by IF-reweighting the augmented cross-fitted scores (compute_replicate_if_variance on the Hajek payload), on both lanes. - Per-cell arm leads the SE dispatch chain; degenerate cells (zero or non-finite replicate variance) fail closed to NaN inference (stricter than the shared aggregate clamp; documented asymmetry). - Df: QR-rank - 1 design df with min(df_survey, n_valid - 1) capping per cell and at the overall relay (deliberate documented divergence from CS's replace convention, which is anti-conservative; CS-side flip tracked in the TODO CS-parity row together with the shared ES/group and staggered-DDD replace sites). df_survey None (rank <= 1) -> df=0 sentinel local to safe_inference; survey_metadata keeps None. - Targeted rejections replace the blanket gate: replicate + bootstrap (before any fit work) and replicate + cluster= (after the cluster column checks — CS ordering, bogus names stay ValueError). - Docs: REGISTRY replicate Note (linearized Hajek equation with fixed full-weight denominator, both combined_weights branches; Neyman- orthogonality justification; ridge weight-scale caveat; df and degeneracy conventions) + support matrix insertion (14 of 21); survey-theory roster + dispatch Notes cell; api rst two-lane split; choosing_estimator matrix + narrative; 4 LLM guides + llms-full tally; survey-roadmap row removed; practitioner decision tree; variance- conventions ROWS literals + regenerated table; tutorial 32 markdown; fit()/results docstrings; changelog.d fragment. - Tests: JK1/BRR builders, acceptance (both lanes + combined_weights= False discriminator), per-cell cross-check vs the helper, df spy matrix (tightening reaches cells/overall/metadata; cap-vs-replace discriminator on a rank-deficient design; rank-one -> NaN), learner- parametrized scale invariance (linear/sieve pinned, ridge bounded), degenerate-cell fail-closed (explicit isnan), targeted rejections, aggregations (ES vcov None, total closed, inherited ES replace df pinned), PSU-fold non-interaction.
Overall assessment: ✅ Looks goodExecutive summary
Methodology
Code QualityNo findings. PerformanceNo findings. MaintainabilityNo findings. Tech Debt
SecurityNo findings. Documentation/Tests
The new tests otherwise cover both data lanes, weight interpretation, df handling, degeneracy, aggregation, and rejection paths. They could not be executed in this review environment because |
The RCS tutorial's survey cell said any declared design makes cross-fitting folds PSU-cohesive; replicate designs have no PSU (mutual exclusion) and retain D x T-stratified folds with rank-1 df, as test_replicate_fit_keeps_stratified_folds pins. Markdown-only edit; code-cell hash pins untouched (drift test green). CI review P2.
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall assessment: ✅ Looks goodExecutive summary
Methodology
Code QualityNo findings. Both per-cell paths use PerformanceNo findings. Reweighting retained influence scores avoids per-replicate nuisance refits as documented. MaintainabilityNo findings. The implementation reuses the shared replicate-variance and aggregation machinery. Tech Debt
SecurityNo findings. Documentation/TestsNo findings. The prior PSU-fold wording is now correctly limited to full PSU designs, with replicate designs described as retaining stratified folds ( |
Summary
NotImplementedError: replicateSurveyDesigns (BRR / Fay / JK1 / JKn / SDR) now compute per-cell AND aggregate variances by IF-reweighting the augmented cross-fitted scores (compute_replicate_if_varianceon the same Hájek payload the aggregate_se_from_psiroute consumes), on both lanes (panel + declared repeated cross sections).min(df_survey, n_valid − 1)capping per cell and at the overall relay. The overall MIN-CAP deliberately diverges from CS's replace convention (anti-conservative — it can raise df above the design df); the CS-side flip plus the shared ES/group and staggered-DDD replace sites are tracked in the new TODO CS-parity row, and the inherited ES replace behavior is pinned by a test cross-linking that row.df_survey is None(rank ≤ 1) → df=0 sentinel local tosafe_inference;survey_metadata.df_surveykeepsNone.n_bootstrap > 0(before any fit work) and replicate +cluster=(after the cluster column checks — CS ordering, bogus names stayValueError); message parity with CS.combined_weightsbranches, verified against the implementation to 1e-15; Neyman-orthogonality justification for no per-replicate re-cross-fitting; ridge weight-scale caveat; df + degeneracy conventions) and support-matrix insertion (14 of 21); survey-theory roster + dispatch Notes cell; api rst two-lane variance split; choosing_estimator matrix + narrative; all four wheel-shipped LLM guides + the llms-full tally; survey-roadmap limitation row removed; practitioner decision tree; variance-conventionsROWSreason literals + regenerated CI-pinned table; tutorial 32 markdown (code-cell hash pins untouched); fit()/results-module docstrings;changelog.d/fragment.Methodology references (required if estimator / math changes)
compute_replicate_if_variancemachinery (REGISTRY "Replicate-weight support matrix")Validation
tests/test_survey_dml.py(new §10 replicate suite: acceptance both lanes + BRR +combined_weights=Falsediscriminator, per-cell SE cross-check against the helper, learner-parametrized scale invariance with ridge bounded, df spy matrix incl. cap-vs-replace discriminator and rank-one NaN, degenerate-cell fail-closed with explicitisnan, targeted rejections, aggregations, PSU-fold non-interaction; blanket fail-closed pins replaced),tests/test_variance_conventions.py(ROWSreason literals). Full battery green on Rust and pure-Python backends (test_survey_dml,test_dml_did,test_survey_phase6,test_methodology_dml_did,test_variance_conventions,test_t32_dml_did_drift,test_guides,test_changelog_fragments).compute_replicate_if_variancecalls exactly (rtol 1e-12); the REGISTRY equation verified against the implementation to 1e-15; scale-invariance probe at ×100 (linear/sieve ≤4e-16 drift, ridge 1.5e-5..2.5e-4 documented).Security / privacy
Changelog
changelog.d/20260830-dml-replicate-weights.md)