Files
foxhunt/crates
jgrusewski 85ce295773 feat(ml-alpha): per-horizon BCE weighting (fixes label-correlation inflation)
For seq_len K and horizon h with h ≫ K, the K position-supervised
labels in a single sequence are near-identical (sequential positions'
forward windows overlap by ~(h-1)/h). Per-position BCE therefore
treats ~K highly-correlated labels as independent samples, inflating
gradient pressure on long horizons by a factor of K.

Concretely at K=96:
  h=30   → ~3 effective samples per seq (forward windows overlap ~97%)
  h=100  → ~1                          (~99%)
  h=6000 → ~1                          (~99.98%)

Per-position supervision was paying 96× the natural signal density on
h=6000, pulling the model toward fitting noise at long horizons.

Fix: the fused BCE kernel now accepts an optional
`loss_weights[N_HORIZONS]` (nullptr → uniform = no-op). Each (k, h)
loss + grad contribution is multiplied by w_h; the normaliser is the
sum of weighted valid entries instead of the raw valid count.

`auto_horizon_weights(K, horizons)` computes `w_h = min(1.0, K/h)` so
short horizons stay at full weight and long horizons collapse to
their independent-sample density. Exposed via CLI:
  --auto-horizon-weights              # K/h auto-derived
  --horizon-weights "1,1,0.5,0.1,0.02" # explicit floats

Default behaviour is uniform (1.0) — apples-to-apples with the
in-flight qf5mj baseline. Synthetic overfit still 0.6268 → 0.1144 in
250 steps (82% drop). 77 tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 10:17:38 +02:00
..