Generalized Additive Models › Visualizing Generalized Additive Models
Machine Learning from ScratchAll chapters Generalized Additive Models › Visualizing Generalized Additive ModelsSection view · Sections in this chapter5 / 10 ↓
Reading tools Definitions, links & notes
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Before we fit anything, we need to see the shape of the problem. Suppose we generate a dataset whose two predictors each have a known non-linear effect on a Gaussian response:
with drawn uniformly from and . The first component is a sinusoid; the second is a convex quadratic (upward-opening parabola). Both are clearly not linear, and the additive structure holds exactly because the two components enter as a sum.
PythonIn [7]Expand
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import patsy
from book_plot_style import (
PALETTE,
polish_axes,
seed_book_plots,
use_book_style,
)
from scipy import stats
n = 400
rng = np.random.default_rng(0)
x1 = rng.uniform(-3.0, 3.0, n)
x2 = rng.uniform(-3.0, 3.0, n)
f1_true = np.sin(x1)
f2_true = 0.5 * x2**2 - 0.5 * x2
y = 1.0 + f1_true + f2_true + rng.normal(0.0, 0.4, n)
order1 = np.argsort(x1)
order2 = np.argsort(x2)
partial_y1 = y - f2_true - 1.0
partial_y2 = y - f1_true - 1.0
partial_y1_centered = partial_y1 - f1_true.mean()Two quick plots showing each predictor against the response, with the true component overlaid, make the additive structure visible and give us a reference to check the fit against later.
VisualizationsOut [8]Expand


These are oracle partial responses: the generating components are known only because the data are synthetic. In observed data, we cannot subtract the unknown true contribution of another predictor. The model instead estimates both components jointly; finite noisy samples and smoothing mean that recovery is approximate.
The other thing to visualize is the spline basis itself, since the smooth is a linear combination of these curves. With a modest number of basis functions, each is a localized bump, and the fitted smooth is determined by the weights we put on them.
PythonIn [9]Expand
grid = np.linspace(-3.0, 3.0, 300)
B_grid = patsy.dmatrix(
"0 + bs(grid, df=8, degree=3, include_intercept=True)",
{"grid": grid},
return_type="matrix",
)VisualizationOut [10]Expand

Each basis curve contributes only to a short segment of the range, and they overlap smoothly so that a weighted sum produces a smooth curve within the knot domain. Increasing the number of basis functions makes the space of possible curves richer. The job of is to determine how aggressively we smooth the resulting weighted sum.
Comments
Add to the conversation
A question, a correction, or an example from your own work.
No comments yet. Be the first to share your thoughts!