Key Concepts
Code cheat-sheet
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42
)
poly = PolynomialFeatures(degree=2, include_bias=False)
X_train_pf = poly.fit_transform(X_train)
X_test_pf = poly.transform(X_test) # transform only — never re-fit
lr = LinearRegression().fit(X_train_pf, y_train)
print("test MSE:", mean_squared_error(y_test, lr.predict(X_test_pf)))from sklearn.model_selection import StratifiedShuffleSplit
sss = StratifiedShuffleSplit(n_splits=5, test_size=0.2, random_state=0)
for train_idx, test_idx in sss.split(X, y):
X_tr, X_te = X.iloc[train_idx], X.iloc[test_idx]
y_tr, y_te = y.iloc[train_idx], y.iloc[test_idx]Math
The training-error curve just keeps falling — that's why it's a bad stand-in for real performance.
The test-error U comes from two terms moving in opposite directions as complexity grows. σ² is irreducible noise.
Degree-2 polynomial expansion of two features. Six columns from two — including the interaction
x₁x₂.
Self-check
Gotchas
Split before you transform. Fit your scaler / one-hot encoder /
log transform on X_train only, then transform the test set.
Fitting on the combined dataset leaks test statistics into training.
random_state is your friend. Without it your "the new model is
better" comparison might just be a luckier split. Pin the seed and
compare apples to apples.
One-hot encoding can blow up your column count. 25 unique neighbourhoods becomes 25 columns (or 24 if you drop one for identifiability). Polynomial features on top of that and you're in the thousands fast — overfitting risk skyrockets.
Drop one dummy if you care about coefficients. Otherwise the encoded columns are perfectly collinear with the intercept and the coefficients are no longer uniquely identified. Pure prediction mostly survives it; interpretation doesn't.
PolynomialFeatures needs a 2-D input. data['x'] is a 1-D
Series and will error. Use data[['x']] (double brackets) so it
arrives as a DataFrame with shape (n, 1).