Skip to main content

ice-skaters (docs)

skaters on a river: calibrated forecast features for streaming machine learning, in Python and in the browser.

Live demo · The paper

The idea, from zero

Suppose data arrives one row at a time and a model must predict, then learn, then move to the next row: sensor readings, poll numbers, prices, counts. That is streaming machine learning, and river is the standard Python library for it. The usual hygiene is to standardize each number on the fly, subtracting a running mean and dividing by a running deviation. That helps with scale and nothing else: one fat-fingered reading still arrives at full force, and worse, it poisons the running mean and deviation that every later reading is judged by.

ice-skaters replaces that with a stronger contract. Every numeric stream gets its own tiny online forecaster (from skaters, a zero-dependency forecasting library), and the model is handed the forecaster's two-number summary instead of the raw value: the predictive mean, which is what the forecaster expected this value to be, and the standardized surprise z, which is how unexpected the actual value was, on a universal scale where 2 is notable, 4 is remarkable, and 7 cannot be exceeded by construction. The mean carries the level. The z carries the news. A wild observation can move the pair only so far, and that bounded influence is where the robustness comes from.

Two ways to feed a stream to a model

Install and use

pip install ice-skaters
from river import datasets, linear_model, metrics, preprocessing
from ice_skaters import LaplaceFeatures, LaplaceTarget

model = LaplaceTarget(
    regressor=preprocessing.TargetStandardScaler(
        regressor=LaplaceFeatures()
        | preprocessing.StandardScaler()
        | linear_model.LinearRegression()))

mae = metrics.MAE()
for x, y in datasets.TrumpApproval():
    pred = model.predict_one(x)
    mae.update(y, pred if pred is not None else 0.0)
    model.learn_one(x, y)

LaplaceFeatures is a river transformer that does the two-number substitution for the input streams. LaplaceTarget wraps any regressor, in the style of TargetStandardScaler, to add the target's own pair, which a transformer cannot do since it never sees the target; the target itself stays raw. Both estimators pipe, pickle and deep-copy like any river estimator. Non-numeric values pass through untouched, and NaN is imputed by the forecast itself with z = 0: the model receives "expected value, no news" instead of a poisoned pipeline.

If you adopt one thing, adopt the wrapper. In the ablation, LaplaceTarget alone beat river's recommended (lag-free) pipeline on three of four of river's own datasets untouched and 10/10 under simulated feature contamination. The fairness audit then asked the referee's question, what about a baseline with raw target lags, and the answer sharpened rather than broke the claim: hand-added lags are strong on smooth single-entity series, fragile everywhere else, and the wrapper on top of whatever features you have, lags included, improved the strongest configuration found on three of four datasets and sat within noise on the fourth. Add LaplaceFeatures when you distrust the features themselves.

What the evidence says

On TrumpApproval with river's recommended pipeline (progressive validation MAE, burn-in 100, examples/trump_approval.py):

clean 2% corrupted readings
StandardScaler pipeline 0.328 0.597
+ Laplace front-end 0.369 0.382

The front-end pays a small toll on clean data and holds its footing when the inputs misbehave. In controlled simulation the same substitution beats raw features, a running z-score, a median/MAD winsorizer and a Huberised loss 30/30 seeds under every contamination type tested. There is also a theorem: pathwise regret transfer with measured constants and no calibration assumption, proofs and a numerical bound check in papers/regret-transfer.md, and the full write-up in papers/ice-skaters-jss.pdf. Protocols, harnesses and the losing rows live in the timemachines repo, benchmarks/RESULTS.md section 6.

Cost, measured: about 390 microseconds per stream per sample, roughly 900x StandardScaler. Right for polls, sensors, market bars and anything at human timescales; wrong inside a hot path at hundreds of thousands of ticks per second. And the cheap-rollup control keeps the pitch honest: a free EWMA version of the same (mean, surprise) pair captures much of the robustness, ties or beats the Laplace pairs as features on the smoothest real datasets, and loses by 14-26% wherever the stream has structure an EWMA cannot track. If cost matters, start there; the calibrated forecaster is the upgrade path, and on smooth series its standalone forecast remains stronger than any of these regressions.

Boundaries, stated plainly

  • Distance-based learners (KNN) do not benefit: neighbour averaging is already spike-robust and the extra dimensions degrade the metric.
  • Entity-interleaved streams (many units multiplexed into one key) want per-entity forecasters; a single forecaster per key is handicapped.
  • If your heavy tails are signal rather than noise, taming them costs accuracy. Whether the extremes are informative decides the coordinates.

JavaScript

The same construction runs in the browser with no build step and no dependencies: docs/js/ice-skaters/index.mjs ports the river pieces the study used (StandardScaler, TargetStandardScaler, LinearRegression and the Pipeline learn-then-transform semantics, line for line, parity-tested against Python to 1e-9) on top of the vendored skaters JavaScript twin. The live demo is a stream, two models and a fat-finger button, all client-side.

Relation to the stack

skaters does one thing: fast univariate distributional forecasting, stdlib-only, in Python or the browser. timemachines builds anomaly detection on the same calibrated surprise streams. ice-skaters is the bridge from those streams to river's estimator protocol, and nothing more.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ice_skaters-0.1.3.tar.gz (13.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ice_skaters-0.1.3-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

File details

Details for the file ice_skaters-0.1.3.tar.gz.

File metadata

  • Download URL: ice_skaters-0.1.3.tar.gz
  • Upload date:
  • Size: 13.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ice_skaters-0.1.3.tar.gz
Algorithm Hash digest
SHA256 197cb635fb4ef2d3563bb4135dadad41495a3f233491d7fd3d39be3004c6484d
MD5 6d4edc964d4819654aa0da10c2fa58df
BLAKE2b-256 ebc4317c142360994270fdb7006c1fb001a5b4bd956613b26faa71f13eb4e4f4

See more details on using hashes here.

File details

Details for the file ice_skaters-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: ice_skaters-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 9.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ice_skaters-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 ee3629abd8743b0c322d2368aafa660c92313ef44d4d1fb5b1b17ade13ef9743
MD5 7f50ce21eac559c3d601b41ec1792176
BLAKE2b-256 248a80c5621ec497bbb8f08a8618e98e2e4e367bf33dda27253b695a176838af

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page