Conversation
…one quantiles Three correctness bugs in _QRFModel.predict are fixed together because they interact in the stochastic-imputation code path: 1. Seed reset on every predict() (#1). np.random.default_rng(self.seed) was called inside predict(), so repeated predict() calls on the same X returned identical draws and collapsed multiple-imputation variance to zero. The RNG is now created once in __init__ and consumed progressively across calls. 2. Quantile-grid bias (#2). The grid [0.091..0.909] combined with .astype(int) (which floors) biased stochastic "median" predictions low and truncated the tails. Stochastic draws are now rounded (not floored) onto a fine symmetric grid so the empirical mean of selected quantiles matches the intended mean_quantile. 3. Per-row random quantile for explicit multi-quantile predict (#3). When users passed quantiles=[0.1, 0.5, 0.9] for prediction intervals, each quantile request sampled a separate random per-row index, producing crossed quantiles. QRFResults._predict now routes explicit quantiles through a deterministic exact_quantile path that guarantees row-level monotonicity. Adds regression tests: - test_qrf_repeated_predict_calls_produce_different_draws - test_qrf_stochastic_median_is_unbiased - test_qrf_multi_quantile_per_row_monotonicity
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
MaxGhenis
commented
Apr 17, 2026
Contributor
Author
MaxGhenis
left a comment
There was a problem hiding this comment.
QRF stochastic fixes verified end-to-end:
- Persistent RNG:
self._rnginitialised in_QRFModel.__init__(qrf.py:150), advanced viaself._rng.beta(...)in predict.test_qrf_repeated_predict_calls_produce_different_drawsasserts two predict calls on same X produce different draws. - Unbiased median:
np.rintonto fine symmetric grid (size = max(count_samples, 101)), eps = 1/(grid+1). With mean_quantile=0.5 → Beta(1,1) uniform → rounded index centred on 0.5.test_qrf_stochastic_median_is_unbiasedaverages 60 stochastic draws against the exact-quantile median and asserts the gap < 0.25·std(y). - Monotone per-row quantiles:
QRFResults._predictroutes explicitquantiles=[...]throughexact_quantile=qwhich callsself.qrf.predict(X, quantiles=[q])directly (no beta sampling).test_qrf_multi_quantile_per_row_monotonicityasserts row-levelq_low <= q_mid <= q_high.
CI all green (lint + 3.12/3.14 tests + changelog). Mergeable. LGTM.
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.
Summary
Fixes three correctness bugs in
_QRFModel.predictthat interact in the stochastic-imputation code path (findings #1, #2, #3 from the bug hunt):predict().np.random.default_rng(self.seed)was called insidepredict(), so repeated calls on the same X returned identical draws and multiple-imputation variance collapsed to zero. The RNG is now created once in__init__and consumed progressively across calls.[0.091..0.909]plus.astype(int)(which floors, not rounds) biased stochastic "median" predictions low and truncated the tails. Stochastic draws are now rounded onto a fine symmetric grid so the empirical mean of selected quantiles matches the intendedmean_quantile.quantiles=[0.1, 0.5, 0.9], each quantile request drew its own random per-row index, producing crossed quantiles.QRFResults._predictnow routes explicit quantiles through a deterministicexact_quantilepath that guarantees row-level monotonicity.Test plan
test_qrf_repeated_predict_calls_produce_different_draws— two sequentialpredict()calls return different drawstest_qrf_stochastic_median_is_unbiased— mean of many stochastic median calls ≈ deterministic mediantest_qrf_multi_quantile_per_row_monotonicity— per-rowq=0.1 <= q=0.5 <= q=0.9with explicit quantilestest_qrf_beta_distribution_samplingstill passestests/test_models/test_qrf.pysuite (30/30) passestests/test_smoke_qrf.pypasses