Recency sample weighting for regime drift. When the data-generating rule changes over time, old rows can actively hurt the model that will be scored on current rows. driftweight selects a transparent recency curve using only the early training block, then validates the chosen weights on a held-out tail against a magnitude-matched permutation null. numpy-only.
from driftweight import held_out
from driftweight.synth import make_regime_drift
X, y, _ = make_regime_drift()
r = held_out(X, y)
print(r["best_mode"], r["uniform"], r["learned"], r["beats_null"])$ driftweight demo
## 1. Regime drift (old rule first, current rule later)
best recency mode : steep
held-out transfer : 0.9847 (uniform 0.9510, lift +0.0337)
null p95 / p : 0.9422 / 0.000
VERDICT : REAL - beats held-out null
## 2. Stationary control (no drift - must NOT beat null)
best recency mode : linear
held-out transfer : 0.9689 (uniform 0.9692, lift -0.0003)
null p95 / p : 0.9694 / 0.830
VERDICT : no gain over null
held_out splits rows by order into LOW and HIGH. On LOW only, it tries a small
menu of recency curves (uniform, linear, exp, tail, steep) and selects
the one that best predicts the late part of LOW from the earlier part. It then
refits on all LOW rows with that curve and scores the untouched HIGH rows.
The null uses the same selected weights, permuted across LOW rows. A win means placing high weights on the recent rows mattered; merely having nonuniform weights was not enough.
MIT. Depends only on numpy.