Re-fitting a GAM every time you need a prediction is wasteful and fragile. Whittaker provides save_gam() and load_gam() to persist a fitted model to a compact .npz archive. The loaded model is fully functional: predict(), summary(), and check() all work immediately without re-fitting.
Fit and save
Fit a Gamma GAM on the wages dataset.
import whittaker as wk
# Load dataset and fit Gamma GAM
data = wk.load_dataset("wages")
model = wk.GAM("wage ~ s(age) + s(experience)", family=wk.Gamma()).fit(data)
model.summary()
GAM fit summary
============================================================
Formula: wage ~ s(age) + s(experience)
Family: Gamma(link='log')
Inference: GCV
Observations: 800
Coefficients: 19
Parametric coefficients:
Term Estimate Std.Err t value p-value
------------------------ ---------- ---------- ---------- ----------
(Intercept) 3.7109 0.0084 440.686 < 1e-16
Approximate significance of smooth terms:
Term EDF Ref.df Chi.sq p-value
------------------------ ------ ------ ---------- ----------
s(age) 3.23 4 2473.551 < 1e-16
s(experience) 2.82 3 177.907 < 1e-16
Total EDF: 7.05
Scale est: 0.056726
Deviance: 44.9806
Null dev: 205.9584
Dev. expl: 78.2%
GCV score: 0.057230
AIC: 5881.68
BIC: 5914.71
Write the fitted model to disk as a .npz archive.
wk.save_gam(model, "wages_model.npz")
The .npz format is a NumPy archive. This is a single compressed file, it has no external dependencies, and it is small enough to commit to a repository or attach to a release.
Load and predict
The load_gam() function reconstructs the fitted model from the archive. No training data is required at load time.
import numpy as np
loaded = wk.load_gam("wages_model.npz")
Verify the loaded model preserved the original fit by comparing the total EDF.
The values are identical, confirming the archive captured all post-fit state. Now generate predictions from the loaded model for a handful of new observations.
# Define new observations and predict
new_data = {
"age": np.array([25, 35, 45, 55]),
"experience": np.array([3, 10, 18, 25]),
}
preds = loaded.predict(new_data)
array([20.68, 39.67, 62.44, 77.77])
Confirm the predictions are numerically identical to those from the original model.
# Confirm predictions match original model
orig_preds = model.predict(new_data)
np.allclose(orig_preds.values, preds.values)
What is preserved
The .npz archive captures everything needed for post-fit operations:
- Formula and family: the model specification, including the link function
- Coefficients: the fitted parameter vector
- Smoothing parameters: the selected λ values
- Basis state: knot locations, penalty matrices, and basis type for each smooth
- Training statistics: EDF, deviance explained, scale estimate, convergence flag
Nothing from the training data itself is stored, so the archive contains no raw observations. If you need to refit or add data, keep the original dataset separately.