Skip to content

anomaly

This module contains the anomaly detection algorithms for the deep_river package.

Modules:

Name Description
ae
probability_weighted_ae
rolling_ae
scaler

Classes:

Name Description
AnomalyMeanScaler

Wrapper around an anomaly detector that scales the model's output

AnomalyMinMaxScaler

Wrapper around an anomaly detector that scales the model's output to

AnomalyStandardScaler

Wrapper around an anomaly detector that standardizes the model's output

Autoencoder

Represents an initialized autoencoder for anomaly detection and feature learning.

ProbabilityWeightedAutoencoder
RollingAutoencoder

Rolling window autoencoder for streaming anomaly detection.

AnomalyMeanScaler

AnomalyMeanScaler(
    anomaly_detector: AnomalyDetector,
    rolling: bool = True,
    window_size=250,
)

Bases: AnomalyScaler

Wrapper around an anomaly detector that scales the model's output by the incremental mean of previous scores.

Parameters:

Name Type Description Default
anomaly_detector AnomalyDetector

The anomaly detector to wrap.

required
metric_type

The type of metric to use.

required
rolling bool

Choose whether the metrics are rolling metrics or not.

True
window_size

The window size used for mean computation if rolling==True.

250

Methods:

Name Description
learn_one

Update the scaler and the underlying anomaly scaler.

score_many

Return scaled anomaly scores based on raw score provided by

score_one

Return a scaled anomaly score based on raw score provided by the

Source code in deep_river/anomaly/scaler.py
def __init__(
    self,
    anomaly_detector: AnomalyDetector,
    rolling: bool = True,
    window_size=250,
):
    super().__init__(anomaly_detector=anomaly_detector)
    self.rolling = rolling
    self.window_size = window_size
    self.mean = utils.Rolling(Mean(), self.window_size) if self.rolling else Mean()

learn_one

learn_one(*args, **kwargs) -> None

Update the scaler and the underlying anomaly scaler.

Parameters:

Name Type Description Default
*args

Depends on whether the underlying anomaly detector is supervised or not.

()

Returns:

Type Description
AnomalyScaler

The model itself.

Source code in deep_river/anomaly/scaler.py
def learn_one(self, *args, **kwargs) -> None:
    """
    Update the scaler and the underlying anomaly scaler.

    Parameters
    ----------
    *args
        Depends on whether the underlying anomaly detector
        is supervised or not.

    Returns
    -------
    AnomalyScaler
        The model itself.
    """

    self.anomaly_detector.learn_one(*args, **kwargs)

score_many abstractmethod

score_many(*args, **kwargs) -> ndarray

Return scaled anomaly scores based on raw score provided by the wrapped anomaly detector.

A high score is indicative of an anomaly. A low score corresponds to a normal observation.

Parameters:

Name Type Description Default
*args

Depends on whether the underlying anomaly detector is supervised or not.

()

Returns:

Type Description
Scaled anomaly scores. Larger values indicate more anomalous examples.
Source code in deep_river/anomaly/scaler.py
@abc.abstractmethod
def score_many(self, *args, **kwargs) -> np.ndarray:
    """Return scaled anomaly scores based on raw score provided by
    the wrapped anomaly detector.

    A high score is indicative of an anomaly. A low score corresponds
    to a normal observation.

    Parameters
    ----------
    *args
        Depends on whether the underlying anomaly detector is
        supervised or not.

    Returns
    -------
    Scaled anomaly scores. Larger values indicate more anomalous examples.
    """

score_one

score_one(*args, **kwargs)

Return a scaled anomaly score based on raw score provided by the wrapped anomaly detector. Larger values indicate more anomalous examples.

Parameters:

Name Type Description Default
*args

Depends on whether the underlying anomaly detector is supervised or not.

()

Returns:

Type Description
An scaled anomaly score. Larger values indicate more
anomalous examples.
Source code in deep_river/anomaly/scaler.py
def score_one(self, *args, **kwargs):
    """
    Return a scaled anomaly score based on raw score provided by the
    wrapped anomaly detector. Larger values indicate more
    anomalous examples.

    Parameters
    ----------
    *args
        Depends on whether the underlying anomaly detector is
        supervised or not.

    Returns
    -------
    An scaled anomaly score. Larger values indicate more
    anomalous examples.
    """
    raw_score = self.anomaly_detector.score_one(*args, **kwargs)
    mean = self.mean.update(raw_score).get()
    score = raw_score / mean

    return score

AnomalyMinMaxScaler

AnomalyMinMaxScaler(
    anomaly_detector: AnomalyDetector,
    rolling: bool = True,
    window_size: int = 250,
)

Bases: AnomalyScaler

Wrapper around an anomaly detector that scales the model's output to \([0, 1]\) using rolling min and max metrics.

Parameters:

Name Type Description Default
anomaly_detector AnomalyDetector

The anomaly detector to wrap.

required
rolling bool

Choose whether the metrics are rolling metrics or not.

True
window_size int

The window size used for the metrics if rolling==True

250

Methods:

Name Description
learn_one

Update the scaler and the underlying anomaly scaler.

score_many

Return scaled anomaly scores based on raw score provided by

score_one

Return a scaled anomaly score based on raw score provided by the

Source code in deep_river/anomaly/scaler.py
def __init__(
    self,
    anomaly_detector: AnomalyDetector,
    rolling: bool = True,
    window_size: int = 250,
):
    super().__init__(anomaly_detector)
    self.rolling = rolling
    self.window_size = window_size
    self.min = RollingMin(self.window_size) if self.rolling else Min()
    self.max = RollingMin(self.window_size) if self.rolling else Min()

learn_one

learn_one(*args, **kwargs) -> None

Update the scaler and the underlying anomaly scaler.

Parameters:

Name Type Description Default
*args

Depends on whether the underlying anomaly detector is supervised or not.

()

Returns:

Type Description
AnomalyScaler

The model itself.

Source code in deep_river/anomaly/scaler.py
def learn_one(self, *args, **kwargs) -> None:
    """
    Update the scaler and the underlying anomaly scaler.

    Parameters
    ----------
    *args
        Depends on whether the underlying anomaly detector
        is supervised or not.

    Returns
    -------
    AnomalyScaler
        The model itself.
    """

    self.anomaly_detector.learn_one(*args, **kwargs)

score_many abstractmethod

score_many(*args, **kwargs) -> ndarray

Return scaled anomaly scores based on raw score provided by the wrapped anomaly detector.

A high score is indicative of an anomaly. A low score corresponds to a normal observation.

Parameters:

Name Type Description Default
*args

Depends on whether the underlying anomaly detector is supervised or not.

()

Returns:

Type Description
Scaled anomaly scores. Larger values indicate more anomalous examples.
Source code in deep_river/anomaly/scaler.py
@abc.abstractmethod
def score_many(self, *args, **kwargs) -> np.ndarray:
    """Return scaled anomaly scores based on raw score provided by
    the wrapped anomaly detector.

    A high score is indicative of an anomaly. A low score corresponds
    to a normal observation.

    Parameters
    ----------
    *args
        Depends on whether the underlying anomaly detector is
        supervised or not.

    Returns
    -------
    Scaled anomaly scores. Larger values indicate more anomalous examples.
    """

score_one

score_one(*args, **kwargs)

Return a scaled anomaly score based on raw score provided by the wrapped anomaly detector. Larger values indicate more anomalous examples.

Parameters:

Name Type Description Default
*args

Depends on whether the underlying anomaly detector is supervised or not.

()

Returns:

Type Description
An scaled anomaly score. Larger values indicate more
anomalous examples.
Source code in deep_river/anomaly/scaler.py
def score_one(self, *args, **kwargs):
    """
    Return a scaled anomaly score based on raw score provided by the
    wrapped anomaly detector. Larger values indicate more
    anomalous examples.

    Parameters
    ----------
    *args
        Depends on whether the underlying anomaly detector is
        supervised or not.

    Returns
    -------
    An scaled anomaly score. Larger values indicate more
    anomalous examples.
    """
    raw_score = self.anomaly_detector.score_one(*args, **kwargs)
    min = self.min.update(raw_score).get()
    max = self.max.update(raw_score).get()
    score = (raw_score - min) / (max - min)

    return score

AnomalyStandardScaler

AnomalyStandardScaler(
    anomaly_detector: AnomalyDetector,
    with_std: bool = True,
    rolling: bool = True,
    window_size: int = 250,
)

Bases: AnomalyScaler

Wrapper around an anomaly detector that standardizes the model's output using incremental mean and variance metrics.

Parameters:

Name Type Description Default
anomaly_detector AnomalyDetector

The anomaly detector to wrap.

required
with_std bool

Whether to use standard deviation for scaling.

True
rolling bool

Choose whether the metrics are rolling metrics or not.

True
window_size int

The window size used for the metrics if rolling==True.

250

Methods:

Name Description
learn_one

Update the scaler and the underlying anomaly scaler.

score_many

Return scaled anomaly scores based on raw score provided by

score_one

Return a scaled anomaly score based on raw score provided by the

Source code in deep_river/anomaly/scaler.py
def __init__(
    self,
    anomaly_detector: AnomalyDetector,
    with_std: bool = True,
    rolling: bool = True,
    window_size: int = 250,
):
    super().__init__(anomaly_detector)
    self.rolling = rolling
    self.window_size = window_size
    self.mean = utils.Rolling(Mean(), self.window_size) if self.rolling else Mean()
    self.sq_mean = (
        utils.Rolling(Mean(), self.window_size) if self.rolling else Mean()
    )
    self.with_std = with_std

learn_one

learn_one(*args, **kwargs) -> None

Update the scaler and the underlying anomaly scaler.

Parameters:

Name Type Description Default
*args

Depends on whether the underlying anomaly detector is supervised or not.

()

Returns:

Type Description
AnomalyScaler

The model itself.

Source code in deep_river/anomaly/scaler.py
def learn_one(self, *args, **kwargs) -> None:
    """
    Update the scaler and the underlying anomaly scaler.

    Parameters
    ----------
    *args
        Depends on whether the underlying anomaly detector
        is supervised or not.

    Returns
    -------
    AnomalyScaler
        The model itself.
    """

    self.anomaly_detector.learn_one(*args, **kwargs)

score_many abstractmethod

score_many(*args, **kwargs) -> ndarray

Return scaled anomaly scores based on raw score provided by the wrapped anomaly detector.

A high score is indicative of an anomaly. A low score corresponds to a normal observation.

Parameters:

Name Type Description Default
*args

Depends on whether the underlying anomaly detector is supervised or not.

()

Returns:

Type Description
Scaled anomaly scores. Larger values indicate more anomalous examples.
Source code in deep_river/anomaly/scaler.py
@abc.abstractmethod
def score_many(self, *args, **kwargs) -> np.ndarray:
    """Return scaled anomaly scores based on raw score provided by
    the wrapped anomaly detector.

    A high score is indicative of an anomaly. A low score corresponds
    to a normal observation.

    Parameters
    ----------
    *args
        Depends on whether the underlying anomaly detector is
        supervised or not.

    Returns
    -------
    Scaled anomaly scores. Larger values indicate more anomalous examples.
    """

score_one

score_one(*args, **kwargs)

Return a scaled anomaly score based on raw score provided by the wrapped anomaly detector. Larger values indicate more anomalous examples.

Parameters:

Name Type Description Default
*args

Depends on whether the underlying anomaly detector is supervised or not.

()

Returns:

Type Description
An scaled anomaly score. Larger values indicate more
anomalous examples.
Source code in deep_river/anomaly/scaler.py
def score_one(self, *args, **kwargs):
    """
    Return a scaled anomaly score based on raw score provided by the
    wrapped anomaly detector. Larger values indicate more
    anomalous examples.

    Parameters
    ----------
    *args
        Depends on whether the underlying anomaly detector
        is supervised or not.

    Returns
    -------
    An scaled anomaly score. Larger values indicate more
    anomalous examples.
    """
    raw_score = self.anomaly_detector.score_one(*args, **kwargs)
    mean = self.mean.update(raw_score).get()
    if self.with_std:
        var = (
            self.sq_mean.update(raw_score**2).get() - mean**2
        )  # todo is this correct?
        score = (raw_score - mean) / var**0.5
    else:
        score = raw_score - mean

    return score

Autoencoder

Autoencoder(
    module: Module,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Callable] = "sgd",
    lr: float = 0.001,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    **kwargs
)

Bases: DeepEstimator, AnomalyDetector

Represents an initialized autoencoder for anomaly detection and feature learning.

This class is built upon the DeepEstimatorInitialized and AnomalyDetector base classes. It provides methods for performing unsupervised learning through an autoencoder mechanism. The primary objective of the class is to train the autoencoder on input data and compute anomaly scores based on the reconstruction error. It supports learning on individual examples or entire batches of data.

Attributes:

Name Type Description
is_feature_incremental bool

Indicates whether the model is designed to increment features dynamically.

module Module

The PyTorch model representing the autoencoder architecture.

loss_fn Union[str, Callable]

Specifies the loss function to compute the reconstruction error.

optimizer_fn Union[str, Callable]

Specifies the optimizer to be used for training the autoencoder.

lr float

The learning rate for optimization.

device str

The device on which the model is loaded and trained (e.g., "cpu", "cuda").

seed int

Random seed for ensuring reproducibility.

Methods:

Name Description
clone

Return a fresh estimator instance with (optionally) copied state.

draw

Render a (partial) computational graph of the wrapped model.

learn_many

Performs one step of training with a batch of examples.

learn_one

Performs one step of training with a single example.

load

Load a previously saved estimator.

save

Persist the estimator (architecture, weights, optimiser & runtime state).

score_many

Returns an anomaly score for the provided batch of examples in

score_one

Returns an anomaly score for the provided example in the form of

Source code in deep_river/anomaly/ae.py
def __init__(
    self,
    module: torch.nn.Module,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Callable] = "sgd",
    lr: float = 1e-3,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    **kwargs,
):
    super().__init__(
        module=module,
        loss_fn=loss_fn,
        optimizer_fn=optimizer_fn,
        lr=lr,
        is_feature_incremental=is_feature_incremental,
        device=device,
        seed=seed,
        **kwargs,
    )
    self.is_feature_incremental = is_feature_incremental

clone

clone(
    new_params=None,
    include_attributes: bool = False,
    copy_weights: bool = False,
)

Return a fresh estimator instance with (optionally) copied state.

Parameters:

Name Type Description Default
new_params dict | None

Parameter overrides for the cloned instance.

None
include_attributes bool

If True, runtime state (observed features, buffers) is also copied.

False
copy_weights bool

If True, model weights are copied (otherwise the module is re‑initialised).

False
Source code in deep_river/base.py
def clone(
    self,
    new_params=None,
    include_attributes: bool = False,
    copy_weights: bool = False,
):
    """Return a fresh estimator instance with (optionally) copied state.

    Parameters
    ----------
    new_params : dict | None
        Parameter overrides for the cloned instance.
    include_attributes : bool, default=False
        If True, runtime state (observed features, buffers) is also copied.
    copy_weights : bool, default=False
        If True, model weights are copied (otherwise the module is re‑initialised).
    """
    new_params = new_params or {}
    copy_weights = new_params.pop("copy_weights", copy_weights)

    params = {**self._get_all_init_params(), **new_params}

    if "module" not in new_params:
        params["module"] = self._rebuild_module()

    new_est = self.__class__(**self._filter_kwargs(self.__class__.__init__, params))

    if copy_weights and hasattr(self.module, "state_dict"):
        new_est.module.load_state_dict(self.module.state_dict())

    if include_attributes:
        new_est._restore_runtime_state(self._get_runtime_state())

    return new_est

draw

draw()

Render a (partial) computational graph of the wrapped model.

Imports graphviz and torchviz lazily. Raises an informative ImportError if the optional dependencies are not installed.

Source code in deep_river/base.py
def draw(self):  # type: ignore[override]
    """Render a (partial) computational graph of the wrapped model.

    Imports ``graphviz`` and ``torchviz`` lazily. Raises an informative
    ImportError if the optional dependencies are not installed.
    """
    try:  # pragma: no cover
        from torchviz import make_dot  # type: ignore
    except Exception as err:  # noqa: BLE001
        raise ImportError(
            "graphviz and torchviz must be installed to draw the model."
        ) from err

    first_parameter = next(self.module.parameters())
    input_shape = first_parameter.size()
    y_pred = self.module(torch.rand(input_shape))
    return make_dot(y_pred.mean(), params=dict(self.module.named_parameters()))

learn_many

learn_many(X: DataFrame) -> None

Performs one step of training with a batch of examples.

Parameters:

Name Type Description Default
X DataFrame

Input batch of examples.

required
Source code in deep_river/anomaly/ae.py
def learn_many(self, X: pd.DataFrame) -> None:
    """
    Performs one step of training with a batch of examples.

    Parameters
    ----------
    X
        Input batch of examples.
    """

    self._update_observed_features(X)
    X_t = self._df2tensor(X)
    self._learn(X_t)

learn_one

learn_one(x: dict, y: Any = None) -> None

Performs one step of training with a single example.

Parameters:

Name Type Description Default
x dict

Input example.

required
Source code in deep_river/anomaly/ae.py
def learn_one(self, x: dict, y: Any = None) -> None:
    """
    Performs one step of training with a single example.

    Parameters
    ----------
    x
        Input example.
    """
    self._update_observed_features(x)
    self._learn(self._dict2tensor(x))

load classmethod

load(filepath: Union[str, Path])

Load a previously saved estimator.

The method reconstructs the estimator class, its wrapped module, optimiser state and runtime information (feature names, buffers, etc.).

Source code in deep_river/base.py
@classmethod
def load(cls, filepath: Union[str, Path]):
    """Load a previously saved estimator.

    The method reconstructs the estimator class, its wrapped module, optimiser
    state and runtime information (feature names, buffers, etc.).
    """
    with open(filepath, "rb") as f:
        state = pickle.load(f)

    estimator_cls = cls._import_from_path(state["estimator_class"])
    init_params = state["init_params"]

    # Rebuild module if needed
    if "module" in init_params and isinstance(init_params["module"], dict):
        module_info = init_params.pop("module")
        module_cls = cls._import_from_path(module_info["class"])
        module = module_cls(
            **cls._filter_kwargs(module_cls.__init__, module_info["kwargs"])
        )
        if state.get("model_state_dict"):
            module.load_state_dict(state["model_state_dict"])
        init_params["module"] = module

    estimator = estimator_cls(
        **cls._filter_kwargs(estimator_cls.__init__, init_params)
    )

    if state.get("optimizer_state_dict") and hasattr(estimator, "optimizer"):
        try:
            estimator.optimizer.load_state_dict(
                state["optimizer_state_dict"]  # type: ignore[arg-type]
            )
        except Exception:  # noqa: E722
            pass

    estimator._restore_runtime_state(state.get("runtime_state", {}))
    return estimator

save

save(filepath: Union[str, Path]) -> None

Persist the estimator (architecture, weights, optimiser & runtime state).

Parameters:

Name Type Description Default
filepath str | Path

Destination file. Parent directories are created automatically.

required
Source code in deep_river/base.py
def save(self, filepath: Union[str, Path]) -> None:
    """Persist the estimator (architecture, weights, optimiser & runtime state).

    Parameters
    ----------
    filepath : str | Path
        Destination file. Parent directories are created automatically.
    """
    filepath = Path(filepath)
    filepath.parent.mkdir(parents=True, exist_ok=True)

    state = {
        "estimator_class": f"{type(self).__module__}.{type(self).__name__}",
        "init_params": self._get_all_init_params(),
        "model_state_dict": getattr(self.module, "state_dict", lambda: {})(),
        "optimizer_state_dict": getattr(self.optimizer, "state_dict", lambda: {})(),
        "runtime_state": self._get_runtime_state(),
    }

    with open(filepath, "wb") as f:
        pickle.dump(state, f)

score_many

score_many(X: DataFrame) -> ndarray

Returns an anomaly score for the provided batch of examples in the form of the autoencoder's reconstruction error.

Parameters:

Name Type Description Default
x

Input batch of examples.

required

Returns:

Type Description
float

Anomaly scores for the given batch of examples. Larger values indicate more anomalous examples.

Source code in deep_river/anomaly/ae.py
def score_many(self, X: pd.DataFrame) -> np.ndarray:
    """
    Returns an anomaly score for the provided batch of examples in
    the form of the autoencoder's reconstruction error.

    Parameters
    ----------
    x
        Input batch of examples.

    Returns
    -------
    float
        Anomaly scores for the given batch of examples. Larger values
        indicate more anomalous examples.
    """
    self._update_observed_features(X)
    x_t = self._df2tensor(X)

    self.module.eval()
    with torch.inference_mode():
        x_pred = self.module(x_t)
    loss = torch.mean(
        self.loss_func(x_pred, x_t, reduction="none"),
        dim=list(range(1, x_t.dim())),
    )
    score = np.asarray(loss.cpu().detach().tolist())
    return score

score_one

score_one(x: dict) -> float

Returns an anomaly score for the provided example in the form of the autoencoder's reconstruction error.

Parameters:

Name Type Description Default
x dict

Input example.

required

Returns:

Type Description
float

Anomaly score for the given example. Larger values indicate more anomalous examples.

Source code in deep_river/anomaly/ae.py
def score_one(self, x: dict) -> float:
    """
    Returns an anomaly score for the provided example in the form of
    the autoencoder's reconstruction error.

    Parameters
    ----------
    x
        Input example.

    Returns
    -------
    float
        Anomaly score for the given example. Larger values indicate
        more anomalous examples.

    """

    self._update_observed_features(x)
    x_t = self._dict2tensor(x)
    self.module.eval()
    with torch.inference_mode():
        x_pred = self.module(x_t)
    loss = self.loss_func(x_pred, x_t).item()
    return loss

ProbabilityWeightedAutoencoder

ProbabilityWeightedAutoencoder(
    module: Module,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Callable] = "sgd",
    lr: float = 0.001,
    device: str = "cpu",
    seed: int = 42,
    skip_threshold: float = 0.9,
    window_size=250,
    **kwargs
)

Bases: Autoencoder

Methods:

Name Description
clone

Return a fresh estimator instance with (optionally) copied state.

draw

Render a (partial) computational graph of the wrapped model.

learn_one

Performs one step of training with a single example,

load

Load a previously saved estimator.

save

Persist the estimator (architecture, weights, optimiser & runtime state).

score_many

Returns an anomaly score for the provided batch of examples in

score_one

Returns an anomaly score for the provided example in the form of

Source code in deep_river/anomaly/probability_weighted_ae.py
def __init__(
    self,
    module: torch.nn.Module,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Callable] = "sgd",
    lr: float = 1e-3,
    device: str = "cpu",
    seed: int = 42,
    skip_threshold: float = 0.9,
    window_size=250,
    **kwargs,
):
    super().__init__(
        module=module,
        loss_fn=loss_fn,
        optimizer_fn=optimizer_fn,
        lr=lr,
        device=device,
        seed=seed,
        **kwargs,
    )
    self.window_size = window_size
    self.skip_threshold = skip_threshold
    self.rolling_mean = utils.Rolling(stats.Mean(), window_size=window_size)
    self.rolling_var = utils.Rolling(stats.Var(), window_size=window_size)

clone

clone(
    new_params=None,
    include_attributes: bool = False,
    copy_weights: bool = False,
)

Return a fresh estimator instance with (optionally) copied state.

Parameters:

Name Type Description Default
new_params dict | None

Parameter overrides for the cloned instance.

None
include_attributes bool

If True, runtime state (observed features, buffers) is also copied.

False
copy_weights bool

If True, model weights are copied (otherwise the module is re‑initialised).

False
Source code in deep_river/base.py
def clone(
    self,
    new_params=None,
    include_attributes: bool = False,
    copy_weights: bool = False,
):
    """Return a fresh estimator instance with (optionally) copied state.

    Parameters
    ----------
    new_params : dict | None
        Parameter overrides for the cloned instance.
    include_attributes : bool, default=False
        If True, runtime state (observed features, buffers) is also copied.
    copy_weights : bool, default=False
        If True, model weights are copied (otherwise the module is re‑initialised).
    """
    new_params = new_params or {}
    copy_weights = new_params.pop("copy_weights", copy_weights)

    params = {**self._get_all_init_params(), **new_params}

    if "module" not in new_params:
        params["module"] = self._rebuild_module()

    new_est = self.__class__(**self._filter_kwargs(self.__class__.__init__, params))

    if copy_weights and hasattr(self.module, "state_dict"):
        new_est.module.load_state_dict(self.module.state_dict())

    if include_attributes:
        new_est._restore_runtime_state(self._get_runtime_state())

    return new_est

draw

draw()

Render a (partial) computational graph of the wrapped model.

Imports graphviz and torchviz lazily. Raises an informative ImportError if the optional dependencies are not installed.

Source code in deep_river/base.py
def draw(self):  # type: ignore[override]
    """Render a (partial) computational graph of the wrapped model.

    Imports ``graphviz`` and ``torchviz`` lazily. Raises an informative
    ImportError if the optional dependencies are not installed.
    """
    try:  # pragma: no cover
        from torchviz import make_dot  # type: ignore
    except Exception as err:  # noqa: BLE001
        raise ImportError(
            "graphviz and torchviz must be installed to draw the model."
        ) from err

    first_parameter = next(self.module.parameters())
    input_shape = first_parameter.size()
    y_pred = self.module(torch.rand(input_shape))
    return make_dot(y_pred.mean(), params=dict(self.module.named_parameters()))

learn_one

learn_one(x: dict, y: Any = None) -> None

Performs one step of training with a single example, scaling the employed learning rate based on the outlier probability estimate of the input example.

Parameters:

Name Type Description Default
x dict

Input example.

required

Returns:

Type Description
ProbabilityWeightedAutoencoder

The autoencoder itself.

Source code in deep_river/anomaly/probability_weighted_ae.py
def learn_one(self, x: dict, y: Any = None) -> None:
    """
    Performs one step of training with a single example,
    scaling the employed learning rate based on the outlier
    probability estimate of the input example.

    Parameters
    ----------
    x
        Input example.

    Returns
    -------
    ProbabilityWeightedAutoencoder
        The autoencoder itself.
    """

    self._update_observed_features(x)
    x_t = self._dict2tensor(x)

    self.module.train()
    x_pred = self.module(x_t)
    loss = self.loss_func(x_pred, x_t)
    self._apply_loss(loss)

load classmethod

load(filepath: Union[str, Path])

Load a previously saved estimator.

The method reconstructs the estimator class, its wrapped module, optimiser state and runtime information (feature names, buffers, etc.).

Source code in deep_river/base.py
@classmethod
def load(cls, filepath: Union[str, Path]):
    """Load a previously saved estimator.

    The method reconstructs the estimator class, its wrapped module, optimiser
    state and runtime information (feature names, buffers, etc.).
    """
    with open(filepath, "rb") as f:
        state = pickle.load(f)

    estimator_cls = cls._import_from_path(state["estimator_class"])
    init_params = state["init_params"]

    # Rebuild module if needed
    if "module" in init_params and isinstance(init_params["module"], dict):
        module_info = init_params.pop("module")
        module_cls = cls._import_from_path(module_info["class"])
        module = module_cls(
            **cls._filter_kwargs(module_cls.__init__, module_info["kwargs"])
        )
        if state.get("model_state_dict"):
            module.load_state_dict(state["model_state_dict"])
        init_params["module"] = module

    estimator = estimator_cls(
        **cls._filter_kwargs(estimator_cls.__init__, init_params)
    )

    if state.get("optimizer_state_dict") and hasattr(estimator, "optimizer"):
        try:
            estimator.optimizer.load_state_dict(
                state["optimizer_state_dict"]  # type: ignore[arg-type]
            )
        except Exception:  # noqa: E722
            pass

    estimator._restore_runtime_state(state.get("runtime_state", {}))
    return estimator

save

save(filepath: Union[str, Path]) -> None

Persist the estimator (architecture, weights, optimiser & runtime state).

Parameters:

Name Type Description Default
filepath str | Path

Destination file. Parent directories are created automatically.

required
Source code in deep_river/base.py
def save(self, filepath: Union[str, Path]) -> None:
    """Persist the estimator (architecture, weights, optimiser & runtime state).

    Parameters
    ----------
    filepath : str | Path
        Destination file. Parent directories are created automatically.
    """
    filepath = Path(filepath)
    filepath.parent.mkdir(parents=True, exist_ok=True)

    state = {
        "estimator_class": f"{type(self).__module__}.{type(self).__name__}",
        "init_params": self._get_all_init_params(),
        "model_state_dict": getattr(self.module, "state_dict", lambda: {})(),
        "optimizer_state_dict": getattr(self.optimizer, "state_dict", lambda: {})(),
        "runtime_state": self._get_runtime_state(),
    }

    with open(filepath, "wb") as f:
        pickle.dump(state, f)

score_many

score_many(X: DataFrame) -> ndarray

Returns an anomaly score for the provided batch of examples in the form of the autoencoder's reconstruction error.

Parameters:

Name Type Description Default
x

Input batch of examples.

required

Returns:

Type Description
float

Anomaly scores for the given batch of examples. Larger values indicate more anomalous examples.

Source code in deep_river/anomaly/ae.py
def score_many(self, X: pd.DataFrame) -> np.ndarray:
    """
    Returns an anomaly score for the provided batch of examples in
    the form of the autoencoder's reconstruction error.

    Parameters
    ----------
    x
        Input batch of examples.

    Returns
    -------
    float
        Anomaly scores for the given batch of examples. Larger values
        indicate more anomalous examples.
    """
    self._update_observed_features(X)
    x_t = self._df2tensor(X)

    self.module.eval()
    with torch.inference_mode():
        x_pred = self.module(x_t)
    loss = torch.mean(
        self.loss_func(x_pred, x_t, reduction="none"),
        dim=list(range(1, x_t.dim())),
    )
    score = np.asarray(loss.cpu().detach().tolist())
    return score

score_one

score_one(x: dict) -> float

Returns an anomaly score for the provided example in the form of the autoencoder's reconstruction error.

Parameters:

Name Type Description Default
x dict

Input example.

required

Returns:

Type Description
float

Anomaly score for the given example. Larger values indicate more anomalous examples.

Source code in deep_river/anomaly/ae.py
def score_one(self, x: dict) -> float:
    """
    Returns an anomaly score for the provided example in the form of
    the autoencoder's reconstruction error.

    Parameters
    ----------
    x
        Input example.

    Returns
    -------
    float
        Anomaly score for the given example. Larger values indicate
        more anomalous examples.

    """

    self._update_observed_features(x)
    x_t = self._dict2tensor(x)
    self.module.eval()
    with torch.inference_mode():
        x_pred = self.module(x_t)
    loss = self.loss_func(x_pred, x_t).item()
    return loss

RollingAutoencoder

RollingAutoencoder(
    module: Module,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Callable] = "sgd",
    lr: float = 0.001,
    device: str = "cpu",
    seed: int = 42,
    window_size: int = 10,
    append_predict: bool = False,
    **kwargs
)

Bases: RollingDeepEstimator, AnomalyDetector

Rolling window autoencoder for streaming anomaly detection.

Maintains a fixed-size deque of the latest window_size observations and feeds them as a sequence tensor to the wrapped autoencoder module. The anomaly score is the reconstruction error for the current (or most recent) window. This design allows sequence context without retaining the full historical stream.

Parameters:

Name Type Description Default
module Module

Autoencoder (or encoder-only) style module operating on a rolling tensor.

required
loss_fn str | Callable

Loss for reconstruction error measurement.

'mse'
optimizer_fn str | Callable

Optimizer specification.

'sgd'
lr float

Learning rate.

1e-3
device str

Torch device.

'cpu'
seed int

Random seed.

42
window_size int

Number of past samples retained.

10
append_predict bool

If True, the scored sample (during prediction) is appended to the window.

False
**kwargs

Forwarded to :class:~deep_river.base.RollingDeepEstimator.

{}
Notes

The provided module should expect input shape roughly (seq_len, batch=1, n_features) which is what :func:deque2rolling_tensor produces.

Methods:

Name Description
clone

Return a fresh estimator instance with (optionally) copied state.

draw

Render a (partial) computational graph of the wrapped model.

learn_many

Batch update; extends window with rows from X and learns if full.

learn_one

Update model using a single sample appended to the rolling window.

load

Load a previously saved estimator.

save

Persist the estimator (architecture, weights, optimiser & runtime state).

score_many

Return list of reconstruction errors for each row in X.

score_one

Return reconstruction error for current window + candidate sample.

Source code in deep_river/anomaly/rolling_ae.py
def __init__(
    self,
    module: torch.nn.Module,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Callable] = "sgd",
    lr: float = 1e-3,
    device: str = "cpu",
    seed: int = 42,
    window_size: int = 10,
    append_predict: bool = False,
    **kwargs,
):
    super().__init__(
        module=module,
        loss_fn=loss_fn,
        optimizer_fn=optimizer_fn,
        lr=lr,
        device=device,
        seed=seed,
        window_size=window_size,
        append_predict=append_predict,
        **kwargs,
    )

clone

clone(
    new_params=None,
    include_attributes: bool = False,
    copy_weights: bool = False,
)

Return a fresh estimator instance with (optionally) copied state.

Parameters:

Name Type Description Default
new_params dict | None

Parameter overrides for the cloned instance.

None
include_attributes bool

If True, runtime state (observed features, buffers) is also copied.

False
copy_weights bool

If True, model weights are copied (otherwise the module is re‑initialised).

False
Source code in deep_river/base.py
def clone(
    self,
    new_params=None,
    include_attributes: bool = False,
    copy_weights: bool = False,
):
    """Return a fresh estimator instance with (optionally) copied state.

    Parameters
    ----------
    new_params : dict | None
        Parameter overrides for the cloned instance.
    include_attributes : bool, default=False
        If True, runtime state (observed features, buffers) is also copied.
    copy_weights : bool, default=False
        If True, model weights are copied (otherwise the module is re‑initialised).
    """
    new_params = new_params or {}
    copy_weights = new_params.pop("copy_weights", copy_weights)

    params = {**self._get_all_init_params(), **new_params}

    if "module" not in new_params:
        params["module"] = self._rebuild_module()

    new_est = self.__class__(**self._filter_kwargs(self.__class__.__init__, params))

    if copy_weights and hasattr(self.module, "state_dict"):
        new_est.module.load_state_dict(self.module.state_dict())

    if include_attributes:
        new_est._restore_runtime_state(self._get_runtime_state())

    return new_est

draw

draw()

Render a (partial) computational graph of the wrapped model.

Imports graphviz and torchviz lazily. Raises an informative ImportError if the optional dependencies are not installed.

Source code in deep_river/base.py
def draw(self):  # type: ignore[override]
    """Render a (partial) computational graph of the wrapped model.

    Imports ``graphviz`` and ``torchviz`` lazily. Raises an informative
    ImportError if the optional dependencies are not installed.
    """
    try:  # pragma: no cover
        from torchviz import make_dot  # type: ignore
    except Exception as err:  # noqa: BLE001
        raise ImportError(
            "graphviz and torchviz must be installed to draw the model."
        ) from err

    first_parameter = next(self.module.parameters())
    input_shape = first_parameter.size()
    y_pred = self.module(torch.rand(input_shape))
    return make_dot(y_pred.mean(), params=dict(self.module.named_parameters()))

learn_many

learn_many(X: DataFrame, y=None) -> None

Batch update; extends window with rows from X and learns if full.

Parameters:

Name Type Description Default
X DataFrame

DataFrame containing the input features for each sample.

required
y None

Ignored, present for compatibility.

None
Source code in deep_river/anomaly/rolling_ae.py
def learn_many(self, X: pd.DataFrame, y=None) -> None:
    """Batch update; extends window with rows from X and learns if full.

    Parameters
    ----------
    X : pd.DataFrame
        DataFrame containing the input features for each sample.
    y : None
        Ignored, present for compatibility.
    """
    self._update_observed_features(X)

    X = X[list(self.observed_features)]
    self._x_window.extend(X.values.tolist())
    if len(self._x_window) == self.window_size:
        X_t = deque2rolling_tensor(self._x_window, device=self.device)
        self._learn(x=X_t)

learn_one

learn_one(x: dict, y: Any = None) -> None

Update model using a single sample appended to the rolling window.

Parameters:

Name Type Description Default
x dict

Dictionary containing feature name-value pairs for the sample.

required
y Any

Target value (not used in autoencoder training).

None
Source code in deep_river/anomaly/rolling_ae.py
def learn_one(self, x: dict, y: Any = None) -> None:
    """Update model using a single sample appended to the rolling window.

    Parameters
    ----------
    x : dict
        Dictionary containing feature name-value pairs for the sample.
    y : Any, optional
        Target value (not used in autoencoder training).
    """
    self._update_observed_features(x)
    self._x_window.append([x.get(feature, 0) for feature in self.observed_features])

    x_t = deque2rolling_tensor(self._x_window, device=self.device)
    self._learn(x=x_t)

load classmethod

load(filepath: Union[str, Path])

Load a previously saved estimator.

The method reconstructs the estimator class, its wrapped module, optimiser state and runtime information (feature names, buffers, etc.).

Source code in deep_river/base.py
@classmethod
def load(cls, filepath: Union[str, Path]):
    """Load a previously saved estimator.

    The method reconstructs the estimator class, its wrapped module, optimiser
    state and runtime information (feature names, buffers, etc.).
    """
    with open(filepath, "rb") as f:
        state = pickle.load(f)

    estimator_cls = cls._import_from_path(state["estimator_class"])
    init_params = state["init_params"]

    # Rebuild module if needed
    if "module" in init_params and isinstance(init_params["module"], dict):
        module_info = init_params.pop("module")
        module_cls = cls._import_from_path(module_info["class"])
        module = module_cls(
            **cls._filter_kwargs(module_cls.__init__, module_info["kwargs"])
        )
        if state.get("model_state_dict"):
            module.load_state_dict(state["model_state_dict"])
        init_params["module"] = module

    estimator = estimator_cls(
        **cls._filter_kwargs(estimator_cls.__init__, init_params)
    )

    if state.get("optimizer_state_dict") and hasattr(estimator, "optimizer"):
        try:
            estimator.optimizer.load_state_dict(
                state["optimizer_state_dict"]  # type: ignore[arg-type]
            )
        except Exception:  # noqa: E722
            pass

    estimator._restore_runtime_state(state.get("runtime_state", {}))
    return estimator

save

save(filepath: Union[str, Path]) -> None

Persist the estimator (architecture, weights, optimiser & runtime state).

Parameters:

Name Type Description Default
filepath str | Path

Destination file. Parent directories are created automatically.

required
Source code in deep_river/base.py
def save(self, filepath: Union[str, Path]) -> None:
    """Persist the estimator (architecture, weights, optimiser & runtime state).

    Parameters
    ----------
    filepath : str | Path
        Destination file. Parent directories are created automatically.
    """
    filepath = Path(filepath)
    filepath.parent.mkdir(parents=True, exist_ok=True)

    state = {
        "estimator_class": f"{type(self).__module__}.{type(self).__name__}",
        "init_params": self._get_all_init_params(),
        "model_state_dict": getattr(self.module, "state_dict", lambda: {})(),
        "optimizer_state_dict": getattr(self.optimizer, "state_dict", lambda: {})(),
        "runtime_state": self._get_runtime_state(),
    }

    with open(filepath, "wb") as f:
        pickle.dump(state, f)

score_many

score_many(X: DataFrame) -> List[Any]

Return list of reconstruction errors for each row in X.

If the window is not yet full, zeros are returned for alignment.

Parameters:

Name Type Description Default
X DataFrame

DataFrame containing the input features for each sample.

required

Returns:

Type Description
List[float]

List of computed anomaly scores (reconstruction errors) for each sample in X.

Source code in deep_river/anomaly/rolling_ae.py
def score_many(self, X: pd.DataFrame) -> List[Any]:
    """Return list of reconstruction errors for each row in X.

    If the window is not yet full, zeros are returned for alignment.

    Parameters
    ----------
    X : pd.DataFrame
        DataFrame containing the input features for each sample.

    Returns
    -------
    List[float]
        List of computed anomaly scores (reconstruction errors) for each sample in X.
    """
    return [self.score_one(row) for row in X.to_dict(orient="records")]

score_one

score_one(x: dict) -> float

Return reconstruction error for current window + candidate sample.

Parameters:

Name Type Description Default
x dict

Dictionary containing feature name-value pairs for the candidate sample.

required

Returns:

Type Description
float

Computed anomaly score (reconstruction error).

Source code in deep_river/anomaly/rolling_ae.py
def score_one(self, x: dict) -> float:
    """Return reconstruction error for current window + candidate sample.

    Parameters
    ----------
    x : dict
        Dictionary containing feature name-value pairs for the candidate sample.

    Returns
    -------
    float
        Computed anomaly score (reconstruction error).
    """
    res = 0.0
    self._update_observed_features(x)
    if len(self._x_window) == self.window_size:
        x_win = self._x_window.copy()
        x_win.append([x.get(feature, 0) for feature in self.observed_features])
        x_t = deque2rolling_tensor(x_win, device=self.device)
        self.module.eval()
        with torch.inference_mode():
            x_pred = self.module(x_t)
        loss = self.loss_func(x_pred, x_t)
        res = loss.item()

    if self.append_predict:
        self._x_window.append(
            [x.get(feature, 0) for feature in self.observed_features]
        )
    return res