Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Online ml River Online Adaptation Pattern

From Leeroopedia


Knowledge Sources Domains Last Updated
River River Docs Online Machine Learning, Time Series Forecasting, Concept Drift 2026-02-08 16:00 GMT

Overview

Concrete tool documenting how SNARIMAX and HoltWinters continuously adapt their parameters to evolving time series patterns. Pattern Doc.

Description

This pattern doc describes the specific code paths through which River's online forecasters adapt to changing data patterns. Both SNARIMAX and HoltWinters perform adaptation as an integral part of their learn_one method, without requiring external drift detection. The adaptation mechanisms are fundamentally different but serve the same purpose: keeping the model aligned with the most recent behavior of the time series.

Usage

Reference this pattern when you need to understand the internal adaptation mechanics of River forecasters, or when tuning hyperparameters that control adaptation speed.

Code Reference

Source Location

  • river/time_series/snarimax.py:L336-L350 (SNARIMAX adaptation via regressor update)
  • river/time_series/holt_winters.py:L187-L208 (HoltWinters adaptation via exponential smoothing)

SNARIMAX Adaptation

The adaptation happens at line 348 of snarimax.py, where the internal regressor learns from the new observation:

def learn_one(self, y, x=None):
    if len(self.y_hist) >= self.differencer.n_required_past_values:
        x = self._add_lag_features(x=x, Y=self.y_diff, errors=self.errors)

        y_diff = self.differencer.diff(y, self.y_hist)
        self.y_diff.appendleft(y_diff)

        y_pred = self.regressor.predict_one(x)
        self.errors.appendleft(y_diff - y_pred)

        # KEY ADAPTATION STEP: regressor updates weights via SGD
        self.regressor.learn_one(x, y_diff)

    self.y_hist.appendleft(y)

Adaptation mechanism: The default regressor is StandardScaler | LinearRegression. The LinearRegression uses SGD (default lr=0.01) which updates weights by:

w_new = w_old - 0.01 * (hat{y} - y) * x

This means the AR/MA weights continuously shift toward values that minimize recent prediction errors.

HoltWinters Adaptation

The adaptation happens through the component update calls at lines 189-193 of holt_winters.py:

def learn_one(self, y, x=None):
    if self._initialized:
        # KEY ADAPTATION: Each component updates via exponential smoothing
        self.level.update(y, self.trend, self.season)
        if self.trend is not None:
            self.trend.update(y, self.level)
        if self.season is not None:
            self.season.update(y, self.level, self.trend)
        return
    # ... initialization phase ...

For additive level, the update (in AdditiveLevel.update) is:

# river/time_series/holt_winters.py:L20-L23
def update(self, y, trend, season):
    self.append(
        self.alpha * (y - (season[-season.seasonality] if season else 0))
        + (1 - self.alpha) * (self[-1] + (trend[-1] if trend else 0))
    )

Adaptation mechanism: Each smoothing parameter (alpha, beta, gamma) controls the blend between the new signal and the previous state. Higher values weight the new observation more, enabling faster adaptation.

Import

from river import time_series

I/O Contract

Inputs

Context Parameter Type Description
SNARIMAX regressor optimizer lr float Learning rate controlling SGD adaptation speed (default 0.01)
HoltWinters alpha float Level smoothing parameter (0 to 1)
HoltWinters beta float or None Trend smoothing parameter (0 to 1)
HoltWinters gamma float or None Seasonal smoothing parameter (0 to 1)

Outputs

Context Output Description
SNARIMAX Updated regressor weights Weights shift toward values minimizing recent prediction errors
HoltWinters Updated level, trend, seasonal components Components adapt based on smoothing parameter settings

Usage Examples

Observing SNARIMAX adaptation

from river import datasets
from river import time_series

model = time_series.SNARIMAX(p=3, d=1, q=1, m=12, sd=1)

for i, (x, y) in enumerate(datasets.AirlinePassengers()):
    model.learn_one(y)
    # The regressor's weights are updated at each step via SGD
    # As patterns change, weights adapt automatically

Controlling HoltWinters adaptation speed

from river import time_series

# Fast adaptation: high smoothing parameters
fast_model = time_series.HoltWinters(alpha=0.8, beta=0.5, gamma=0.8, seasonality=12)

# Slow adaptation: low smoothing parameters
slow_model = time_series.HoltWinters(alpha=0.1, beta=0.05, gamma=0.1, seasonality=12)

# Both models adapt, but at different rates
for y in [112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115]:
    fast_model.learn_one(y)
    slow_model.learn_one(y)

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment