
EE 541 - Unit 7B
Fall 2026
Data model, class \(c \in \{0, 1\}\)
\[p(\mathbf{x} \mid c) = \frac{1}{\pi}\int_0^{\pi} \mathcal{N}\big(\mathbf{x};\, \mathbf{a}_c(t),\, 0.35^2\,\mathbf{I}\big)\, dt\]
Bayes rule, equal priors: decide class \(1\) where
\[P(1 \mid \mathbf{x}) = \frac{p(\mathbf{x} \mid 1)}{p(\mathbf{x} \mid 0) + p(\mathbf{x} \mid 1)} > \tfrac{1}{2}\]
Training set: \(200\) points, \(100\) per class
Best accuracy on new points: \(88.9\%\), the Bayes rule’s



Training
Past \(88.9\%\): the network fits points that no rule classifies correctly on new data

Validation set: \(2{,}000\) new points from the same distribution
Step \(400\): validation loss \(0.29\), against \(0.28\) for the Bayes rule
After step \(400\): every step lowers the training loss and raises the validation loss
Correctly classified point: logits \(\mathbf{s}\), true class \(y\), margins \(s_y - s_k > 0\)
\[\ell(c\,\mathbf{s}) = \log\Big(1 + \sum_{k \ne y} e^{-c\,(s_y - s_k)}\Big)\]
Every training point correct


FashionMNIST, \(1{,}000\) training images
Wrong with probability above \(0.99\): 620 of the \(10{,}000\) validation images
Loss above \(2\)

Shuffled labels: a point’s label says nothing about the point
Training accuracy reaches nearly \(100\%\) with or without a pattern in the labels
FashionMNIST, the same network and \(8{,}000\) steps
Validation loss falls: \(1.15\) at \(1{,}000\) images, \(0.31\) at \(50{,}000\)
Training loss rises: below \(0.001\) at \(1{,}000\) images, \(0.18\) at \(50{,}000\)
Validation accuracy: \(80\%\), \(85\%\), \(89\%\) at \(1{,}000\), \(5{,}000\), \(50{,}000\)
Lowest validation loss: later and lower with more images

Training loss, the average over the \(n\) training points
\[\hat{R}_n(f) = \frac{1}{n}\sum_{i=1}^{n} \ell(y_i, f(\mathbf{x}_i))\]
Loss on new data, the expected loss
\[R(f) = \mathbb{E}\big[\ell(Y, f(\mathbf{X}))\big]\]
Fitted network \(\hat{f}_n = \arg\min_f \hat{R}_n(f)\)
Two moons, one run

Penalized loss, weights only, biases unpenalized
\[\mathcal{L}_\lambda = \frac{1}{n}\sum_{i=1}^{n} \ell_i + \frac{\lambda}{2}\sum_l \|\mathbf{W}^{(l)}\|_F^2\]
Gradient step
\[\mathbf{W} \leftarrow (1 - \eta\lambda)\,\mathbf{W} - \eta\, \nabla_{\mathbf{W}} \frac{1}{n}\sum_i \ell_i\]


\(\lambda = 0.01\), after \(80{,}000\) steps
Without decay: validation loss \(3.38\), weights still growing
With decay: \(\|\mathbf{W}\| = 4.1\) from step \(10{,}000\) on
weight_decay Adds \(\lambda \mathbf{W}\) to Each Weight’s GradientThe penalty in the loss: ordinary tensor code, differentiated by backward()
\[\nabla_{\mathbf{W}}\Big(\mathcal{L} + \frac{\lambda}{2}\|\mathbf{W}\|_F^2\Big) = \nabla_{\mathbf{W}}\mathcal{L} + \lambda\mathbf{W}\]
named_parameters(): each tensor with its name, '0.weight', '0.bias', …The penalty in the optimizer: weight_decay adds \(\lambda \mathbf{w}\) to the gradient inside step()
\[\mathbf{g} \leftarrow \nabla_{\mathbf{W}}\mathcal{L} + \lambda\mathbf{W}, \qquad \mathbf{W} \leftarrow \mathbf{W} - \eta\,\mathbf{g}\]

Training loss rises with every increase in \(\lambda\)
Validation loss has a minimum

\(1{,}000\) training images, \(8{,}000\) steps
\(\lambda = 0.03\), lowest validation loss at the end
Validation accuracy: \(80\%\) at both
\(\lambda = 0.3\): validation loss \(1.18\), underfit
What \(\lambda\) sets: a prior width on the weights, \(\tau = 1/\sqrt{n\lambda}\)
What the penalty depends on: \(\|\mathbf{W}\|\) only, the same for any arrangement of the weights
What it does not change, FashionMNIST

Co-adaptation: units useful only together (Hinton et al. 2012)
Half the hidden units removed at evaluation
Network: one hidden layer of \(256\) units, \(10{,}000\) FashionMNIST images

Training step: each hidden activation \(a_j\) is replaced by
\[\tilde{a}_j = \frac{m_j}{1 - p}\, a_j, \qquad m_j = \begin{cases} 0 & \text{with probability } p \\ 1 & \text{with probability } 1 - p \end{cases}\]
Example, set by hand, \(p = 0.35\)
Any other unit is absent on a fraction \(p\) of the steps

model.eval() Turns Dropout Offtensor([3.0769, 0.7692, 0.0000, 4.6154])
tensor([0.0000, 0.7692, 1.5385, 4.6154])
tensor([2.0000, 0.5000, 1.0000, 3.0000])
Where the scaling happens, the same expected input to the next layer
Not matched: the variance of the next layer’s input, larger in training than at evaluation

Placement
Rates (Srivastava et al. 2014)
Evaluating in training mode: a different random subnetwork on every call

Validation loss after \(80{,}000\) steps
Training accuracy: \(100\%\), \(98.5\%\), \(93.5\%\) at \(p = 0, 0.5, 0.8\)
Subnetworks: \(2^n\) masks for \(n\) droppable units, one set of weights

Average prediction over masks \(\mathbf{m}\)
\[\bar{q}(\mathbf{x}) = \mathbb{E}_{\mathbf{m}}\big[q(\mathbf{x}; \mathbf{m})\big]\]
Two moons, \(p = 0.5\)
Evaluation mode against the average of \(100\) random masks
Same predicted class on \(98.7\%\) of the \(2{,}000\) validation points


Lowest validation loss
Input dropout \(0.2\): a random fifth of the pixels set to \(0\) in each training step
Two hidden layers of \(1{,}024\) units, \(p = 0.5\)
At the end of training
Weight norm \(\|\mathbf{W}\|\), end of training
Changed by dropout
Unchanged: logits keep growing once the training points are fit


Overtraining: training past the lowest validation loss
Two moons, no regularization
FashionMNIST, \(50{,}000\) images, no regularization
FashionMNIST, \(50{,}000\) images, dropout \(p = 0.5\), input dropout \(0.2\)

FashionMNIST, \(50{,}000\) images: kept \(0.287\) at epoch \(10\), against \(0.64\) after \(100\) epochs
import copy
best, kept, waited = float('inf'), None, 0
for epoch in range(max_epochs):
train_one_epoch(model, loader, opt)
val = val_loss(model, val_loader) # eval mode
if val < best:
best, waited = val, 0
kept = copy.deepcopy(model.state_dict())
else:
waited += 1
if waited == patience:
break
model.load_state_dict(kept)Best network: the parameters with the lowest validation loss of the run
patience: epochs allowed without a new lowest validation lossstate_dict(): the parameters by namecopy.deepcopy: state_dict() returns the live tensors, which later steps change in placeload_state_dict(kept) restores the epoch-\(10\) parametersstate_dict Contains the Tensors, Not the Architecturemodel.state_dict(): every parameter and buffer (batch-norm running statistics), by name
0.weight (1024, 784)
0.bias (1024,)
3.weight (1024, 1024)
3.bias (1024,)
6.weight (10, 1024)
6.bias (10,)
nn.Sequentialnn.ReLU and nn.Dropout hold no tensors: no entries 1, 2, 4, 5Saving: the tensors only
Loading: the layers from build(), then the tensors
eval() before predicting: dropout offONNX (a model file format): torch.onnx.export writes the computation graph with the tensors, for inference without the model’s code
Patience \(k\): epochs allowed without a new lowest validation loss

FashionMNIST, \(50{,}000\) images, no regularization
Short patience stops on noise and keeps a worse network
Patience \(5\): stops at epoch \(15\)
Patience \(20\): the same parameters, \(15\) epochs later
Second seed: patience \(5\) keeps \(0.299\), patience \(10\) the minimum, \(0.291\)

FashionMNIST, \(10{,}000\) images, no regularization
Confidence on wrong predictions: the probability of the predicted class, averaged over misclassified images
From the lowest loss to the end, step \(2{,}000\) to \(20{,}000\)
Highest accuracy: step \(8{,}000\), \(87.5\%\), validation loss \(0.586\)
Second seed: lowest loss at step \(2{,}500\), highest accuracy at \(9{,}000\)
Kept copy: one per quantity monitored
Early stopping, logistic regression, from \(\mathbf{w} = \mathbf{0}\)
Quadratic loss near a minimum \(\mathbf{w}^*\), Hessian \(\mathbf{H}\) with eigenvalues \(h_i\), \(w_i\) the component along eigenvector \(i\)
\[\mathcal{L}(\mathbf{w}) = \mathcal{L}(\mathbf{w}^*) + \tfrac{1}{2}(\mathbf{w} - \mathbf{w}^*)^T \mathbf{H}\, (\mathbf{w} - \mathbf{w}^*)\]
Gradient descent from \(\mathbf{w}^{(0)} = \mathbf{0}\), with \(0 < \eta h_i < 1\)
\[\mathbf{w}^{(t)} - \mathbf{w}^* = (\mathbf{I} - \eta \mathbf{H})(\mathbf{w}^{(t-1)} - \mathbf{w}^*) \quad\Rightarrow\quad w_i^{(t)} = \big(1 - (1 - \eta h_i)^t\big)\, w_i^*\]
L2 penalty \(\tfrac{\lambda}{2}\|\mathbf{w}\|^2\)
\[\mathbf{H}(\mathbf{w} - \mathbf{w}^*) + \lambda \mathbf{w} = \mathbf{0} \quad\Rightarrow\quad w_i = \frac{h_i}{h_i + \lambda}\, w_i^*\]
From a random start \(\mathbf{w}^{(0)}\): \(\mathbf{w} - \mathbf{w}^{(0)}\) in place of \(\mathbf{w}\), so the penalty is \(\tfrac{\lambda}{2}\|\mathbf{w} - \mathbf{w}^{(0)}\|^2\)

Both factors are near \(1\) where \(h_i\) is large and near \(0\) where \(h_i\) is small
\[\eta h_i t \ll 1: \qquad \eta h_i t \;\approx\; \frac{h_i}{\lambda} \quad\Rightarrow\quad \lambda = \frac{1}{\eta t}\]
\(\|\mathbf{W}\|\): the norm of all weight matrices, biases excluded
Two moons, one run without regularization
Weight decay, \(\lambda = 0.01\): a penalty centered at \(\mathbf{0}\)
Validation loss, Bayes rule \(0.28\) (computed from the generating distribution)

Two moons, the same network, data, and start, three learning rates
Best stopping step, full batch: one step per epoch
Best network at every \(\eta\)
A stopping step tuned at one \(\eta\): not the best step at any other \(\eta\)

Hard target: one-hot, \(1\) on the true class and \(0\) on every other class
Label smoothing: a fraction \(\varepsilon\) of the target moved off the true class and spread evenly over all \(K\) classes
\[\tilde{y}_k = (1 - \varepsilon)\, y_k + \frac{\varepsilon}{K}\]
Soft target: a probability distribution over the classes, which CrossEntropyLoss accepts as a target

Cross-entropy with a hard target, true logit ahead of each of the other \(K - 1\) logits by \(g\)
\[\ell(g) = \log\big(1 + (K - 1)\, e^{-g}\big)\]
FashionMNIST, \(10{,}000\) images, two hidden layers of \(1{,}024\) units, \(20{,}000\) steps

\(q_k\): the softmax probability of class \(k\)
Loss at gap \(g\), the other logits equal
\[\tilde{\ell}(g) = -\tilde{y}_{\text{true}} \log q_{\text{true}}(g) - (1 - \tilde{y}_{\text{true}}) \log q_{\text{other}}(g)\]
Lowest at \(q = \tilde{y}\)
\[g^* = \log \frac{1 - \varepsilon + \varepsilon/K}{\varepsilon / K}\]
Predicted and measured, median gap over training images

Expanding \(\tilde{y}\) in the cross-entropy
\[\tilde{\ell} = (1 - \varepsilon)\, \ell_{\text{CE}} + \varepsilon \cdot \frac{1}{K} \sum_{k=1}^{K} -\log q_k\]
Penalized quantity
F = nn.functional
s = torch.tensor([[2.0, 0.5, -1.0]])
y = torch.tensor([0])
eps, K = 0.1, 3
a = nn.CrossEntropyLoss(label_smoothing=eps)(s, y)
target = (1 - eps) * F.one_hot(y, K) + eps / K
b = nn.CrossEntropyLoss()(s, target)
c = ((1 - eps) * F.cross_entropy(s, y)
- eps * s.log_softmax(1).mean())
print(f'{a:.4f} {b:.4f} {c:.4f}')0.3913 0.3913 0.3913
label_smoothing=ε: the smoothed target, built inside the loss
Validation loss: plain cross-entropy against the true labels
Confidence: the largest softmax probability
FashionMNIST, \(10{,}000\) images, \(\varepsilon = 0\) and \(0.1\), end of training
With \(\varepsilon = 0.1\), validation loss ends within \(0.04\) of its lowest
Lowest validation loss: \(0.375\) and \(0.437\), higher with smoothing
Calibration: among predictions given confidence \(\approx c\), a fraction \(c\) correct
Expected calibration error (ECE): the gap between confidence and accuracy, averaged over \(10\) confidence bins weighted by their counts
FashionMNIST, \(10{,}000\) images, validation set, mean confidence and accuracy
\(\varepsilon\): a setting chosen on the validation set


Smoothed target: \(\varepsilon / K\) on every other class, the same for a coat as for a sneaker
Shirt images, mean logit minus the shirt logit
Class ranked second, the same in two training runs (seeds \(0\) and \(1\))
Distillation trains on the other classes’ probabilities (Müller et al. 2019)
SGD: \(\mathbf{w} \leftarrow \mathbf{w} - \eta\, \mathbf{g}_t\), with \(\mathbf{g}_t\) the minibatch gradient
Per layer, plain SGD: relative steps differing by orders of magnitude across layers
Two changes to the gradient, before the step

SGD with momentum, PyTorch’s form
\[\mathbf{m}_t = \beta\, \mathbf{m}_{t-1} + \mathbf{g}_t, \qquad \mathbf{w} \leftarrow \mathbf{w} - \eta\, \mathbf{m}_t\]
Unrolled: \(\mathbf{m}_t = \mathbf{g}_t + \beta\, \mathbf{g}_{t-1} + \beta^2 \mathbf{g}_{t-2} + \cdots\)
Valley, set by hand: steep across (\(\eta < 2/50 = 0.04\) for plain SGD), shallow along
Variants: Nesterov, the gradient at the point momentum is about to reach, SGD(nesterov=True)

Steady gradient \(\mathbf{g}\): \(\mathbf{m}_t \to \mathbf{g}/(1 - \beta)\)
FashionMNIST, two hidden layers of \(256\) units, \(10\) epochs
Averaged form: \(\mathbf{m}_t = \beta\, \mathbf{m}_{t-1} + (1 - \beta)\, \mathbf{g}_t\), the same update with \(\eta\) divided by \(1 - \beta\)

Per-weight scale: the step divided by an estimate of the gradient’s size, elementwise
Adagrad: \(\mathbf{s}_t = \mathbf{s}_{t-1} + \mathbf{g}_t^2\), step \(\eta\, \mathbf{g}_t / (\sqrt{\mathbf{s}_t} + \delta)\)
RMSprop: a running average in place of the sum
\[\mathbf{v}_t = \beta_2\, \mathbf{v}_{t-1} + (1 - \beta_2)\, \mathbf{g}_t^2, \qquad \mathbf{w} \leftarrow \mathbf{w} - \eta\, \frac{\mathbf{g}_t}{\sqrt{\mathbf{v}_t} + \delta}\]
Valley: similar step sizes across and along

Adam (Kingma and Ba 2015): momentum as an average, RMSprop’s scale
\[\mathbf{m}_t = \beta_1 \mathbf{m}_{t-1} + (1 - \beta_1)\, \mathbf{g}_t, \qquad \mathbf{v}_t = \beta_2 \mathbf{v}_{t-1} + (1 - \beta_2)\, \mathbf{g}_t^2\]
\[\hat{\mathbf{m}}_t = \frac{\mathbf{m}_t}{1 - \beta_1^t}, \qquad \hat{\mathbf{v}}_t = \frac{\mathbf{v}_t}{1 - \beta_2^t}, \qquad \mathbf{w} \leftarrow \mathbf{w} - \eta\, \frac{\hat{\mathbf{m}}_t}{\sqrt{\hat{\mathbf{v}}_t} + \delta}\]
Started at zero, steady gradient \(g\): \(m_t = (1 - \beta_1^t)\, g\), \(v_t = (1 - \beta_2^t)\, g^2\)
Correction: division by \(1 - \beta^t\), exact for a steady gradient

Loss multiplied by \(c\): every gradient multiplied by \(c\)
Consequence
\(\beta_1 = \beta_2 = 0\): the step \(\eta\, \operatorname{sign}(\mathbf{g})\), SignSGD, every weight moved by \(\eta\)

Optimizer state: opt.state[p], per parameter tensor
momentum_buffer, \(\mathbf{m}\)exp_avg \(\mathbf{m}\), exp_avg_sq \(\mathbf{v}\), step \(t\)Memory: Adam’s state, twice the size of the weights
Resuming training from a checkpoint needs the state
step ()
exp_avg (10, 784)
exp_avg_sq (10, 784)

Same network, data, and batch order, one \(\eta\) per optimizer, not tuned
Training loss at the end, two seeds
Validation loss at the end: within the seed-to-seed spread
L2 penalty \(\tfrac{\lambda}{2}\|\mathbf{w}\|^2\) added to the loss, SGD step

\[\mathbf{w} \leftarrow \mathbf{w} - \eta\,(\mathbf{g} + \lambda \mathbf{w}) = (1 - \eta\lambda)\,\mathbf{w} - \eta\,\mathbf{g}\]
Weight decay: every weight \(\times (1 - \eta\lambda)\) each step, applied outside the loss
SGD(weight_decay=λ): the same updateAdam, for each weight

\[\mathbf{m}_t = \beta_1 \mathbf{m}_{t-1} + (1 - \beta_1)\,\mathbf{g}_t\]
\[\mathbf{v}_t = \beta_2 \mathbf{v}_{t-1} + (1 - \beta_2)\,\mathbf{g}_t^2\]
\[\mathbf{w} \leftarrow \mathbf{w} - \eta\, \frac{\hat{\mathbf{m}}_t}{\sqrt{\hat{\mathbf{v}}_t} + \delta}\]
Adam with an L2 penalty: \(\lambda \mathbf{w}\) inside \(\mathbf{g}_t\)
\[\text{decay rate per step} \approx \frac{\eta\lambda}{\sqrt{\hat{v}} + \delta}\]
Gradient RMS \(\sqrt{\hat{v}}\), FashionMNIST, Adam, first layer, end of training

Decoupled weight decay (Loshchilov and Hutter 2019): decay outside the running averages
\[\mathbf{w} \leftarrow (1 - \eta\lambda)\, \mathbf{w} - \eta\, \frac{\hat{\mathbf{m}}_t}{\sqrt{\hat{\mathbf{v}}_t} + \delta}\]
weight_decay in PyTorch
Adam: L2 penalty, inside \(\mathbf{g}_t\), default \(0\)AdamW: decoupled, default \(0.01\)

Each form at its best \(\lambda\) (Loshchilov and Hutter 2019)
First-layer weights, per input pixel
Batch norm: output independent of the weight scale
Step relative to the weights: \(\|\Delta \mathbf{w}\| = \eta \|\mathbf{g}\| \propto \eta / \|\mathbf{w}\|\)
\[\frac{\|\Delta \mathbf{w}\|}{\|\mathbf{w}\|} \propto \frac{\eta}{\|\mathbf{w}\|^2}\]
\(\|\mathbf{W}\|\): norm of both hidden weight matrices, SGD \(\eta = 0.1\), \(20{,}000\) steps

Batch-normalized layers: shrinking \(\mathbf{w}\) leaves the output unchanged
Raising \(\eta\) without decay: \(\|\mathbf{w}\|\) grows with it
Weight decay \(\lambda = 5 \times 10^{-3}\), \(\eta = 0.1\): effective rate \(2.3 \times 10^{-3}\)
Output layer, no batch norm: weight decay is an L2 penalty

Noise floor: the level SGD levels off at with a constant \(\eta\), above the minimum, because minibatch gradients are noisy
\[\mathbb{E}\big[\|\mathbf{w}_t - \mathbf{w}^*\|^2\big] \le (1 - \eta\mu)^t \|\mathbf{w}_0 - \mathbf{w}^*\|^2 + O\Big(\frac{\eta\, \sigma_g^2}{\mu}\Big)\]
Logistic regression, FashionMNIST, SGD, training loss after \(15\) epochs


Learning-rate schedule: \(\eta_t\), the learning rate as a function of the step
Noise floor: proportional to the current \(\eta\)
Step decay, \(\eta \times 0.1\) at epochs \(10\) and \(20\), SGD with momentum
sched.step() once per epoch: milestones count epochs
Noise floor at the end: proportional to the final \(\eta\)
Validation loss after \(15\) epochs (\(T\) steps), MLP, \(\eta_0 = 0.1\)
Cosine: \(\eta_t = \tfrac{\eta_0}{2}\big(1 + \cos(\pi t / T)\big)\)
\(\eta_0/(1 + \kappa t)\): decays as \(1/t\), equal to \(\eta_0\) at \(t = 0\)
In PyTorch
MultiStepLR(opt, milestones, gamma)LambdaLR(opt, lambda t: 1 / (1 + kappa * t))CosineAnnealingLR(opt, T_max)
Noise floor: proportional to the current \(\eta\), rising or falling
Warm restarts (SGDR): \(\eta\) reset to \(\eta_0\), then a new cosine decay
Measured, MLP, training loss at each restart
Schedules that raise \(\eta\)
Adam’s step, per weight: \(\eta\, \hat{m}_t / \sqrt{\hat{v}_t}\)
Simulated gradients, a small mean plus unit noise per weight, mean step size in units of \(\eta\)
Warmup: \(\eta_t = \eta \cdot \min(1,\ t / t_w)\), over the first \(t_w\) steps

Clipping by norm, threshold \(c\)
\[\mathbf{g} \leftarrow \mathbf{g} \cdot \min\Big(1,\ \frac{c}{\|\mathbf{g}\|}\Big)\]
Clipping by value: each component clipped to \([-c, c]\)

Gradient descent on a quadratic with curvature \(h\): stable for \(\eta h < 2\)
Deep network: the gradient is a product of the layers’ weights and slopes
Clipping: next step length at most \(\eta c\), whatever the gradient
Four hidden layers of \(256\) units, SGD \(\eta = 1.0\), one epoch

Cosine and step decay: \(T\) set before the first step
Cosine from \(0.1\), validation loss at epoch \(5\)
\(T\) too short: \(\eta\) near \(0\) while the loss is still falling
Hyperparameters of a schedule, chosen by rule of thumb before training
Training length

Hyperparameter \(h\): a setting that training does not adjust
Two nested problems
\[h^* = \arg\min_h\ \mathcal{L}_{\text{val}}\big(\mathbf{w}^*(h)\big), \qquad \mathbf{w}^*(h) = \arg\min_{\mathbf{w}}\ \mathcal{L}_{\text{train}}(\mathbf{w};\, h)\]
Outer objective on validation data


Grid search: \(k\) values of each of \(d\) hyperparameters, every combination, \(k^d\) runs
Measured, \(4 \times 4\) grid, validation loss after \(10\) epochs
Effective dimension: the loss depends on few of the hyperparameters

Random search (Bergstra and Bengio 2012): each setting drawn at random, independently per hyperparameter
\(N\) runs
Measured, \(16\) runs each

Range searched: \(\eta\) from \(0.001\) to \(0.3\), \(2.5\) orders of magnitude
Linear-uniform sampling on \([0.001, 0.3]\)
Log-uniform sampling: \(\log \eta\) uniform

Most settings are poor: of \(32\), the poor ones are already poor after \(1\) epoch
Rank agreement with the final validation loss, \(32\) runs (Spearman)
Successive halving (Jamieson and Talwalkar 2016): every setting trained briefly, the better half continued, repeated
Its assumption: early rank predicts final rank
Seed: the random start and the batch order
One setting, \(8\) seeds, \(\eta = 0.03\), \(\lambda = 10^{-4}\)
Changing \(\lambda\) to \(10^{-3}\): mean validation loss up by \(0.0019\)

Paired comparison: both settings run with the same seeds, the difference taken seed by seed
\[\mathrm{Var}(L_B - L_A) = \mathrm{Var}(L_A) + \mathrm{Var}(L_B) - 2\,\mathrm{Cov}(L_A, L_B)\]
Measured, the same \(8\) seeds, \(\lambda = 10^{-3}\) minus \(\lambda = 10^{-4}\)

Choosing the minimum of \(N\) noisy validation losses: the chosen value is low partly by chance
Consequence: the chosen setting’s validation loss overstates its quality

Runs to resolve a difference \(\Delta\) at two standard errors
Measured spreads: \(\sigma = 0.012\), \(\sigma_d = 0.0003\)
Every hyperparameter searched multiplies the settings, every small effect multiplies the seeds
