Implementation:Online ml River Anomaly OneClassSVM
| Knowledge Sources | River River Docs Estimating the Support of a High-Dimensional Distribution |
|---|---|
| Domains | Online Machine Learning, Anomaly Detection, Support Vector Machines |
| Last Updated | 2026-02-08 16:00 GMT |
Overview
Concrete tool for performing online one-class SVM anomaly detection in the River library, implementing stochastic gradient descent optimization of the nu-SVM objective for streaming data.
Description
The anomaly.OneClassSVM class implements an online variant of the One-Class SVM algorithm for unsupervised anomaly detection. It inherits from both linear_model.base.GLM (for the SGD machinery) and anomaly.base.AnomalyDetector (for the anomaly detection interface).
Internally, the model treats every observation as a positive example (y=1) and optimizes a hinge loss with L2 regularization controlled by nu / 2. The decision function score_one(x) returns w . x - intercept, where lower values indicate more anomalous observations.
It is recommended to:
- Scale data upstream with
preprocessing.StandardScaler - Use
feature_extraction.RBFSamplerto capture non-linearities - Wrap with
anomaly.QuantileFilterto convert raw scores to binary anomaly labels
Usage
Import and use anomaly.OneClassSVM when:
- You need an SGD-based online anomaly detector
- You want to leverage the SVM framework for unsupervised anomaly detection
- You can estimate the expected anomaly fraction (nu parameter)
- You want raw decision function scores for flexible downstream thresholding
Code Reference
Source Location
river/anomaly/svm.py, lines 8-111.
Signature
class OneClassSVM(linear_model.base.GLM, anomaly.base.AnomalyDetector):
def __init__(
self,
nu=0.1,
optimizer: optim.base.Optimizer | None = None,
intercept_lr: optim.base.Scheduler | float = 0.01,
clip_gradient=1e12,
initializer: optim.base.Initializer | None = None,
):
Import
from river import anomaly
model = anomaly.OneClassSVM(nu=0.1)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| nu | float | 0.1 | Upper bound on the fraction of training errors and lower bound on the fraction of support vectors. Interpreted as the expected fraction of anomalies. |
| optimizer | optim.base.Optimizer or None | None | Sequential optimizer for weight updates. Defaults to optim.SGD(0.01).
|
| intercept_lr | float or Scheduler | 0.01 | Learning rate for the intercept. Set to 0 to disable intercept updates. |
| clip_gradient | float | 1e12 | Clips the absolute value of each gradient value. |
| initializer | optim.base.Initializer or None | None | Weight initialization scheme. Defaults to optim.initializers.Zeros().
|
Methods
learn_one(x: dict) -> None-- Updates the model weights using SGD on the hinge loss, treating x as a positive (normal) example.score_one(x: dict) -> float-- Returns the raw decision function valuew . x - intercept. Lower values indicate more anomalous observations.
I/O Contract
Inputs
| Method | Parameter | Type | Description |
|---|---|---|---|
| learn_one | x | dict | A dictionary mapping feature names to numeric values. |
| score_one | x | dict | A dictionary mapping feature names to numeric values. |
Outputs
| Method | Return Type | Description |
|---|---|---|
| learn_one | None | Updates internal weights via SGD; no return value. |
| score_one | float | Raw decision function value. Not bounded to [0, 1]. Lower values indicate more anomalous observations. |
Usage Examples
Basic usage with QuantileFilter:
from river import anomaly, datasets, metrics
model = anomaly.QuantileFilter(
anomaly.OneClassSVM(nu=0.2),
q=0.995
)
auc = metrics.ROCAUC()
for x, y in datasets.CreditCard().take(2500):
score = model.score_one(x)
is_anomaly = model.classify(score)
model.learn_one(x)
auc.update(y, is_anomaly)
print(auc)
# ROCAUC: 74.68%
Evaluation with progressive_val_score:
from river import anomaly, datasets, metrics, evaluate
model = anomaly.QuantileFilter(
anomaly.OneClassSVM(nu=0.2),
q=0.995
)
evaluate.progressive_val_score(
dataset=datasets.CreditCard().take(2500),
model=model,
metric=metrics.ROCAUC(),
print_every=1000
)
# [1,000] ROCAUC: 74.40%
# [2,000] ROCAUC: 74.60%
# [2,500] ROCAUC: 74.68%
# ROCAUC: 74.68%