Type at least 2 letters. Enter opens the first result, Esc closes.

    Deep Learning · Lesson 6 · Making deep networks trainable

    Regularization: dropout, weight decay, label smoothing, augmentation, early stopping

    Intermediate 55 min 4 interactive figures 3 videos Colab notebook

    Before this lesson: lesson 02, training a network (softmax, cross-entropy, SGD), lesson 03, backpropagation and lesson 05, normalization. From other tracks: L2 regularization and the bias–variance trade-off (ML fundamentals track), Adam (optimization track), and the SVD (linear algebra lesson 08) for the last section. Time: about 55 minutes, plus the notebook.


    Why this matters #

    • LLM pretraining uses AdamW with weight decay 0.1 (GPT-3, LLaMA). Using Adam(weight_decay=...) instead is a common bug: it is L2, not weight decay.
    • The original Transformer used dropout 0.1 and label smoothing 0.1.
    • Vision transformers trained on ImageNet only (DeiT) need heavy augmentation, label smoothing and stochastic depth; without them they overfit.
    • Small scientific datasets rely on early stopping on a validation set, and on augmentations that respect the physics of the data.

    1. Predict first #

    2. The picture #

    Dropout, simplest case #

    Take one unit with value xx and a drop probability pp. At training time, keep the unit with probability 1−p1 - p and multiply it by 1/(1−p)1/(1 - p); otherwise set it to 0. The expected output is

    (1−p)⋅x1−p+p⋅0=x.(1 - p) \cdot \frac{x}{1 - p} + p \cdot 0 = x .

    At eval time, use xx itself. So the network sees the same mean in both modes, but during training it cannot rely on any single unit: any unit may be missing.

    Interactive figure: loading…

    Press One training step a few times, then Sample 1000 masks. Each step drops some units (magenta) and scales the kept ones (blue) by 1/(1−p)1/(1-p); the violet lines are the weights. The histogram shows the output yy over many masks. Its mean (blue line) meets the eval output (aqua line). Move pp: the spread grows like p/(1−p)p/(1-p), but the mean stays.

    Weight decay, simplest case #

    Weight decay multiplies every weight by 1−ηλ1 - \eta\lambda at every step (η\eta the learning rate, λ\lambda the decay rate). Weights that the loss does not need decay towards 0. For SGD this is the same as adding λ2∥θ∥2\frac\lambda2\|\theta\|^2 to the loss (L2 regularization). Adam divides each gradient coordinate by its own running size. If the penalty's gradient goes through Adam, it is divided too, and the shrinkage is no longer the same for every weight. Section 3 shows this in a figure.

    Label smoothing #

    With label smoothing, the target is not one-hot. The true class gets a bit less than 1, and the other classes get a bit more than 0. The model is never asked to be 100% sure, so the logits stay finite.

    Interactive figure: loading…

    Move the logit gap Δ\Delta and watch the dot on the loss curve. The left chart compares the smoothed target qq with the prediction pp. With smoothing (aqua curve), the loss has a minimum H(q)>0H(q) > 0 at a finite gap Δ∗\Delta^* (the dashed lines); beyond it the gradient pushes the gap back down. Without smoothing (grey) the loss keeps falling as Δ→∞\Delta \to \infty. Set ε=0\varepsilon = 0 to see that case.

    Augmentation and early stopping #

    If the label does not change when an input is rotated, show the model rotated inputs: the invariance enters through the data. Early stopping limits how far the weights travel from their small initial values, which acts like L2 (section 3, last part).

    Quick check

    A unit has value x=3x = 3 and dropout uses p=0.25p = 0.25 (PyTorch convention). Which values can the training output take?

    3. Definitions and main results #

    A regularizer is a change to the training procedure (the loss, the update rule, the data or the stopping time) that aims to lower the test error, possibly at the cost of a higher training error. Lesson 17 discusses why large networks generalize at all.

    Inverted dropout #

    With drop probability pp, draw mi∼Bernoulli(1−p)m_i \sim \text{Bernoulli}(1 - p) independently for each entry, and set

    y=m⊙x1−p  (training),y=x  (eval).y = \frac{m \odot x}{1 - p}\ \ \text{(training)}, \qquad y = x\ \ \text{(eval)} .
    • Expectation: E[yi]=xi\mathbb{E}[y_i] = x_i. Variance: Var⁡(yi)=xi2 p1−p\operatorname{Var}(y_i) = x_i^2\, \frac{p}{1-p}.
    • Backward: xˉ=m1−p⊙yˉ\bar x = \frac{m}{1-p} \odot \bar y, with the same mask as in the forward pass.
    • Why "inverted". The original dropout (Srivastava et al., 2014) did not scale during training and multiplied the weights by the keep probability at test time. Scaling during training leaves the eval network unchanged, so nothing special happens at inference.
    • Ensemble view. Each mask selects one of 2n2^n thinned subnetworks that share weights. Eval mode approximates the average of their predictions. When everything after the dropout layer is linear, the average is exact (this is the figure above).

    Theorem (dropout on the inputs of linear regression is a ridge penalty). Let y^i=∑jxijwjmij/(1−p)\hat y_i = \sum_j x_{ij} w_j m_{ij}/(1-p) with independent masks. Then

    Em∑i(yi−y^i)2=∑i(yi−xi⊤w)2+p1−p∑jwj2∑ixij2.\mathbb{E}_m \sum_i (y_i - \hat y_i)^2 = \sum_i (y_i - x_i^\top w)^2 + \frac{p}{1-p} \sum_j w_j^2 \sum_i x_{ij}^2 .

    Proof.

    1. E[mij/(1−p)]=1\mathbb{E}[m_{ij}/(1-p)] = 1, so E[y^i]=xi⊤w\mathbb{E}[\hat y_i] = x_i^\top w.
    2. Var⁡(mij/(1−p))=(1−p)p/(1−p)2=p/(1−p)\operatorname{Var}(m_{ij}/(1-p)) = (1-p)p/(1-p)^2 = p/(1-p), and the masks are independent, so Var⁡(y^i)=p1−p∑jxij2wj2\operatorname{Var}(\hat y_i) = \frac{p}{1-p}\sum_j x_{ij}^2 w_j^2.
    3. For any random y^i\hat y_i: E(yi−y^i)2=(yi−Ey^i)2+Var⁡(y^i)\mathbb{E}(y_i - \hat y_i)^2 = (y_i - \mathbb{E}\hat y_i)^2 + \operatorname{Var}(\hat y_i). Sum over ii. ■\blacksquare

    So dropout acts like a ridge penalty whose strength for wjw_j grows with the energy ∑ixij2\sum_i x_{ij}^2 of feature jj.

    Dropout before BatchNorm. In training, dropout inflates the second moment: E[yi2]=xi2/(1−p)\mathbb{E}[y_i^2] = x_i^2/(1-p). In eval mode it is xi2x_i^2. A BatchNorm layer after dropout learns running statistics from the inflated training activations, so they do not match the eval activations. Li et al. (2019) call this the variance shift. Place dropout after the last BatchNorm, or avoid mixing the two.

    L2 regularization and weight decay #

    Theorem (they are the same for SGD). SGD with learning rate η\eta on L(θ)+λ2∥θ∥2\mathcal{L}(\theta) + \frac\lambda2\|\theta\|^2 makes exactly the same steps as SGD on L\mathcal{L} with weight decay, θ←(1−ηλ)θ−η∇L(θ)\theta \leftarrow (1 - \eta\lambda)\theta - \eta\nabla\mathcal{L}(\theta).

    Proof.

    1. The gradient of the penalized loss is ∇L(θ)+λθ\nabla\mathcal{L}(\theta) + \lambda\theta.
    2. One step: θ−η(∇L+λθ)=(1−ηλ)θ−η∇L\theta - \eta(\nabla\mathcal{L} + \lambda\theta) = (1 - \eta\lambda)\theta - \eta\nabla\mathcal{L}. ■\blacksquare

    The decay per step is ηλ\eta\lambda: the best L2 coefficient depends on the learning rate.

    Adam with L2. Adam keeps running averages of the gradient, mtm_t, and of its square, vtv_t, corrects their start-up bias (m^t,v^t\hat m_t, \hat v_t), and steps θ←θ−η m^t/(v^t+ϵ)\theta \leftarrow \theta - \eta\, \hat m_t/(\sqrt{\hat v_t} + \epsilon). With L2, the term λθ\lambda\theta is added to the gradient before these averages. So the decay moves coordinate ii by about ηλθi/v^t,i\eta\lambda\theta_i/\sqrt{\hat v_{t,i}}:

    • weights with large past gradients (large v^\hat v) are decayed less;
    • weights with small gradients are decayed more.

    Loshchilov and Hutter (2019, Proposition 2) prove that, for any preconditioner that is not a multiple of II, no L2 coefficient makes the method equal to weight decay.

    AdamW decouples the decay from the gradient step: the moments use ∇L\nabla\mathcal{L} only, and

    θt=θt−1−ηt(α m^tv^t+ϵ+λ θt−1),\theta_t = \theta_{t-1} - \eta_t\Big(\alpha\, \frac{\hat m_t}{\sqrt{\hat v_t} + \epsilon} + \lambda\,\theta_{t-1}\Big),

    with base learning rate α\alpha and schedule multiplier ηt\eta_t (their Algorithm 2). Every weight now shrinks at the same rate. PyTorch's AdamW first applies θ←θ(1−lr⋅λ)\theta \leftarrow \theta(1 - \text{lr}\cdot\lambda) and then the Adam step, so its decay per step is lr × weight_decay and follows the learning-rate schedule. PyTorch's Adam(weight_decay=...) is L2, not AdamW.

    Interactive figure: loading…

    Change the number of steps and the gradient size GG. The chart shows how much the decay term alone shrank each weight (the run with decay minus the run without). With AdamW, both weights shrink by about t ηλt\,\eta\lambda (the two aqua lines almost overlap). With Adam + L2, the weight with no gradient (solid) is pulled to 0 within about 100 steps, while the weight with large gradients (dashed) shrinks about 10 times less than under AdamW.

    With normalization layers. A weight followed by BatchNorm or LayerNorm is scale-invariant (lesson 05): decay does not change the function, but it keeps ∥W∥\|W\| small and so keeps the effective learning rate η/∥W∥2\eta/\|W\|^2 up. Biases and normalization gains γ\gamma are usually excluded from decay.

    Quick check

    You train with SGD, learning rate η=0.1\eta = 0.1, and add λ2∥θ∥2\frac\lambda2\|\theta\|^2 with λ=5⋅10−4\lambda = 5 \cdot 10^{-4} to the loss. By which factor does the penalty multiply the weights at each step?

    Label smoothing #

    With KK classes, true class yy and smoothing ε\varepsilon (PyTorch convention):

    q=(1−ε) onehot(y)+εK1,ℓ(z)=−∑cqclog⁡pc,p=softmax⁡(z).q = (1 - \varepsilon)\,\text{onehot}(y) + \frac{\varepsilon}{K}\mathbf 1, \qquad \ell(z) = -\sum_c q_c \log p_c, \qquad p = \operatorname{softmax}(z) .

    So the true class gets 1−ε+ε/K1 - \varepsilon + \varepsilon/K and every other class gets ε/K\varepsilon/K. (Some texts give the true class 1−ε1 - \varepsilon and the others ε/(K−1)\varepsilon/(K - 1).)

    Gradient. Since log⁡pc=zc−log⁡∑jezj\log p_c = z_c - \log\sum_j e^{z_j},

    ∂ℓ∂zk=−qk+pk∑cqc=pk−qk,\frac{\partial \ell}{\partial z_k} = -q_k + p_k \sum_c q_c = p_k - q_k ,

    because ∑cqc=1\sum_c q_c = 1. This is the same form as plain cross-entropy, with qq in place of the one-hot target.

    Minimal loss and bounded logits. For a fixed qq, ℓ=H(q)+KL⁡(q ∥ p)\ell = H(q) + \operatorname{KL}(q\,\|\,p), where H(q)=−∑cqclog⁡qcH(q) = -\sum_c q_c \log q_c is the entropy of qq and KL⁡≥0\operatorname{KL} \ge 0 (Gibbs' inequality). So the loss is minimal exactly at p=qp = q, and it never goes below H(q)>0H(q) > 0. At p=qp = q, the logit gap between the true class and any other class is

    zy−zc=log⁡1−ε+ε/Kε/K=log⁡(1+K(1−ε)ε),z_y - z_c = \log\frac{1 - \varepsilon + \varepsilon/K}{\varepsilon/K} = \log\Big(1 + \frac{K(1-\varepsilon)}{\varepsilon}\Big),

    which is finite. Without smoothing the optimum p=onehotp = \text{onehot} needs an infinite gap, so the logits keep growing and the model becomes overconfident. Müller et al. (2019) found that label smoothing improves calibration, but makes the network a worse teacher for knowledge distillation.

    Quick check

    K=10K = 10 classes and label smoothing ε=0.1\varepsilon = 0.1. What is the optimal logit gap zy−zcz_y - z_c?

    Data augmentation encodes invariances #

    Suppose the label does not change under a finite group GG of transformations (rotations by 90°, flips, cyclic shifts): y(gx)=y(x)y(gx) = y(x) for every g∈Gg \in G. With gg drawn uniformly from GG, data augmentation minimizes

    Raug(f)=Ex Eg ℓ(f(gx),y).R_{\text{aug}}(f) = \mathbb{E}_{x}\,\mathbb{E}_{g}\, \ell\big(f(gx), y\big) .

    For a loss that is convex in the prediction, the averaged predictor fˉ(x)=Egf(gx)\bar f(x) = \mathbb{E}_g f(gx) is GG-invariant, and by Jensen's inequality ℓ(fˉ(x),y)≤Eg ℓ(f(gx),y)\ell(\bar f(x), y) \le \mathbb{E}_g\, \ell(f(gx), y). Since fˉ\bar f is invariant, Raug(fˉ)=Ex ℓ(fˉ(x),y)≤Raug(f)R_{\text{aug}}(\bar f) = \mathbb{E}_x\,\ell(\bar f(x), y) \le R_{\text{aug}}(f): the augmented objective prefers invariant predictors.

    Additive input noise is another simple case. For linear regression on nn samples, with independent noise ei∼N(0,σ2I)e_i \sim \mathcal{N}(0, \sigma^2 I) added to each input xix_i,

    E∑i(yi−(xi+ei)⊤w)2=∑i(yi−xi⊤w)2+nσ2∥w∥2,\mathbb{E}\sum_i \big(y_i - (x_i + e_i)^\top w\big)^2 = \sum_i (y_i - x_i^\top w)^2 + n\sigma^2\|w\|^2 ,

    which is ridge again (Bishop, 1995). An equivariant architecture (a CNN, or an E(3)-equivariant graph network) builds the same symmetry into the model instead of the data (lessons 07 and 13).

    An augmentation must keep the label and the physics. Rotating a handwritten "6" by 180° gives a "9". Flipping a regional weather map north–south makes cyclones turn the wrong way for their hemisphere. Rescaling a seismic waveform changes the magnitude it encodes.

    Early stopping acts like ridge #

    Take least squares, L(w)=12n∥Xw−y∥2\mathcal{L}(w) = \frac1{2n}\|Xw - y\|^2, with gradient Sw−bSw - b, where S=X⊤X/nS = X^\top X/n and b=X⊤y/nb = X^\top y/n. Assume SS is invertible. Write S=Vdiag⁡(s)V⊤S = V\operatorname{diag}(s)V^\top (its eigendecomposition; the sis_i are the squared singular values of X/nX/\sqrt n) and w⋆=S−1bw^\star = S^{-1}b. Ridge with strength λ\lambda minimizes L(w)+λ2∥w∥2\mathcal{L}(w) + \frac\lambda2\|w\|^2, so it solves (S+λI)w=b(S + \lambda I)w = b.

    Theorem (filter factors). Gradient descent from w0=0w_0 = 0 with step η<2/smax⁡\eta < 2/s_{\max} gives, along each eigenvector with eigenvalue ss, the component (1−(1−ηs)t) ws⋆\big(1 - (1 - \eta s)^t\big)\,w^\star_s after tt steps. Ridge with strength λ\lambda gives ss+λ ws⋆\frac{s}{s + \lambda}\,w^\star_s.

    Proof.

    1. wt+1−w⋆=wt−η(Swt−b)−w⋆=(I−ηS)(wt−w⋆)w_{t+1} - w^\star = w_t - \eta(Sw_t - b) - w^\star = (I - \eta S)(w_t - w^\star), because b=Sw⋆b = Sw^\star.
    2. Hence wt−w⋆=(I−ηS)t(0−w⋆)w_t - w^\star = (I - \eta S)^t(0 - w^\star), that is, wt=(I−(I−ηS)t)w⋆w_t = \big(I - (I - \eta S)^t\big)w^\star.
    3. Ridge solves (S+λI)w=b=Sw⋆(S + \lambda I)w = b = Sw^\star, so wλ=(S+λI)−1S w⋆w_\lambda = (S + \lambda I)^{-1} S\, w^\star.
    4. In the eigenbasis both matrices are diagonal, which gives the two filter factors. ■\blacksquare

    Reading the factors. For s≫1/(ηt)s \gg 1/(\eta t) both factors are about 1: these directions are fitted. For s≪1/(ηt)s \ll 1/(\eta t), GD gives about ηst\eta s t (because (1−ηs)t≈1−ηst(1 - \eta s)^t \approx 1 - \eta s t) and ridge gives about s/λs/\lambda. They match when

    λ≈1ηt.\lambda \approx \frac{1}{\eta t} .

    So stopping early suppresses the directions with small eigenvalues, which are the ones most affected by noise, just as ridge does. The stopping time is chosen on a validation set, never on the test set.

    Interactive figure: loading…

    Move the number of steps tt. The violet path is gradient descent from 0 (the dots are steps); the aqua dashed curve is the ridge solution for all λ\lambda, and the aqua dot is ridge with λ=1/(ηt)\lambda = 1/(\eta t). Both first move along the steep direction of the loss (large eigenvalue s1s_1) and reach w⋆w^\star along the flat direction (s2s_2) only later. The right chart shows the two filter factors; the dots mark s1s_1 and s2s_2.

    Answers to section 1. (1) No. The minimum is H(q)H(q) with q=(0.91,0.01,…,0.01)q = (0.91, 0.01, \dots, 0.01): −(0.91ln⁡0.91+9⋅0.01ln⁡0.01)≈0.500-(0.91\ln 0.91 + 9 \cdot 0.01 \ln 0.01) \approx 0.500. (2) With Adam + L2, the weight with no gradient shrinks much faster: its v^\sqrt{\hat v} is tiny, so the decay term is divided by a tiny number. With AdamW both shrink at the same rate, ηλ\eta\lambda per step.

    4. Worked example #

    (a) Dropout. x=(1,2,3,4)x = (1, 2, 3, 4), p=0.5p = 0.5, mask draw m=(1,0,1,1)m = (1, 0, 1, 1).

    • Training output: y=m⊙x/(1−p)=2 m⊙x=(2,0,6,8)y = m \odot x/(1 - p) = 2\,m \odot x = (2, 0, 6, 8).
    • Over many draws: E[y]=x\mathbb{E}[y] = x and Var⁡(yi)=xi2⋅0.5/0.5=(1,4,9,16)\operatorname{Var}(y_i) = x_i^2 \cdot 0.5/0.5 = (1, 4, 9, 16).
    • Backward with this mask: xˉ=(2,0,2,2)⊙yˉ\bar x = (2, 0, 2, 2) \odot \bar y.
    • Eval: y=xy = x.

    (b) Label smoothing. K=3K = 3, ε=0.15\varepsilon = 0.15, true class 0, logits z=(2,0,0)z = (2, 0, 0).

    • Target: q=(0.85+0.05, 0.05, 0.05)=(0.9,0.05,0.05)q = (0.85 + 0.05,\ 0.05,\ 0.05) = (0.9, 0.05, 0.05).
    • Prediction: p=(e2,1,1)/(e2+2)=(7.389,1,1)/9.389=(0.7870,0.1065,0.1065)p = (e^2, 1, 1)/(e^2 + 2) = (7.389, 1, 1)/9.389 = (0.7870, 0.1065, 0.1065).
    • Loss: −(0.9ln⁡0.7870+0.05ln⁡0.1065+0.05ln⁡0.1065)=0.2156+0.2240=0.4395-(0.9 \ln 0.7870 + 0.05 \ln 0.1065 + 0.05 \ln 0.1065) = 0.2156 + 0.2240 = 0.4395.
    • Gradient: p−q=(−0.113,0.0565,0.0565)p - q = (-0.113, 0.0565, 0.0565). It still pushes the gap up, because the optimal gap is ln⁡(0.9/0.05)=ln⁡18≈2.89>2\ln(0.9/0.05) = \ln 18 \approx 2.89 > 2. Above 2.89 the gradient pushes back.
    • Without smoothing, the gradient is p−onehot=(−0.213,0.1065,0.1065)p - \text{onehot} = (-0.213, 0.1065, 0.1065), and its first entry is negative for every gap.

    (c) Adam + L2 vs AdamW. Learning rate 0.01, λ=0.01\lambda = 0.01, 10 steps, two weights at 1. The data gradients alternate in sign, with size 0 (first weight) or 10 (second weight). Adam moves the second weight even without decay (by about 0.015 here), so we compare each run with the same run without decay. The shrinkage caused by the decay:

    no-gradient weight large-gradient weight
    Adam + L2 0.0997 0.00009
    AdamW 0.0010 0.0010

    AdamW shrinks both by about 10⋅ηλ=10−310 \cdot \eta\lambda = 10^{-3}. Adam + L2 shrinks the no-gradient weight 100 times more, and the large-gradient weight 11 times less.

    (d) Early stopping. η=0.1\eta = 0.1 and t=100t = 100, so λ≈1/(ηt)=0.1\lambda \approx 1/(\eta t) = 0.1.

    eigenvalue ss GD: 1−(1−ηs)t1 - (1 - \eta s)^t ridge: s/(s+λ)s/(s + \lambda)
    1 1−0.9100≈1.0001 - 0.9^{100} \approx 1.000 1/1.1=0.9091/1.1 = 0.909
    0.1 1−0.99100=0.6341 - 0.99^{100} = 0.634 0.1/0.2=0.50.1/0.2 = 0.5
    0.01 1−0.999100=0.0951 - 0.999^{100} = 0.095 0.01/0.11=0.0910.01/0.11 = 0.091

    Both keep the large-ss directions and shrink the small-ss ones; GD's filter is sharper.

    Quick check

    Gradient descent with η=0.01\eta = 0.01 is stopped after t=500t = 500 steps on a least-squares problem. A direction has eigenvalue s=0.02s = 0.02. About how much of w⋆w^\star along it has GD fitted?

    5. In code #

    PyTorch checks the worked examples (a)–(c):

    import torch
    import torch.nn.functional as F
    
    torch.manual_seed(0)
    x = torch.tensor([1., 2., 3., 4.], dtype=torch.float64).repeat(200_000, 1)   # 200k copies
    y = F.dropout(x, p=0.5, training=True)
    print(sorted(y[:, 3].unique().tolist()))           # [0.0, 8.0]: kept entries scaled by 1/(1-p)
    print(round((y == 0).double().mean().item(), 3))   # 0.5: fraction dropped
    print(y.mean(0).numpy().round(1))                  # [1. 2. 3. 4.]      E[y] = x
    print(y.var(0).numpy().round(1))                   # [ 1.  4.  9. 16.]  Var = x^2 p/(1-p)
    print(torch.equal(F.dropout(x, p=0.5, training=False), x))   # True: identity at eval
    
    z = torch.tensor([[2.0, 0.0, 0.0]], dtype=torch.float64, requires_grad=True)
    loss = F.cross_entropy(z, torch.tensor([0]), label_smoothing=0.15)
    loss.backward()
    print(round(loss.item(), 4), z.grad.numpy().round(4))   # 0.4395 [[-0.113   0.0565  0.0565]]
    
    def run(opt_cls, weight_decay, steps=10):
        """Two weights start at 1. Their data gradients alternate in sign, with sizes 0 and 10."""
        theta = torch.ones(2, dtype=torch.float64, requires_grad=True)
        size = torch.tensor([0.0, 10.0], dtype=torch.float64)
        opt = opt_cls([theta], lr=0.01, weight_decay=weight_decay)
        for t in range(steps):
            theta.grad = size * (-1.0) ** t        # the data gradient of this step
            opt.step()
        return theta.detach()
    
    for name, cls in [("Adam + L2", torch.optim.Adam), ("AdamW", torch.optim.AdamW)]:
        shrink = run(cls, 0.0) - run(cls, 0.01)    # the part of the movement caused by the decay
        print(f"{name:9s}  no-gradient weight {shrink[0]:.5f}   large-gradient weight {shrink[1]:.5f}")
    # Adam + L2  no-gradient weight 0.09965   large-gradient weight 0.00009
    # AdamW      no-gradient weight 0.00100   large-gradient weight 0.00099
    

    Early stopping against ridge on a least-squares problem with a wide spread of eigenvalues:

    import numpy as np
    
    rng = np.random.default_rng(0)
    n, d = 200, 20
    X = rng.standard_normal((n, d)) * np.logspace(0, -1.5, d)   # feature scales from 1 down to 0.03
    y = X @ rng.standard_normal(d) + 0.1 * rng.standard_normal(n)
    S, b = X.T @ X / n, X.T @ y / n          # the loss (1/2n)|Xw - y|^2 has gradient S w - b
    
    eta, t = 0.5, 400
    w = np.zeros(d)
    for _ in range(t):                       # gradient descent from 0, stopped after t steps
        w -= eta * (S @ w - b)
    lam = 1 / (eta * t)                      # predicted equivalent ridge strength: 0.005
    w_ridge = np.linalg.solve(S + lam * np.eye(d), b)
    w_ls = np.linalg.solve(S, b)
    
    s, V = np.linalg.eigh(S)                 # filter factor = component of w / component of w_ls
    f_gd, f_ridge = (V.T @ w) / (V.T @ w_ls), (V.T @ w_ridge) / (V.T @ w_ls)
    print(np.allclose(f_gd, 1 - (1 - eta * s) ** t), np.allclose(f_ridge, s / (s + lam)))  # True True
    for i in (0, 5, 10, 19):
        print(f"s={s[i]:.4f}  GD {f_gd[i]:.3f}  ridge {f_ridge[i]:.3f}")
    # s=0.0009  GD 0.158  ridge 0.147
    # s=0.0070  GD 0.755  ridge 0.584
    # s=0.0332  GD 0.999  ridge 0.869
    # s=0.9810  GD 1.000  ridge 0.995
    

    6. Where it shows up #

    • LLM pretraining. AdamW with weight decay 0.1 (GPT-3, LLaMA), no decay on biases and norm gains, and usually no dropout: with one pass over a huge dataset, overfitting is not the main risk. Dropout returns when fine-tuning on small data.
    • Vision. DeiT trains ViTs on ImageNet-1k only, with strong augmentation (RandAugment, Mixup, CutMix), label smoothing 0.1 and stochastic depth (randomly dropping whole residual branches).
    • ML for science. Labelled data are often small, so early stopping on a held-out set is standard. Split the held-out set by time or region, not at random, or neighbouring samples leak. Augment only with true symmetries: rotations are fine for molecules, but not a north–south flip of a regional weather map. Learned simulators add noise to their inputs during training so that long autoregressive rollouts stay stable (Sanchez-Gonzalez et al., 2020).
    • Uncertainty. Monte Carlo dropout keeps dropout on at test time and averages several predictions; their spread is a cheap uncertainty estimate (Gal and Ghahramani, 2016).

    7. Common mistakes #

    • Adam(weight_decay=λ) is L2, not AdamW. Use AdamW for decoupled decay.
    • Tuning λ\lambda without the learning rate. In PyTorch's AdamW the decay per step is lr × λ, so changing lr changes the decay, and the decay fades with a cosine schedule.
    • Decaying biases and normalization gains. They are usually excluded; decaying γ\gamma pulls the output scale of every normalized layer towards 0.
    • Forgetting model.eval(). Dropout stays on and the predictions are noisy.
    • Wrong meaning of pp. PyTorch's pp is the drop probability; Srivastava et al. and TensorFlow 1's keep_prob use the keep probability.
    • Dropout before BatchNorm. Dropout inflates E[y2]\mathbb{E}[y^2] by 1/(1−p)1/(1-p) during training, so BN's running variance does not match the eval activations.
    • Label-changing augmentation. Rotating a "6" by 180° gives a "9"; flipping a regional weather map breaks the physics.
    • Early stopping on the test set. That leaks the test set into model selection; use a validation set.

    8. Check yourself #

    1. Dropout with p=0.25p = 0.25 on a unit with value x=2x = 2. Which values can yy take, with which probabilities? What are E[y]\mathbb{E}[y] and Var⁡(y)\operatorname{Var}(y)?
      Answery=2/0.75=8/3≈2.667y = 2/0.75 = 8/3 \approx 2.667 with probability 0.75, and y=0y = 0 with probability 0.25. E[y]=2\mathbb{E}[y] = 2 and Var⁡(y)=4⋅0.25/0.75=4/3≈1.333\operatorname{Var}(y) = 4 \cdot 0.25/0.75 = 4/3 \approx 1.333.
    2. In PyTorch, what does a dropout layer do to its input in eval mode, and why is no rescaling needed there?
      AnswerIt returns the input unchanged. Inverted dropout already divides by 1−p1 - p during training, so the expected training output equals the eval output.
    3. K=10K = 10, ε=0.1\varepsilon = 0.1: give the smoothed target, the minimal loss and the optimal logit gap.
      AnswerTrue class 0.9+0.01=0.910.9 + 0.01 = 0.91, others 0.010.01. Minimal loss H(q)=−(0.91ln⁡0.91+9⋅0.01ln⁡0.01)≈0.500H(q) = -(0.91\ln 0.91 + 9 \cdot 0.01\ln 0.01) \approx 0.500. Gap ln⁡(0.91/0.01)=ln⁡91≈4.51\ln(0.91/0.01) = \ln 91 \approx 4.51.
    4. PyTorch AdamW(lr=3e-4, weight_decay=0.1) with a constant learning rate: by which factor does the decay alone shrink a weight over 10,000 steps?
      AnswerThe factor per step is 1−3⋅10−4⋅0.1=1−3⋅10−51 - 3\cdot10^{-4} \cdot 0.1 = 1 - 3\cdot10^{-5}, so (1−3⋅10−5)104≈e−0.3≈0.741(1 - 3\cdot10^{-5})^{10^4} \approx e^{-0.3} \approx 0.741.
    5. Linear regression with dropout pp on the inputs, and standardized features (∑ixij2=n\sum_i x_{ij}^2 = n). Which ridge penalty λ∥w∥2\lambda\|w\|^2 does dropout add to the summed squared loss?
      Answerλ=n p/(1−p)\lambda = n\,p/(1-p). For p=0.5p = 0.5, λ=n\lambda = n, which is ridge strength 1 on the mean squared loss.
    6. Gradient descent with η=0.01\eta = 0.01 is stopped after t=500t = 500 steps. Which ridge strength does it resemble, and which eigen-directions of SS does it fit?
      Answerλ≈1/(ηt)=0.2\lambda \approx 1/(\eta t) = 0.2. Directions with s≫0.2s \gg 0.2 are fitted almost fully; directions with s≪0.2s \ll 0.2 are shrunk to about ηst=5s\eta s t = 5s of their value.
    Recall cardsAnswer in your head first, then reveal. Add the cards to your review deck to see them again just before you would forget.
    1. Write inverted dropout with drop probability pp (training and eval).

    2. Why does inverted dropout divide by 1−p1 - p?

    3. Dropout with p=0.5p = 0.5 on a unit with value x=3x = 3: what is Var⁡(y)\operatorname{Var}(y)?

    4. Show that SGD with the L2 penalty λ2∥θ∥2\frac\lambda2\|\theta\|^2 is weight decay.

    5. Why is L2 regularization not weight decay under Adam?

    6. What is the AdamW update in PyTorch?

    7. What is the label-smoothed target with KK classes and smoothing ε\varepsilon?

    8. What is the minimal cross-entropy under label smoothing, and where is it reached?

    9. Which ridge strength does early stopping after tt GD steps with step η\eta resemble?

    10. What does data augmentation with a symmetry group GG of the labels encourage?

    Open the review →

    9. Interview angle #

    • "Why scale by 1/(1−p)1/(1-p) in dropout?" — So that E[y]=x\mathbb{E}[y] = x, and nothing changes at eval time.
    • "Weight decay vs L2?" — Equal for SGD (factor 1−ηλ1 - \eta\lambda per step); different for Adam, because the L2 gradient is divided by v^\sqrt{\hat v}. AdamW decouples the decay.
    • "What does label smoothing do to the logits?" — The optimum is p=qp = q with a finite gap log⁡(1+K(1−ε)/ε)\log(1 + K(1-\varepsilon)/\varepsilon); the loss never reaches 0, and the model is less overconfident.
    • "Is early stopping a regularizer?" — Yes: for least squares it acts like ridge with λ≈1/(ηt)\lambda \approx 1/(\eta t).
    • "Why do LLMs often train without dropout?" — One epoch over a huge dataset; the regularization comes from data scale and weight decay.

    10. Practice #

    The notebook for this lesson runs in Colab. Each exercise has a check cell and a folded solution.

    1. Inverted dropout (forward and backward with the same mask), with a check of the mean and the variance.
    2. Adam + L2 and AdamW written by hand on two weights, reproducing the numbers of section 4 and checked against torch.optim.
    3. Label-smoothed cross-entropy and its gradient, checked against F.cross_entropy(..., label_smoothing=).
    4. Early-stopping and ridge filter factors on a random least-squares problem.
    5. A small MLP on the scikit-learn digits: validation accuracy with and without dropout and weight decay.

    11. Watch and read #

    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    Open on YouTube · the player loads from youtube-nocookie.com when you press play