Homogenization

A forecast can have the right centre and the wrong width. Homogenization is an online correction for the width, learned from the forecaster's own track record rather than from the data directly. It is worth about 3.3% of pinball loss at the horizon where it helps most, and it never made things worse in any cell measured.

The motivation: a forecaster that grades itself

If a predictive distribution is correct, then pushing each realized value through its own forecast CDF gives a uniform number, and through the normal quantile gives a standard normal one. That transformed residual is what skaters calls the parade z, and it is available online, for free, at every horizon.

So the forecaster can grade itself. If those z values have variance below one, the intervals were too wide; above one, too narrow. Either way the miscalibration is visible without any held-out data, because the grade only uses forecasts that have already matured.

Two kinds of structure are commonly left over. The first is a predictable shift in conditional variance: quiet stretches and violent ones, which a single fixed scale cannot serve. The second is unresolved heterogeneity: excess kurtosis that no single time-varying variance explains, because the residual is really drawn from several latent regimes at once. A Hermite expansion names both precisely, as the H₂ and H₄ terms, but the correction it suggests is not usable: it can go negative in the tails, so it is not a density at all.

The mechanism: a two-point scale mixture, hedged

The correction used instead is the simplest object with both effects built in and no way to go negative, a two-point Gaussian scale mixture:

g(z) = ½ N(0, v(1−δ)) + ½ N(0, v(1+δ))

Here v carries the variance level and δ splits one variance into two nearby ones, which is exactly how excess kurtosis arises from purely Gaussian pieces. It is a genuine density for any v > 0. The name comes from that split: an unresolved mixture of latent regimes is replaced by an effective aggregate description, without ever committing to which regime is active now.

A small fixed grid of candidates is run in parallel, each with its own filter on the residual stream, and combined by discounted Bayesian weight. One candidate is the identity, frozen at v = 1 and holding most of the prior weight, which is what makes the whole thing safe: on a well-specified forecaster the identity wins and the correction does nothing.

Results by horizon

One candidate pool per horizon, each resolved against its own matured forecast. FRED economic change-series, 792 paired series per horizon, one-step through twelve-step. Ratio below 1 means homogenization wins; the coverage target is 0.800, and implied sd of 1.000 would be perfect whitening.

hnpinball ratiowinscoverage raw coverage correctedimplied residual sd
17920.990961.4%0.8540.8410.882 → 0.909
27910.993856.8%0.8490.8340.893 → 0.926
37910.991058.2%0.8580.8560.874 → 0.877
47900.972363.4%0.8710.8290.844 → 0.937
57920.966664.4%0.9200.8690.732 → 0.849
67900.967664.7%0.9020.8590.773 → 0.871
77920.971163.4%0.8480.7940.896 → 1.014
87900.976462.7%0.8940.8490.793 → 0.893
97920.979062.6%0.8680.8230.852 → 0.950
107900.976062.9%0.9000.8630.779 → 0.863
117920.980960.9%0.8390.7940.915 → 1.014
127860.967265.8%0.8560.8020.877 → 0.994

Two things stand out. The gain grows with horizon: about 0.9% at one step, rising to 3.3% at h=5. And the defect being corrected is real and largest in the middle of the range, where raw laplace's implied residual sd falls to 0.732 at h=5 — intervals roughly 37% too wide. Coverage moves toward nominal at every horizon.

One step, held-out corpus

Independently on GIFT-Eval, at one step, across 21 datasets and 3,299 paired series: median ratio 0.9950, winning 57.7% of series (56.0% weighting every dataset equally), and positive on 15 of 21 datasets. So the effect is not confined to the corpus it was developed on.

Using it

from skaters import laplace
from skaters.homogenize import homogenize

f = homogenize(laplace(k=12), k=12)     # one pool per horizon
state = None
for y in stream:
    dists, state = f(y, state)          # dists[h-1] is the corrected h-step predictive

It is deliberately opt-in rather than part of laplace's default output. It costs roughly 10% more compute per step, and keeping raw laplace as a stable baseline is what makes measuring the correction possible at all.

What did not work

Caveats

Reproducing this

PYTHONPATH=src:benchmarks python benchmarks/homogenization_page.py

Measured with skaters 0.16.0+ff9740f, written 2026-08-14. Every figure on this page is generated from the results store, not transcribed.