Implementation:Online ml River Ensemble StreamingRandomPatches
| Knowledge Sources | |
|---|---|
| Domains | Online_Learning, Ensemble_Methods, Random_Forests |
| Last Updated | 2026-02-08 16:00 GMT |
Overview
Streaming Random Patches (SRP) is an online ensemble method combining bagging and random subspaces with drift detection for evolving data streams.
Description
SRP trains each base learner on a random patch (subset of features and instances). Three training methods are supported: random subspaces (feature subsets), resampling (instance subsets via Poisson sampling), and random patches (both). Each ensemble member has its own drift detector (ADWIN) and warning detector to trigger background learners. When drift is detected, the model either switches to a trained background learner or resets. Feature subspaces are generated once and maintained throughout, with automatic regeneration on drift. Predictions use weighted voting based on member performance metrics, providing robust adaptation to concept drift.
Usage
Use SRPClassifier for classification tasks with concept drift and high-dimensional data. Use SRPRegressor for regression under similar conditions. The random patches method (default) generally works best, but use random subspaces when instances are reliable or resampling when features are limited. Configure drift detection with ADWIN or disable it for stationary data. The default n_models=10 balances accuracy and speed.
Code Reference
Source Location
- Repository: Online_ml_River
- File: river/ensemble/streaming_random_patches.py
Signature
class SRPClassifier(BaseSRPEnsemble, base.Classifier):
def __init__(
self,
model: base.Estimator | None = None,
n_models: int = 10,
subspace_size: int | float | str = 0.6,
training_method: str = "patches",
lam: int = 6,
drift_detector: base.DriftDetector | None = None,
warning_detector: base.DriftDetector | None = None,
disable_detector: str = "off",
disable_weighted_vote: bool = False,
seed: int | None = None,
metric: ClassificationMetric | None = None,
)
class SRPRegressor(BaseSRPEnsemble, base.Regressor):
def __init__(
self,
model: base.Regressor | None = None,
n_models: int = 10,
subspace_size: int | float | str = 0.6,
training_method: str = "patches",
lam: int = 6,
drift_detector: base.DriftDetector | None = None,
warning_detector: base.DriftDetector | None = None,
disable_detector: str = "off",
disable_weighted_vote: bool = True,
drift_detection_criteria: str = "error",
aggregation_method: str = "mean",
seed=None,
metric: RegressionMetric | None = None,
)
Import
from river import ensemble
I/O Contract
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| model | Estimator or None | HoeffdingTree | Base learner for ensemble |
| n_models | int | 10 | Number of ensemble members |
| subspace_size | int/float/str | 0.6 | Feature subset size (%, count, 'sqrt', 'rmsqrt') |
| training_method | str | "patches" | 'subspaces', 'resampling', or 'patches' |
| lam | int | 6 | Poisson lambda for resampling |
| drift_detector | DriftDetector | ADWIN(1e-5) | Drift detection algorithm |
| warning_detector | DriftDetector | ADWIN(1e-4) | Warning detection for background learner |
| disable_detector | str | "off" | Disable drift detection: 'off', 'drift', 'warning' |
| disable_weighted_vote | bool | False (clf) / True (reg) | Use uniform voting |
| metric | Metric | Accuracy / MAE | Performance metric for weighting |
| aggregation_method | str | "mean" | Aggregation: 'mean' or 'median' (regressor) |
| drift_detection_criteria | str | "error" | Track 'error' or 'prediction' (regressor) |
Input/Output
| Method | Input | Output |
|---|---|---|
| learn_one | x: dict, y: target | None |
| predict_proba_one | x: dict | dict (classifier) |
| predict_one | x: dict | float (regressor) or class (classifier) |
Usage Examples
# SRPClassifier
from river import ensemble
from river import evaluate
from river import metrics
from river.datasets import synth
from river import tree
dataset = synth.ConceptDriftStream(
seed=42,
position=500,
width=50
).take(1000)
base_model = tree.HoeffdingTreeClassifier(
grace_period=50, delta=0.01,
nominal_attributes=['age', 'car', 'zipcode']
)
model = ensemble.SRPClassifier(
model=base_model, n_models=3, seed=42,
)
metric = metrics.Accuracy()
evaluate.progressive_val_score(dataset, model, metric)
# Accuracy: 72.17%
# SRPRegressor
dataset = synth.FriedmanDrift(
drift_type='gsg',
position=(350, 750),
transition_window=200,
seed=42
).take(1000)
base_model = tree.HoeffdingTreeRegressor(grace_period=50)
model = ensemble.SRPRegressor(
model=base_model,
training_method="patches",
n_models=3,
seed=42
)
metric = metrics.R2()
evaluate.progressive_val_score(dataset, model, metric)
# R2: 0.571117