Skip to content

zoo

Classes:

Name Description
GRUForecaster

Autoregressive forecaster backed by torch.nn.GRU.

LSTMForecaster

Autoregressive forecaster backed by torch.nn.LSTM.

LinearForecaster

Autoregressive linear forecaster with optional exogenous features.

LiquidForecaster

Autoregressive forecaster backed by closed-form liquid recurrent cells.

MLPForecaster

Autoregressive multi-layer perceptron forecaster.

NBEATSForecaster

Compact N-BEATS-style residual MLP forecaster for online point forecasts.

RNNForecaster

Autoregressive forecaster backed by torch.nn.RNN.

GRUForecaster

GRUForecaster(
    n_features: int = 0,
    window_size: int = 10,
    hidden_size: int = 16,
    num_layers: int = 1,
    dropout: float = 0.0,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Type[Optimizer]] = "adam",
    lr: float = 0.001,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    gradient_clip_value: float | None = 1.0,
    **kwargs
)

Bases: DeepForecaster

Autoregressive forecaster backed by torch.nn.GRU.

Methods:

Name Description
clone

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

draw

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

forecast

Forecast horizon steps ahead using autoregressive rollouts.

learn_one

Update the model with one target and optional exogenous features.

load

Load a previously saved estimator.

save

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

Source code in deep_river/forecasting/zoo.py
def __init__(
    self,
    n_features: int = 0,
    window_size: int = 10,
    hidden_size: int = 16,
    num_layers: int = 1,
    dropout: float = 0.0,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Type[optim.Optimizer]] = "adam",
    lr: float = 1e-3,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    gradient_clip_value: float | None = 1.0,
    **kwargs,
):
    self.n_features = n_features
    self.hidden_size = hidden_size
    self.num_layers = num_layers
    self.dropout = dropout
    module = GRUForecaster.GRUModule(
        input_size=1 + n_features,
        hidden_size=hidden_size,
        num_layers=num_layers,
        dropout=dropout,
    )
    kwargs.pop("module", None)
    super().__init__(
        module=module,
        loss_fn=loss_fn,
        optimizer_fn=optimizer_fn,
        lr=lr,
        is_feature_incremental=is_feature_incremental,
        device=device,
        seed=seed,
        window_size=window_size,
        is_sequence_model=True,
        gradient_clip_value=gradient_clip_value,
        **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()))

forecast

forecast(
    horizon: int, xs: list[dict] | None = None
) -> list

Forecast horizon steps ahead using autoregressive rollouts.

Source code in deep_river/forecasting/forecaster.py
def forecast(self, horizon: int, xs: list[dict] | None = None) -> list:
    """Forecast ``horizon`` steps ahead using autoregressive rollouts."""
    if horizon < 0:
        raise ValueError("horizon must be non-negative")
    if xs is None:
        xs = [{} for _ in range(horizon)]
    if len(xs) != horizon:
        raise ValueError(
            "the length of xs should be equal to the specified horizon"
        )

    y_window = collections.deque(self._y_window, maxlen=self.window_size)
    forecasts = []

    self.module.eval()
    with torch.inference_mode():
        for x in xs:
            x = x or {}
            self._update_observed_features(x)
            x_t = self._make_input_tensor(y_window, x)
            y_pred = self.module(x_t)
            if isinstance(y_pred, torch.Tensor):
                y_pred = y_pred.detach().view(-1)[-1].cpu().item()
            else:
                y_pred = float(y_pred)
            forecasts.append(y_pred)
            y_window.append(float(y_pred))

    return forecasts

learn_one

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

Update the model with one target and optional exogenous features.

Source code in deep_river/forecasting/forecaster.py
def learn_one(self, y: float, x: dict | None = None) -> None:
    """Update the model with one target and optional exogenous features."""
    x = x or {}
    self._update_observed_features(x)
    x_t = self._make_input_tensor(self._y_window, x)
    y_t = torch.tensor([[y]], dtype=torch.float32, device=self.device)
    self._learn(x_t, y_t)
    self._y_window.append(float(y))

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)

LSTMForecaster

LSTMForecaster(
    n_features: int = 0,
    window_size: int = 10,
    hidden_size: int = 16,
    num_layers: int = 1,
    dropout: float = 0.0,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Type[Optimizer]] = "adam",
    lr: float = 0.001,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    gradient_clip_value: float | None = 1.0,
    **kwargs
)

Bases: DeepForecaster

Autoregressive forecaster backed by torch.nn.LSTM.

Methods:

Name Description
clone

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

draw

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

forecast

Forecast horizon steps ahead using autoregressive rollouts.

learn_one

Update the model with one target and optional exogenous features.

load

Load a previously saved estimator.

save

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

Source code in deep_river/forecasting/zoo.py
def __init__(
    self,
    n_features: int = 0,
    window_size: int = 10,
    hidden_size: int = 16,
    num_layers: int = 1,
    dropout: float = 0.0,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Type[optim.Optimizer]] = "adam",
    lr: float = 1e-3,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    gradient_clip_value: float | None = 1.0,
    **kwargs,
):
    self.n_features = n_features
    self.hidden_size = hidden_size
    self.num_layers = num_layers
    self.dropout = dropout
    module = LSTMForecaster.LSTMModule(
        input_size=1 + n_features,
        hidden_size=hidden_size,
        num_layers=num_layers,
        dropout=dropout,
    )
    kwargs.pop("module", None)
    super().__init__(
        module=module,
        loss_fn=loss_fn,
        optimizer_fn=optimizer_fn,
        lr=lr,
        is_feature_incremental=is_feature_incremental,
        device=device,
        seed=seed,
        window_size=window_size,
        is_sequence_model=True,
        gradient_clip_value=gradient_clip_value,
        **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()))

forecast

forecast(
    horizon: int, xs: list[dict] | None = None
) -> list

Forecast horizon steps ahead using autoregressive rollouts.

Source code in deep_river/forecasting/forecaster.py
def forecast(self, horizon: int, xs: list[dict] | None = None) -> list:
    """Forecast ``horizon`` steps ahead using autoregressive rollouts."""
    if horizon < 0:
        raise ValueError("horizon must be non-negative")
    if xs is None:
        xs = [{} for _ in range(horizon)]
    if len(xs) != horizon:
        raise ValueError(
            "the length of xs should be equal to the specified horizon"
        )

    y_window = collections.deque(self._y_window, maxlen=self.window_size)
    forecasts = []

    self.module.eval()
    with torch.inference_mode():
        for x in xs:
            x = x or {}
            self._update_observed_features(x)
            x_t = self._make_input_tensor(y_window, x)
            y_pred = self.module(x_t)
            if isinstance(y_pred, torch.Tensor):
                y_pred = y_pred.detach().view(-1)[-1].cpu().item()
            else:
                y_pred = float(y_pred)
            forecasts.append(y_pred)
            y_window.append(float(y_pred))

    return forecasts

learn_one

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

Update the model with one target and optional exogenous features.

Source code in deep_river/forecasting/forecaster.py
def learn_one(self, y: float, x: dict | None = None) -> None:
    """Update the model with one target and optional exogenous features."""
    x = x or {}
    self._update_observed_features(x)
    x_t = self._make_input_tensor(self._y_window, x)
    y_t = torch.tensor([[y]], dtype=torch.float32, device=self.device)
    self._learn(x_t, y_t)
    self._y_window.append(float(y))

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)

LinearForecaster

LinearForecaster(
    n_features: int = 0,
    window_size: int = 10,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Type[Optimizer]] = "sgd",
    lr: float = 0.001,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    gradient_clip_value: float | None = 1.0,
    **kwargs
)

Bases: DeepForecaster

Autoregressive linear forecaster with optional exogenous features.

Methods:

Name Description
clone

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

draw

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

forecast

Forecast horizon steps ahead using autoregressive rollouts.

learn_one

Update the model with one target and optional exogenous features.

load

Load a previously saved estimator.

save

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

Source code in deep_river/forecasting/zoo.py
def __init__(
    self,
    n_features: int = 0,
    window_size: int = 10,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Type[optim.Optimizer]] = "sgd",
    lr: float = 1e-3,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    gradient_clip_value: float | None = 1.0,
    **kwargs,
):
    self.n_features = n_features
    module = LinearForecaster.LinearModule(input_size=window_size + n_features)
    kwargs.pop("module", None)
    super().__init__(
        module=module,
        loss_fn=loss_fn,
        optimizer_fn=optimizer_fn,
        lr=lr,
        is_feature_incremental=is_feature_incremental,
        device=device,
        seed=seed,
        window_size=window_size,
        is_sequence_model=False,
        gradient_clip_value=gradient_clip_value,
        **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()))

forecast

forecast(
    horizon: int, xs: list[dict] | None = None
) -> list

Forecast horizon steps ahead using autoregressive rollouts.

Source code in deep_river/forecasting/forecaster.py
def forecast(self, horizon: int, xs: list[dict] | None = None) -> list:
    """Forecast ``horizon`` steps ahead using autoregressive rollouts."""
    if horizon < 0:
        raise ValueError("horizon must be non-negative")
    if xs is None:
        xs = [{} for _ in range(horizon)]
    if len(xs) != horizon:
        raise ValueError(
            "the length of xs should be equal to the specified horizon"
        )

    y_window = collections.deque(self._y_window, maxlen=self.window_size)
    forecasts = []

    self.module.eval()
    with torch.inference_mode():
        for x in xs:
            x = x or {}
            self._update_observed_features(x)
            x_t = self._make_input_tensor(y_window, x)
            y_pred = self.module(x_t)
            if isinstance(y_pred, torch.Tensor):
                y_pred = y_pred.detach().view(-1)[-1].cpu().item()
            else:
                y_pred = float(y_pred)
            forecasts.append(y_pred)
            y_window.append(float(y_pred))

    return forecasts

learn_one

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

Update the model with one target and optional exogenous features.

Source code in deep_river/forecasting/forecaster.py
def learn_one(self, y: float, x: dict | None = None) -> None:
    """Update the model with one target and optional exogenous features."""
    x = x or {}
    self._update_observed_features(x)
    x_t = self._make_input_tensor(self._y_window, x)
    y_t = torch.tensor([[y]], dtype=torch.float32, device=self.device)
    self._learn(x_t, y_t)
    self._y_window.append(float(y))

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)

LiquidForecaster

LiquidForecaster(
    n_features: int = 0,
    window_size: int = 10,
    hidden_size: int = 16,
    num_layers: int = 1,
    dropout: float = 0.0,
    time_delta: float = 1.0,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Type[Optimizer]] = "adam",
    lr: float = 0.001,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    gradient_clip_value: float | None = 1.0,
    **kwargs
)

Bases: DeepForecaster

Autoregressive forecaster backed by closed-form liquid recurrent cells.

The recurrent state follows a fixed-step liquid update where each hidden unit learns a positive time constant. time_delta is constant across all steps, matching regularly sampled time series.

Methods:

Name Description
clone

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

draw

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

forecast

Forecast horizon steps ahead using autoregressive rollouts.

learn_one

Update the model with one target and optional exogenous features.

load

Load a previously saved estimator.

save

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

Source code in deep_river/forecasting/zoo.py
def __init__(
    self,
    n_features: int = 0,
    window_size: int = 10,
    hidden_size: int = 16,
    num_layers: int = 1,
    dropout: float = 0.0,
    time_delta: float = 1.0,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Type[optim.Optimizer]] = "adam",
    lr: float = 1e-3,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    gradient_clip_value: float | None = 1.0,
    **kwargs,
):
    if is_feature_incremental:
        raise ValueError("LiquidForecaster does not support feature incrementality")
    if num_layers < 1:
        raise ValueError("num_layers must be at least 1")
    if time_delta <= 0:
        raise ValueError("time_delta must be positive")

    self.n_features = n_features
    self.hidden_size = hidden_size
    self.num_layers = num_layers
    self.dropout = dropout
    self.time_delta = time_delta
    module = LiquidForecaster.LiquidModule(
        input_size=1 + n_features,
        hidden_size=hidden_size,
        num_layers=num_layers,
        dropout=dropout,
        time_delta=time_delta,
    )
    kwargs.pop("module", None)
    super().__init__(
        module=module,
        loss_fn=loss_fn,
        optimizer_fn=optimizer_fn,
        lr=lr,
        is_feature_incremental=is_feature_incremental,
        device=device,
        seed=seed,
        window_size=window_size,
        is_sequence_model=True,
        gradient_clip_value=gradient_clip_value,
        **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()))

forecast

forecast(
    horizon: int, xs: list[dict] | None = None
) -> list

Forecast horizon steps ahead using autoregressive rollouts.

Source code in deep_river/forecasting/forecaster.py
def forecast(self, horizon: int, xs: list[dict] | None = None) -> list:
    """Forecast ``horizon`` steps ahead using autoregressive rollouts."""
    if horizon < 0:
        raise ValueError("horizon must be non-negative")
    if xs is None:
        xs = [{} for _ in range(horizon)]
    if len(xs) != horizon:
        raise ValueError(
            "the length of xs should be equal to the specified horizon"
        )

    y_window = collections.deque(self._y_window, maxlen=self.window_size)
    forecasts = []

    self.module.eval()
    with torch.inference_mode():
        for x in xs:
            x = x or {}
            self._update_observed_features(x)
            x_t = self._make_input_tensor(y_window, x)
            y_pred = self.module(x_t)
            if isinstance(y_pred, torch.Tensor):
                y_pred = y_pred.detach().view(-1)[-1].cpu().item()
            else:
                y_pred = float(y_pred)
            forecasts.append(y_pred)
            y_window.append(float(y_pred))

    return forecasts

learn_one

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

Update the model with one target and optional exogenous features.

Source code in deep_river/forecasting/forecaster.py
def learn_one(self, y: float, x: dict | None = None) -> None:
    """Update the model with one target and optional exogenous features."""
    x = x or {}
    self._update_observed_features(x)
    x_t = self._make_input_tensor(self._y_window, x)
    y_t = torch.tensor([[y]], dtype=torch.float32, device=self.device)
    self._learn(x_t, y_t)
    self._y_window.append(float(y))

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)

MLPForecaster

MLPForecaster(
    n_features: int = 0,
    window_size: int = 10,
    n_width: int = 16,
    n_layers: int = 2,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Type[Optimizer]] = "adam",
    lr: float = 0.001,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    gradient_clip_value: float | None = 1.0,
    **kwargs
)

Bases: DeepForecaster

Autoregressive multi-layer perceptron forecaster.

Methods:

Name Description
clone

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

draw

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

forecast

Forecast horizon steps ahead using autoregressive rollouts.

learn_one

Update the model with one target and optional exogenous features.

load

Load a previously saved estimator.

save

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

Source code in deep_river/forecasting/zoo.py
def __init__(
    self,
    n_features: int = 0,
    window_size: int = 10,
    n_width: int = 16,
    n_layers: int = 2,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Type[optim.Optimizer]] = "adam",
    lr: float = 1e-3,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    gradient_clip_value: float | None = 1.0,
    **kwargs,
):
    self.n_features = n_features
    self.n_width = n_width
    self.n_layers = n_layers
    module = MLPForecaster.MLPModule(
        input_size=window_size + n_features,
        n_width=n_width,
        n_layers=n_layers,
    )
    kwargs.pop("module", None)
    super().__init__(
        module=module,
        loss_fn=loss_fn,
        optimizer_fn=optimizer_fn,
        lr=lr,
        is_feature_incremental=is_feature_incremental,
        device=device,
        seed=seed,
        window_size=window_size,
        is_sequence_model=False,
        gradient_clip_value=gradient_clip_value,
        **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()))

forecast

forecast(
    horizon: int, xs: list[dict] | None = None
) -> list

Forecast horizon steps ahead using autoregressive rollouts.

Source code in deep_river/forecasting/forecaster.py
def forecast(self, horizon: int, xs: list[dict] | None = None) -> list:
    """Forecast ``horizon`` steps ahead using autoregressive rollouts."""
    if horizon < 0:
        raise ValueError("horizon must be non-negative")
    if xs is None:
        xs = [{} for _ in range(horizon)]
    if len(xs) != horizon:
        raise ValueError(
            "the length of xs should be equal to the specified horizon"
        )

    y_window = collections.deque(self._y_window, maxlen=self.window_size)
    forecasts = []

    self.module.eval()
    with torch.inference_mode():
        for x in xs:
            x = x or {}
            self._update_observed_features(x)
            x_t = self._make_input_tensor(y_window, x)
            y_pred = self.module(x_t)
            if isinstance(y_pred, torch.Tensor):
                y_pred = y_pred.detach().view(-1)[-1].cpu().item()
            else:
                y_pred = float(y_pred)
            forecasts.append(y_pred)
            y_window.append(float(y_pred))

    return forecasts

learn_one

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

Update the model with one target and optional exogenous features.

Source code in deep_river/forecasting/forecaster.py
def learn_one(self, y: float, x: dict | None = None) -> None:
    """Update the model with one target and optional exogenous features."""
    x = x or {}
    self._update_observed_features(x)
    x_t = self._make_input_tensor(self._y_window, x)
    y_t = torch.tensor([[y]], dtype=torch.float32, device=self.device)
    self._learn(x_t, y_t)
    self._y_window.append(float(y))

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)

NBEATSForecaster

NBEATSForecaster(
    n_features: int = 0,
    window_size: int = 10,
    n_width: int = 32,
    n_layers: int = 2,
    n_blocks: int = 2,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Type[Optimizer]] = "adam",
    lr: float = 0.001,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    gradient_clip_value: float | None = 1.0,
    **kwargs
)

Bases: DeepForecaster

Compact N-BEATS-style residual MLP forecaster for online point forecasts.

Methods:

Name Description
clone

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

draw

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

forecast

Forecast horizon steps ahead using autoregressive rollouts.

learn_one

Update the model with one target and optional exogenous features.

load

Load a previously saved estimator.

save

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

Source code in deep_river/forecasting/zoo.py
def __init__(
    self,
    n_features: int = 0,
    window_size: int = 10,
    n_width: int = 32,
    n_layers: int = 2,
    n_blocks: int = 2,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Type[optim.Optimizer]] = "adam",
    lr: float = 1e-3,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    gradient_clip_value: float | None = 1.0,
    **kwargs,
):
    if is_feature_incremental:
        raise ValueError("NBEATSForecaster does not support feature incrementality")

    self.n_features = n_features
    self.n_width = n_width
    self.n_layers = n_layers
    self.n_blocks = n_blocks
    module = NBEATSForecaster.NBEATSModule(
        input_size=window_size + n_features,
        n_width=n_width,
        n_layers=n_layers,
        n_blocks=n_blocks,
    )
    kwargs.pop("module", None)
    super().__init__(
        module=module,
        loss_fn=loss_fn,
        optimizer_fn=optimizer_fn,
        lr=lr,
        is_feature_incremental=is_feature_incremental,
        device=device,
        seed=seed,
        window_size=window_size,
        is_sequence_model=False,
        gradient_clip_value=gradient_clip_value,
        **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()))

forecast

forecast(
    horizon: int, xs: list[dict] | None = None
) -> list

Forecast horizon steps ahead using autoregressive rollouts.

Source code in deep_river/forecasting/forecaster.py
def forecast(self, horizon: int, xs: list[dict] | None = None) -> list:
    """Forecast ``horizon`` steps ahead using autoregressive rollouts."""
    if horizon < 0:
        raise ValueError("horizon must be non-negative")
    if xs is None:
        xs = [{} for _ in range(horizon)]
    if len(xs) != horizon:
        raise ValueError(
            "the length of xs should be equal to the specified horizon"
        )

    y_window = collections.deque(self._y_window, maxlen=self.window_size)
    forecasts = []

    self.module.eval()
    with torch.inference_mode():
        for x in xs:
            x = x or {}
            self._update_observed_features(x)
            x_t = self._make_input_tensor(y_window, x)
            y_pred = self.module(x_t)
            if isinstance(y_pred, torch.Tensor):
                y_pred = y_pred.detach().view(-1)[-1].cpu().item()
            else:
                y_pred = float(y_pred)
            forecasts.append(y_pred)
            y_window.append(float(y_pred))

    return forecasts

learn_one

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

Update the model with one target and optional exogenous features.

Source code in deep_river/forecasting/forecaster.py
def learn_one(self, y: float, x: dict | None = None) -> None:
    """Update the model with one target and optional exogenous features."""
    x = x or {}
    self._update_observed_features(x)
    x_t = self._make_input_tensor(self._y_window, x)
    y_t = torch.tensor([[y]], dtype=torch.float32, device=self.device)
    self._learn(x_t, y_t)
    self._y_window.append(float(y))

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)

RNNForecaster

RNNForecaster(
    n_features: int = 0,
    window_size: int = 10,
    hidden_size: int = 16,
    num_layers: int = 1,
    nonlinearity: str = "tanh",
    dropout: float = 0.0,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Type[Optimizer]] = "adam",
    lr: float = 0.001,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    gradient_clip_value: float | None = 1.0,
    **kwargs
)

Bases: DeepForecaster

Autoregressive forecaster backed by torch.nn.RNN.

Methods:

Name Description
clone

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

draw

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

forecast

Forecast horizon steps ahead using autoregressive rollouts.

learn_one

Update the model with one target and optional exogenous features.

load

Load a previously saved estimator.

save

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

Source code in deep_river/forecasting/zoo.py
def __init__(
    self,
    n_features: int = 0,
    window_size: int = 10,
    hidden_size: int = 16,
    num_layers: int = 1,
    nonlinearity: str = "tanh",
    dropout: float = 0.0,
    loss_fn: Union[str, Callable] = "mse",
    optimizer_fn: Union[str, Type[optim.Optimizer]] = "adam",
    lr: float = 1e-3,
    is_feature_incremental: bool = False,
    device: str = "cpu",
    seed: int = 42,
    gradient_clip_value: float | None = 1.0,
    **kwargs,
):
    self.n_features = n_features
    self.hidden_size = hidden_size
    self.num_layers = num_layers
    self.nonlinearity = nonlinearity
    self.dropout = dropout
    module = RNNForecaster.RNNModule(
        input_size=1 + n_features,
        hidden_size=hidden_size,
        num_layers=num_layers,
        nonlinearity=nonlinearity,
        dropout=dropout,
    )
    kwargs.pop("module", None)
    super().__init__(
        module=module,
        loss_fn=loss_fn,
        optimizer_fn=optimizer_fn,
        lr=lr,
        is_feature_incremental=is_feature_incremental,
        device=device,
        seed=seed,
        window_size=window_size,
        is_sequence_model=True,
        gradient_clip_value=gradient_clip_value,
        **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()))

forecast

forecast(
    horizon: int, xs: list[dict] | None = None
) -> list

Forecast horizon steps ahead using autoregressive rollouts.

Source code in deep_river/forecasting/forecaster.py
def forecast(self, horizon: int, xs: list[dict] | None = None) -> list:
    """Forecast ``horizon`` steps ahead using autoregressive rollouts."""
    if horizon < 0:
        raise ValueError("horizon must be non-negative")
    if xs is None:
        xs = [{} for _ in range(horizon)]
    if len(xs) != horizon:
        raise ValueError(
            "the length of xs should be equal to the specified horizon"
        )

    y_window = collections.deque(self._y_window, maxlen=self.window_size)
    forecasts = []

    self.module.eval()
    with torch.inference_mode():
        for x in xs:
            x = x or {}
            self._update_observed_features(x)
            x_t = self._make_input_tensor(y_window, x)
            y_pred = self.module(x_t)
            if isinstance(y_pred, torch.Tensor):
                y_pred = y_pred.detach().view(-1)[-1].cpu().item()
            else:
                y_pred = float(y_pred)
            forecasts.append(y_pred)
            y_window.append(float(y_pred))

    return forecasts

learn_one

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

Update the model with one target and optional exogenous features.

Source code in deep_river/forecasting/forecaster.py
def learn_one(self, y: float, x: dict | None = None) -> None:
    """Update the model with one target and optional exogenous features."""
    x = x or {}
    self._update_observed_features(x)
    x_t = self._make_input_tensor(self._y_window, x)
    y_t = torch.tensor([[y]], dtype=torch.float32, device=self.device)
    self._learn(x_t, y_t)
    self._y_window.append(float(y))

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)