Forecasting API¶
Forecasters learn one series with learn_one(y) and forecast it with
forecast_one(). Regressors learn a target from covariates with
learn_one(x, y) and predict it with predict_one(x). Both issue a
Forecast.
SeasonalNaive ¶
SeasonalNaive(season_length: int = 1, *, horizon: int = 1, residual_alpha: float = 0.05, min_scale: float = 1e-06)
Bases: BaseForecaster
Forecast each lead with the value one cycle earlier.
Lead h repeats the value at the same position of the last observed
cycle. With season_length=1 this is the naive forecast: every lead
repeats the last value. It is the usual baseline a forecaster must beat.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
season_length
|
int
|
Observations per cycle; 1 for the naive forecast. |
1
|
horizon
|
int
|
Largest lead to forecast. |
1
|
residual_alpha
|
float
|
Weight of each new absolute error in the faded mean absolute error kept for every lead, in (0, 1]. |
0.05
|
min_scale
|
float
|
Positive floor for the reported spread, in target units. |
1e-06
|
Notes
Two cycles warm the forecaster up. The spread of every lead starts at the mean absolute seasonal-naive error within the second cycle, then each lead fades towards its own errors. State is O(season_length + horizon^2) and each event after warm-up costs O(horizon).
Examples:
from aberrant.forecast import SeasonalNaive
model = SeasonalNaive(season_length=3, horizon=2)
for y in [1.0, 5.0, 3.0, 1.5, 5.5, 3.5]:
model.learn_one(y)
model.forecast_one().mean # (1.5, 5.5)
HoltWinters ¶
HoltWinters(season_length: int, *, horizon: int = 1, alpha: float = 0.2, beta: float = 0.05, gamma: float = 0.1, residual_alpha: float = 0.05, min_scale: float = 1e-06)
Bases: BaseForecaster
Forecast level, trend and one season with additive Holt-Winters.
Lead h forecasts level + h * trend + season at the matching seasonal
position. Every learned value advances one seasonal position.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
season_length
|
int
|
Known number of observations in a cycle, at least two. |
required |
horizon
|
int
|
Largest lead to forecast. |
1
|
alpha
|
float
|
Level smoothing weight in [0, 1]. |
0.2
|
beta
|
float
|
Trend smoothing weight in [0, 1] (the usual beta-star parameter). |
0.05
|
gamma
|
float
|
Seasonal smoothing weight in [0, 1-alpha], using prior level and trend in the seasonal update. |
0.1
|
residual_alpha
|
float
|
Weight of each new absolute error in the faded mean absolute error kept for every lead, in (0, 1]. |
0.05
|
min_scale
|
float
|
Positive floor for the reported spread, in target units. |
1e-06
|
Notes
Two cycles initialize the model as in
:class:~aberrant.model.timeseries.SeasonalResidualDetector, whose
scores equal this forecaster's lead-1 residual divided by its lead-1
spread. Every lead's spread starts at the mean absolute error of the
fitted warm-up model, then fades towards that lead's own errors. State
is O(season_length + horizon^2) and each event costs O(horizon).
Unrepresentable arithmetic raises OverflowError without changing state.
References
Hyndman and Athanasopoulos, Forecasting: Principles and Practice, 3rd ed., additive Holt-Winters component equations: https://otexts.com/fpp3/holt-winters.html
RLSRegressor ¶
RLSRegressor(*, forgetting: float = 0.999, delta: float = 1000.0, fit_intercept: bool = True, residual_alpha: float = 0.05, min_scale: float = 1e-06)
Bases: BaseRegressor
Predict a target linearly from covariates, by recursive least squares.
Each event updates the weights exactly as a least-squares refit with
geometrically faded event weights would, at O(d^2) cost for d
coefficients. The covariate names are fixed by the first learned event.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
forgetting
|
float
|
Weight factor in (0, 1] applied to past events at every update. 1 weighs all events equally; 0.999 remembers roughly the last 1,000. |
0.999
|
delta
|
float
|
Positive initial variance of the coefficients. Larger values mean a weaker prior towards zero. |
1000.0
|
fit_intercept
|
bool
|
Whether to learn a constant term. |
True
|
residual_alpha
|
float
|
Weight of each new absolute error in the faded mean absolute error that gives the spread, in (0, 1]. |
0.05
|
min_scale
|
float
|
Positive floor for the reported spread, in target units. |
1e-06
|
Notes
Once d events are learned, each further event's error is measured
against the prediction made before learning it, and the faded mean
absolute error of those errors is the reported spread. The model is
ready after the first such error, at d + 1 events. With
forgetting < 1 and covariates that stop varying, the coefficient
covariance can grow without bound; keep inputs informative or use 1.
Unrepresentable arithmetic raises OverflowError without changing state.
Examples:
from aberrant.forecast import RLSRegressor
model = RLSRegressor()
for a, b in [(0.0, 1.0), (1.0, 0.0), (1.0, 1.0), (2.0, 1.0)]:
x = {"a": a, "b": b}
prediction = model.predict_one(x) # None until ready
model.learn_one(x, 2.0 * a - b + 1.0)
model.predict_one({"a": 3.0, "b": 2.0}).mean # close to (5.0,)
References
Haykin, Adaptive Filter Theory, 5th ed., chapter 10 (recursive least-squares adaptive filters).
feature_names
property
¶
Covariate names in coefficient order, once learned.
coefficients
property
¶
Learned weight per covariate, and "intercept" when fitted.
predict_one ¶
predict_one(x: FeatureMap) -> Forecast | None
Predict the target of the event with covariates x at lead 0.
learn_one ¶
learn_one(x: FeatureMap, y: float) -> None
Learn the target y of the event with covariates x.
ResidualDetector ¶
ResidualDetector(model: ForecasterProtocol | RegressorProtocol, target: str, *, lead: int | None = None, score: Literal['absolute', 'scaled'] = 'scaled')
Score each event by how far its target misses a forecast or prediction.
The detector splits each event into the target x[target] and, for a
regressor, the covariates (every other key). It scores before learning:
- A regressor predicts the target from the event's covariates (lead 0).
- A forecaster's score uses the forecast issued
leadevents earlier, so the target is compared with what was expected before it arrived. A forecaster learns only the target; other keys are ignored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
ForecasterProtocol | RegressorProtocol
|
An online forecaster ( |
required |
target
|
str
|
Name of the target feature in every event. |
required |
lead
|
int | None
|
Forecast lead to score, from 1 to the forecaster's horizon; defaults to 1. Must be 0, the default, for a regressor. |
None
|
score
|
Literal['absolute', 'scaled']
|
|
'scaled'
|
Notes
Scores are non-negative and higher is more anomalous. They are 0 until
a forecast for the event exists. The detector learns every event, so
the model adapts to anomalies too; a longer lead compares with a
forecast issued before an anomaly began. Calibrate the scores, for
example with :class:~aberrant.calibration.ScoreCalibrator.
Examples:
from aberrant.forecast import HoltWinters, ResidualDetector
detector = ResidualDetector(HoltWinters(season_length=24), "load")
for x in stream:
score = detector.score_one(x)
detector.learn_one(x)
forecast_for ¶
forecast_for(x: FeatureMap) -> Forecast | None
Return the forecast x is scored against, or None without one.
For a forecaster it is the forecast issued lead events earlier; read
it at lead. For a regressor it is the prediction from the covariates
of x. The target is not read, so x may be the event before its
target is known.
explain_one ¶
explain_one(x: FeatureMap) -> tuple[float, float | None, float | None]
Return (score, expected target, signed residual) without learning.
Before a forecast exists return (0.0, None, None). A positive
residual means the target exceeds what was expected.
score_one ¶
score_one(x: FeatureMap) -> float
Return the nonconformity of x[target], or 0 without a forecast.
learn_one ¶
learn_one(x: FeatureMap) -> None
Learn the event, then keep the forecaster's next forecast.
nonconformity ¶
nonconformity(forecast: Forecast, lead: int, y: float, score: NonconformityScore = 'absolute', *, alpha: float | None = None) -> float
How far y falls from the forecast at lead; larger is stranger.
absolute:|y - mean|, in target units.scaled:|y - mean| / spread, comparable across leads and series.cqr:max(lo - y, y - hi)for the quantiles atalpha / 2and1 - alpha / 2; negative inside that interval (conformalized quantile regression).
Feed the score to a calibrator with the target event as its key. Each lead is its own score stream, since forecast errors grow with the lead.
interval ¶
interval(forecast: Forecast, lead: int, threshold: float, score: NonconformityScore = 'absolute', *, alpha: float | None = None) -> tuple[float, float]
The values of y whose score stays at or below threshold.
An infinite threshold, as a calibrator issues before its first score,
gives (-inf, inf). A cqr threshold below -(hi - lo) / 2 leaves
no such value; the interval then collapses to the quantiles' midpoint.
BaseForecaster ¶
Bases: ABC
An online forecaster of one series sampled at a fixed cadence.
forecast_one() forecasts leads 1..horizon from the values learned
so far, and learn_one(y) learns the next value. Each learned value
advances the series by one step: there are no timestamps, so resample
irregular or missing readings before learning them.
BaseRegressor ¶
Bases: ABC
An online regressor of one target from the covariates of each event.
predict_one(x) predicts the target of the event with covariates x
at lead 0, and learn_one(x, y) learns that event's target once known.
learn_one
abstractmethod
¶
learn_one(x: FeatureMap, y: float) -> None
Learn the target y of the event with covariates x.
predict_one
abstractmethod
¶
predict_one(x: FeatureMap) -> Forecast | None
Predict the target at lead 0, or None before readiness.