A compact time-series model built on a 32M-parameter ModernBERT backbone
(33.4M parameters in total with the time-series input/output heads). One call
returns three things:
📈 Quantile forecast
Probabilistic forecasts at any requested quantile levels
🧭 Variable / time impact
Normalized contribution of every input variable at every time step
📌 Anchor forecast
Forecasts conditioned on known future points you specify
Installation
pip install time-anchor
predict_time_anchor accepts a Hugging Face Hub model id or a local checkpoint directory.
Source code for the package lives at
K-Iwa/time-anchor.
Quantile Forecast
Quantile forecast
Hourly temperature in Tokyo (Open-Meteo archive), 64-hour holdout: median MAE 0.57 °C,
with every actual value inside the q10–q90 band.
Per-hour contribution of each weather variable over a one-week Tokyo context.
For each time_index, impact across all variables sums to 1.
python
1result = predict_time_anchor(2"K-Iwa/time-anchor-modernbert-32m",3 target_context=temperature[:168],4 explanatory_contexts=[weather.iloc[:168, i].astype("float32")for i in(2,3,4)],5 gaf={"enabled":True,"topk_time_steps":0},6)7print(pd.DataFrame(result.variable_impact_rows))
Impact Validation
The impact scores were checked against synthetic data where the correct answer
is known in advance.
Test 1 — do the shares match known mixing weights? The target is built as a
weighted sum of three sine waves, and the same three waves are passed in as the
explanatory series:
target(t) = w1*f1(t) + w2*f2(t) + w3*f3(t)
A wave with twice the weight contributes twice as much to the target, so its
measured impact share should be about twice as large. That is what comes out:
True weights w1 / w2 / w3
Measured impact shares f1 / f2 / f3
0.60 / 0.30 / 0.10
0.55 / 0.33 / 0.12
0.10 / 0.30 / 0.60
0.26 / 0.30 / 0.44
0.33 / 0.33 / 0.33
0.33 / 0.29 / 0.39
The first two rows use the same three waves with the weights swapped, and the
measured shares swap with them — the score reflects how much each series
contributes, not which series it happens to be.
Test 2 — does the per-time-step impact follow changes over time? Here the
target switches drivers mid-context: wave A alone drives the first half, wave B
alone drives the second half. Each wave's per-time impact share is higher in
the half it drives, and swapping A and B mirrors the result. One reading note:
B's overall share is larger, and that is expected — impact explains the
forecast, and the forecast continues from the end of the context, where B is
the active driver.
Anchor Forecast
Forecast with user-specified anchors
Monthly airline passengers (Box & Jenkins), 24-month holdout: pinning six known
months cuts the median forecast MAE from 46 to 10 thousand passengers.
Writes output/forecast.csv, output/variable_impact.csv, and output/result.json.
Add --no-impact for forecast-only runs, or --anchor-mode observed --anchor-positions 12,24 --anchor-values 0.2,0.4 for anchor forecasts.