Skip to content
mlmentorship

The neural-network training recipe

Inspect data, verify updates, fit a known signal, then test generalization and tune within a declared budget.

Published · 6 min read ·Core ·Intermediate
Reading depth

Summary

A training recipe orders evidence checks before expensive changes: inspect, build a baseline, fit, regularize, tune and refine. Passing a fitting check does not establish generalization.

Consider 32 distinct separable inputs, eight per class, with four classes and no regularization. Zero logits predict each class with probability , giving mean cross-entropy . Suppose gradients are nonzero but parameters never change. Should you search architectures, or inspect the update path?

Return to the earliest failed check

A nonzero gradient does not prove that the intended parameters changed

A nonzero gradient does not prove that the intended weights changedThe recipe produces gradient 0.8 but observed parameter change zero. Check the actual optimizer-bound parameters and step receipt.A computed gradient is not yet anapplied update0.8nonzerogradient0delta weightsTiny-batch loss stays flat at 1.10.Diagnose the step before full-datageneralization.
Derivation
A nonzero gradient is not proof that the intended parameters changedAn illustrative known 32-example batch has flat loss 1.10, nonzero gradient norm 0.8, and zero maximum parameter change. The diagnostic checks the optimizer step, learning rate, and optimizer-bound parameter identities, then repeats the same fitting check before escalating to full data. The evidence narrows hypotheses without proving one cause.Illustrative known 32-example fitting checkLoss stays at 1.10 across updatessame batch / no regularizationgradient norm0.8: nonzeromax weightchange0: unchangedInspect step, learning rate, andoptimizer-bound parameters.Recheck the same batch before full-datatraining.
The gradient exists, but the intended weights do not move. Inspect update wiring and repeat the same batch. This evidence does not uniquely identify a cause.
Check: Which observed check blocks progression beyond the known batch? What measurement distinguishes the proposed causes?
Read it this way: The recipe produces gradient 0.8 but observed parameter change zero. Check the actual optimizer-bound parameters and step receipt.
What receipt is missing when gradient is 0.8 but weight change is zero?

References: Karpathy's recipe, Deep Learning practical methodology, and Bergstra and Bengio.

Check the update, then fit the known batch

With no update, the same fixed inputs retain the same predictions and loss. Inspect optimizer ownership, learning rate and step(), not only backward().

This complete CPU fixture separates gradient creation from a parameter update. Its 500-update budget and loss threshold are diagnostic choices, not convergence guarantees for other datasets.

import torch
from torch import nn

torch.manual_seed(0)
scales = torch.linspace(0.9, 1.1, 8).repeat(4)
inputs = torch.eye(4).repeat_interleave(8, dim=0) * scales[:, None]
targets = torch.arange(4).repeat_interleave(8)
model = nn.Linear(4, 4)
with torch.no_grad():
	model.weight.zero_()
	model.bias.zero_()
optimizer = torch.optim.Adam(model.parameters(), lr=0.05)
criterion = nn.CrossEntropyLoss()
model.train()

before = model.weight.detach().clone()
optimizer.zero_grad(set_to_none=True)
initial_loss = criterion(model(inputs), targets)
initial_loss.backward()
assert model.weight.grad.abs().sum().item() > 0
assert torch.equal(before, model.weight)
optimizer.step()
assert not torch.equal(before, model.weight)

for update in range(499):
	optimizer.zero_grad(set_to_none=True)
	loss = criterion(model(inputs), targets)
	loss.backward()
	optimizer.step()

model.eval()
with torch.no_grad():
	final_loss = criterion(model(inputs), targets)
assert final_loss.item() < 0.02
print(initial_loss.item(), final_loss.item())

A true-class probability of gives , below that illustrative threshold. Neither number establishes held-out performance.

Follow the evidence gates

StageEvidence before proceeding
InspectRaw and transformed examples, labels, duplicates, corruption, leakage and slice distributions
End-to-end baselineCheckable metrics, predictions, expected loss and correct updates
FitAppropriate known architecture can fit the attainable training signal
RegularizeHeld-out quality improves under task-valid interventions
TuneSearch space, budget, selection and all outcomes recorded
RefineLonger training, ensemble or distillation justified by measured value and cost

Change the prior or search purpose

1. Initialize a nonuniform prior

New task: class proportions become [0.7, 0.1, 0.1, 0.1].

Picture and change: use zero final-layer weights and biases , for positive priors. Softmax then predicts the declared proportions.

Check: mean loss at those frequencies is , not . That lower initial loss is not a bug.

Use when: a deliberate marginal baseline replaces uniform predictions.

New task: the verified pipeline has 12 tuning trials left.

Picture and change: sample learning rate and weight decay jointly over declared log ranges. For causal diagnosis, instead vary one factor under a matched comparison.

Check: a three-rate by four-decay grid tests only three rates. Twelve continuous random draws can explore twelve, but do not isolate a causal learning-rate effect.

Use when: broad search coverage, rather than an explanatory intervention, is the goal.

A tiny-batch failure is not always a bug

Two identical inputs with contradictory binary labels cannot both be fitted by a deterministic predictor. Their minimum mean cross-entropy is , reached by predicting one half. Inspect target consistency, capacity and the attainable loss before demanding zero.

Transfer to a binary baseline

For a 1% positive prior, must initial loss equal ?

Check your answer

No. With zero weights, bias predicts that prior. At matching class frequencies, binary entropy is about .

Step 1: Become one with the data

Inspect the exact transformed tensors and labels entering the model, not only raw files. Look for shortcuts, outliers and corruption.

Step 2: End-to-end skeleton + dumb baseline

Use simple, input-independent and task-appropriate human baselines. Track fixed predictions as well as loss. Simplify augmentation and regularization during diagnosis. Seeds help reproduce a comparison but do not guarantee determinism or generalization.

Step 3: Overfit

Prefer a known architecture while separating fitting from generalization. Adam near is a starting hypothesis for some tasks, not a correctness condition. Do not copy an epoch-based schedule without checking its update and data units.

Step 4: Regularize

Options include relevant clean data, valid augmentation, synthetic data, pretraining, smaller models, bottlenecks and lower input dimensionality. Also test weight decay, dropout and early stopping. Remove leakage before evaluation; it is not a regularization strategy. More data or a larger early-stopped model is not universally better.

Step 5: Tune

Random search can cover influential dimensions more effectively than a grid with repeated values. Bayesian optimization is another budget-dependent option. Preserve untouched confirmation data after adaptive selection.

Step 6: Squeeze the last drops

Evaluate longer training, ensembles and distillation against latency, memory, quality and compute budgets. No fixed ensemble gain or improvement from indefinite training is guaranteed.

What an interviewer expects you to say

Name the failed gate and the observation that would justify proceeding. For loop-state details, use the complete debugging fixture.

Common confusions

Initial loss depends on predictions, targets, weighting and reduction. Failed fitting, generalization and search are different problems. Use declared evidence and stopping rules, not remembered defaults.


Related: How would you debug a model that’s not learning?, Debug this training loop, How to choose a learning rate, Regularization, Exploding and vanishing gradients.