Save and Load
Use save and load when you want to persist a fitted PanelMMM and rebuild it
later without redefining the whole model configuration in code.
Basic round trip
The standard workflow is:
mmm.fit(
X,
y,
draws=500,
tune=500,
chains=2,
progressbar=False,
random_seed=42,
)
mmm.save("mmm.nc")
loaded = PanelMMM.load("mmm.nc")
save() writes the model’s InferenceData to NetCDF. load() reads that file,
recreates the PanelMMM configuration from stored metadata, restores
loaded.idata, and rebuilds the PyMC graph from the saved training data.
What AMMM3 stores
AMMM3 relies on more than the posterior draws for a full round trip.
| Stored item | Why it matters |
|---|---|
posterior and other InferenceData groups | Preserve sampled results |
fit_data | Rebuild the model graph with the original training data |
idata.attrs | Reconstruct PanelMMM init kwargs and validate compatibility |
The stored attrs include both the shared model metadata and PanelMMM-specific
configuration such as:
date_columnchannel_columnstarget_columntarget_typedimscontrol_columnscontrol_impactsadstockandsaturationadstock_firstyearly_seasonalitytime_varying_interceptandtime_varying_mediascalingmodel_configsampler_config- serialised
mu_effects
save() behaviour
save(fname, **kwargs) is a thin wrapper over self.idata.to_netcdf(...).
Important constraints:
- the model must already be fitted
self.idatamust contain aposteriorgroup- any extra kwargs are passed directly to
InferenceData.to_netcdf(...)
If you call save() before fitting, AMMM3 raises:
RuntimeError: The model hasn't been fit yet, call .fit() first
load() and compatibility checks
By default, PanelMMM.load(...) validates that the saved file matches the
current model class and configuration:
loaded = PanelMMM.load("mmm.nc", check=True)
With check=True, AMMM3 verifies:
- the saved model version
- the saved model id derived from the serialised configuration
If those checks fail, AMMM3 raises DifferentModelError.
If you need to bypass those checks, you can set check=False:
loaded = PanelMMM.load("mmm.nc", check=False)
Use that only when you understand why the saved metadata does not match.
Load from an in-memory InferenceData
If you already have an InferenceData object, use load_from_idata(...)
instead of saving to disk first:
loaded = PanelMMM.load_from_idata(idata, check=True)
This is the same round-trip path that load() uses internally after reading
the NetCDF file.
Where build_from_idata() fits
build_from_idata(idata) is the lower-level rebuild step. It:
- restores supported serialised
mu_effects - reads
idata.fit_data - splits that saved training data back into
Xandy - rebuilds the PyMC graph
You usually do not need to call build_from_idata() yourself because
load() and load_from_idata() already do it.
The rebuilt graph keeps the training-data record described in
Fitting an existing graph again.
Calling fit() on a loaded model is accepted when the supplied X and y
equal the saved training data. Different data raise ValueError before
sampling; create a new model instance to fit them.
Round-trip limitations
Not every fitted object can be restored fully.
Event payload requirements
Current EventAdditiveEffect serialisation stores the event DataFrame and
the effect specification. PanelMMM.load(...) restores both. Older payloads
that lack df_events or effect raise ValueError during restoration.
Reconstruct those older models from their original inputs before saving them
with the current format.
Do not drop fit_data if you want to reload
Because rebuild uses idata.fit_data, do not save a partial file that omits
that group if you want to call PanelMMM.load(...) later.
For example, this is valid NetCDF output:
mmm.save("posterior_only.nc", groups=["posterior"])
But it is not a full PanelMMM round-trip artefact, because the saved file no
longer includes the training data needed for build_from_idata(...).
Practical advice
- Use the default
save()behaviour for round trips. - Keep
check=Trueunless you have a specific compatibility reason not to. - Prefer
PanelMMM.load(...)over loading NetCDF manually. - Retain the original event inputs when working with older saved payloads.
Next steps
After loading a model, you can go straight to posterior predictive sampling,
diagnostics, decomposition, or optimisation using the restored idata and
rebuilt graph.