Source code for setu.io
"""Serialization API for saving and loading trained estimators."""
from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING, TypeVar
import equinox as eqx
if TYPE_CHECKING:
from setu.discrete_nle import DiscreteNLE
from setu.mixed_nle import MixedNLE
from setu.nle import NLE
T = TypeVar("T")
[docs]
def save_estimator(estimator: NLE | MixedNLE | DiscreteNLE, path: str | Path) -> None:
"""Save a trained NLE, MixedNLE, or DiscreteNLE to disk.
Uses equinox serialization to save all array leaves of the estimator pytree.
Args:
estimator: Trained NLE or MixedNLE instance.
path: File path to save to (e.g., "model.eqx").
Example:
>>> nle = create_nle(x_dim=3, theta_dim=3, key=key)
>>> result = fit_nle(nle, dataset, key=key)
>>> save_estimator(result.nle, "trained_nle.eqx")
"""
eqx.tree_serialise_leaves(str(path), estimator)
[docs]
def load_estimator(path: str | Path, like: T) -> T:
"""Load a trained NLE, MixedNLE, or DiscreteNLE from disk.
Uses equinox deserialization. The `like` parameter provides the pytree
structure for deserialization -- it must be an estimator with the **exact
same structure** as the saved model. This means:
- Same architecture (x_dim, theta_dim, flow_type, hidden_dims, n_layers)
- Same fitted state: if the saved model was trained (has transforms fitted),
`like` must also have fitted transforms. The simplest way to ensure this
is to train a model with the same architecture on dummy data, or to keep
a copy of the untrained-but-fitted template.
For convenience, use the pattern: save the trained estimator, and when
loading, create a new estimator with the same architecture and train it
briefly (even 1 epoch) to match the pytree structure.
Args:
path: File path to load from.
like: An estimator with matching pytree structure. Must have the same
hyperparameters and fitted state as the saved model.
Returns:
Estimator with weights loaded from disk.
Example:
>>> # Save after training
>>> save_estimator(result.nle, "trained_nle.eqx")
>>>
>>> # Load: create matching template (train briefly on dummy data)
>>> template_nle = create_nle(x_dim=3, theta_dim=3, key=key)
>>> template_result = fit_nle(
... template_nle, dummy_dataset, max_epochs=1, key=key
... )
>>> loaded = load_estimator("trained_nle.eqx", like=template_result.nle)
"""
return eqx.tree_deserialise_leaves(str(path), like)