Ir para o conteúdo

Gradient Descent & Regularization

The closed-form OLS solution is elegant, but it does not scale to huge feature counts, does not exist for most other models, and says nothing about controlling overfitting. This lesson adds the two tools that do: gradient descent — the optimization engine behind nearly all of modern ML — and regularization — the standard brake on model complexity.

Gradient descent

To minimize a differentiable loss \(J(w)\), repeatedly step against the gradient (the direction of steepest increase):

\[ w^{(t+1)} = w^{(t)} - \eta \, \nabla_w J\big(w^{(t)}\big) \]

where \(\eta\) is the learning rate. For linear regression with mean squared error,

\[ J(w) = \frac{1}{n}\lVert y - Xw \rVert^2, \qquad \nabla_w J = -\frac{2}{n} X^\top (y - Xw), \]

a convex bowl with a single global minimum — gradient descent is guaranteed to reach it for small enough \(\eta\).

The learning rate

  • \(\eta\) too small → tiny steps, painfully slow convergence;
  • \(\eta\) too large → steps overshoot the minimum; the loss oscillates or diverges;
  • practical recipe: try \(\eta \in \{10^{-3}, 10^{-2}, 10^{-1}\}\), monitor the training-loss curve — it should fall smoothly.

Feel it yourself — step through the descent, then set \(\eta = 1.05\) and watch it explode:

Scale your features

Unscaled features create an elongated, ravine-like loss surface: the gradient points across the ravine, not along it, and convergence crawls. Standardization makes the bowl round and gradient descent fast — the practical reason scaling matters for all gradient-trained models.

Batch, stochastic, and mini-batch

Variant Gradient computed on Per-step cost Behavior
Batch GD the full dataset \(O(nd)\) exact, smooth descent
Stochastic GD (SGD) one random sample \(O(d)\) noisy but cheap; escapes shallow traps
Mini-batch GD a batch of ~32–512 in between the modern default (vectorizes well)
from sklearn.linear_model import SGDRegressor
model = SGDRegressor(loss='squared_error', penalty='l2', alpha=1e-4,
                     learning_rate='invscaling', max_iter=1000)

The same loop — with different losses — trains logistic regression, SVMs, and neural networks. Learn it once, reuse it everywhere.

From lines to curves: polynomial features

Linear regression is linear in the parameters, not necessarily in the inputs. Expanding features to powers, \(x \mapsto (x, x^2, \dots, x^p)\), fits polynomials with the same OLS machinery:

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures

model = make_pipeline(PolynomialFeatures(degree=3), LinearRegression())

But flexibility cuts both ways:

Polynomial underfit, overfit, and Ridge regularization

Degree 1 underfits — too rigid to follow the sine. Degree 15 overfits — 16 parameters chase 25 noisy points, producing wild oscillations. The right panel keeps all 16 parameters but adds a Ridge penalty: the curve relaxes back to the signal. That is regularization at work.

Regularization

Instead of restricting the number of parameters, penalize their magnitude — add a complexity term to the loss:

Ridge (L2) — Tikhonov, 1943; Hoerl & Kennard, 1970

\[ J(w) = \lVert y - Xw \rVert^2 + \alpha \sum_{j=1}^{d} w_j^2 \]
  • shrinks all coefficients smoothly toward zero (never exactly zero);
  • spreads weight across correlated features — the standard cure for multicollinearity;
  • closed form still exists: \(\hat{w} = (X^\top X + \alpha I)^{-1} X^\top y\) — the \(\alpha I\) makes the matrix invertible even with collinear features.

Lasso (L1) — Tibshirani, 1996

\[ J(w) = \lVert y - Xw \rVert^2 + \alpha \sum_{j=1}^{d} \lvert w_j \rvert \]
  • the absolute-value penalty has corners at zero: solutions land exactly at zero for weak features;
  • performs automatic feature selection — the surviving nonzero coefficients name the features that matter;
  • among a group of highly correlated features, it tends to keep one arbitrarily and zero the rest.

Elastic Net blends both penalties (l1_ratio) — a robust default when features are many and correlated.

from sklearn.linear_model import Ridge, Lasso, ElasticNet

Ridge(alpha=1.0)
Lasso(alpha=0.1)
ElasticNet(alpha=0.1, l1_ratio=0.5)

The knob α

\(\alpha\) trades data fidelity against coefficient size:

  • \(\alpha \to 0\): plain OLS (no brake);
  • \(\alpha \to \infty\): all coefficients crushed to ~0, model predicts the mean (full brake);
  • the right \(\alpha\) is not known in advance — it is chosen by cross-validation (RidgeCV, LassoCV, or a grid search).

Scale before regularizing — and don't penalize the intercept

The penalty \(\sum w_j^2\) compares coefficients across features, which is only fair if features share a scale: otherwise a feature measured in kilometers is penalized differently than the same one in meters. Standardize first (in a Pipeline). By convention the intercept \(w_0\) is excluded from the penalty — scikit-learn does this for you.

Class materials

Class notebook (in Portuguese)

Hands-on notebook used in class — Aula 12 — Regressão Linear: open in Colab


Quiz