import whittaker as wk
# Load data and fit nested candidate models
data = wk.load_dataset("abalone")
m1 = wk.GAM("rings ~ s(length)").fit(data)
m2 = wk.GAM("rings ~ s(length) + s(diameter)").fit(data)
m3 = wk.GAM("rings ~ s(length) + s(diameter) + s(height) + s(shucked_weight)").fit(data)Compare Models with AIC
The AIC (Akaike Information Criterion) ranks models by balancing goodness-of-fit against complexity. In a GAM, complexity is measured by the total effective degrees of freedom (EDF) rather than the raw number of parameters, so AIC automatically accounts for how wiggly each smooth is.
Use AIC when you have several candidate models and want a principled way to decide which predictors to include.
Fit the candidate models
Load the abalone dataset and fit three nested models, starting with a single smooth and adding predictors one at a time.
Compare AIC values
Extract the .aic attribute from each model and display them together.
# Compare AIC values across models
m1.aic, m2.aic, m3.aic(2052.895482172216, 2054.8931824650294, 1847.3973234458235)
Lower AIC is better. A difference (ΔAIC) of less than 2 means the models are essentially equivalent in predictive quality. A ΔAIC greater than 10 means the simpler model is decisively worse and the extra predictors are earning their place.
Check total EDF
AIC penalises via total EDF, so it is worth inspecting how complex each model actually is.
# Compare total EDF across models
m1.edf_total, m2.edf_total, m3.edf_total(4.329619009488265, 5.339006719376878, 19.625034023054337)
The full model carries more EDF. If its AIC is not substantially lower, the extra terms are not paying off after the penalty is applied.
Inspect the winning model
Look at the summary of the winning model. In this dataset m3 has the lowest AIC.
m3.summary()GAM fit summary
============================================================
Formula: rings ~ s(length) + s(diameter) + s(height) + s(shucked_weight)
Family: Gaussian(link='identity')
Observations: 500
Coefficients: 37
Parametric coefficients:
Term Estimate Std.Err t value p-value
------------------------ ---------- ---------- ---------- ----------
(Intercept) 6.8680 0.0673 102.038 < 1e-16
Approximate significance of smooth terms:
Term EDF Ref.df Chi.sq p-value
------------------------ ------ ------ ---------- ----------
s(length) 6.27 7 42.371 4.411e-07
s(diameter) 1.00 2 0.002 0.9991
s(height) 5.99 6 25.650 0.0002587
s(shucked_weight) 5.36 6 245.380 < 1e-16
Total EDF: 19.63
Deviance: 1088.1502
Null dev: 6745.2880
Dev. expl: 83.9%
GCV score: 2.357752
Scale est: 2.265210
AIC: 1847.40
BIC: 1930.11
Check deviance_explained and the per-smooth EDF values. Any smooth with EDF near 1.0 is nearly linear (it contributes little beyond a simple slope).
AIC rule of thumb
| ΔAIC from best model | Interpretation |
|---|---|
| 0–2 | Essentially equivalent; prefer simpler |
| 2–10 | Some evidence for the more complex model |
| > 10 | Strong evidence; simpler model is decisively worse |
AIC selects the model that will generalise best on average, not the model that fits the training data best. When predictive accuracy on held-out data is the primary goal, pair AIC comparison with cross-validation (see recipe 26).