ice-skaters (docs)
skaters on a river: calibrated forecast features for streaming machine learning, in Python and in the browser.
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.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
197cb635fb4ef2d3563bb4135dadad41495a3f233491d7fd3d39be3004c6484d
|
|
| MD5 |
6d4edc964d4819654aa0da10c2fa58df
|
|
| BLAKE2b-256 |
ebc4317c142360994270fdb7006c1fb001a5b4bd956613b26faa71f13eb4e4f4
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ee3629abd8743b0c322d2368aafa660c92313ef44d4d1fb5b1b17ade13ef9743
|
|
| MD5 |
7f50ce21eac559c3d601b41ec1792176
|
|
| BLAKE2b-256 |
248a80c5621ec497bbb8f08a8618e98e2e4e367bf33dda27253b695a176838af
|