# Save and Load a Fitted Model

Re-fitting a GAM every time you need a prediction is wasteful and fragile. Whittaker provides [save_gam()](../reference/save_gam.md#whittaker.save_gam) and [load_gam()](../reference/load_gam.md#whittaker.load_gam) to persist a fitted model to a compact `.npz` archive. The loaded model is fully functional: `predict()`, `summary()`, and [check()](../reference/check.md#whittaker.check) all work immediately without re-fitting.


# Fit and save

Fit a Gamma GAM on the `wages` dataset.


``` python
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.


``` python
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()](../reference/load_gam.md#whittaker.load_gam) function reconstructs the fitted model from the archive. No training data is required at load time.


``` python
import numpy as np

loaded = wk.load_gam("wages_model.npz")
```


Verify the loaded model preserved the original fit by comparing the total EDF.


``` python
loaded.edf_total
```


    7.0508328482675875


``` python
model.edf_total
```


    7.0508328482675875


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.


``` python
# 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)
```


``` python
preds.values.round(2)
```


    array([20.68, 39.67, 62.44, 77.77])


Confirm the predictions are numerically identical to those from the original model.


``` python
# Confirm predictions match original model
orig_preds = model.predict(new_data)
np.allclose(orig_preds.values, preds.values)
```


    True


# 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.
