d2l-ai/d2l-zh · error · AssertionError
train_loss < 0.5
Error message
train_loss < 0.5
What it means
An AssertionError raised at the end of d2l.paddle.train_ch3, the PaddlePaddle edition of the chapter-3 softmax-regression training loop. After the final epoch it requires train_loss < 0.5 on Fashion-MNIST; a value >= 0.5 means the model diverged or undertrained, and the assert turns that into an immediate failure.
Source
Thrown at d2l/paddle.py:350
self.axes[0].cla()
for x, y, fmt in zip(self.X, self.Y, self.fmts):
self.axes[0].plot(x, y, fmt)
self.config_axes()
display.display(self.fig)
display.clear_output(wait=True)
def train_ch3(net, train_iter, test_iter, loss, num_epochs, updater):
"""训练模型(定义见第3章)
Defined in :numref:`sec_softmax_scratch`"""
animator = Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9],
legend=['train loss', 'train acc', 'test acc'])
for epoch in range(num_epochs):
train_metrics = train_epoch_ch3(net, train_iter, loss, updater)
test_acc = evaluate_accuracy(net, test_iter)
animator.add(epoch + 1, train_metrics + (test_acc,))
train_loss, train_acc = train_metrics
assert train_loss < 0.5, train_loss
assert train_acc <= 1 and train_acc > 0.7, train_acc
assert test_acc <= 1 and test_acc > 0.7, test_acc
def predict_ch3(net, test_iter, n=6):
"""预测标签(定义见第3章)
Defined in :numref:`sec_softmax_scratch`"""
for X, y in test_iter:
break
trues = d2l.get_fashion_mnist_labels(y)
preds = d2l.get_fashion_mnist_labels(d2l.argmax(net(X), axis=1))
titles = [true +'\n' + pred for true, pred in zip(trues, preds)]
d2l.show_images(
d2l.reshape(X[0:n], (n, 28, 28)), 1, n, titles=titles[0:n])
def evaluate_loss(net, data_iter, loss):
"""评估给定数据集上模型的损失。
View on GitHub (pinned to e6b18ccea7)
Solutions
- Restore the book's hyperparameters: lr=0.1 (from-scratch SGD), batch_size=256, num_epochs=10.
- Ensure the updater averages gradients over the batch (divide summed gradients by batch_size) exactly like d2l.Updater/paddle.sgd.
- Use the default loss (paddle regularized cross-entropy with mean reduction) so the 0.5 threshold is comparable.
- Watch the Animator: if loss is still falling at the last epoch, raise num_epochs; if it spikes, lower lr.
Example fix
# before updater = Updater([W, b], lr=5.0) # divergence -> AssertionError # after updater = Updater([W, b], lr=0.1) train_ch3(net, train_iter, test_iter, loss, 10, updater)
Defensive patterns
Strategy: validation
Validate before calling
final = train_epoch_ch3(net, train_iter, loss, updater)
if final[0] >= 0.5:
raise ValueError(f'loss={final[0]:.3f} >= 0.5; check lr (try 0.1), '
f'batch-averaged gradients, and num_epochs=10') Try / catch
try:
train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
except AssertionError as e:
raise RuntimeError(f'Paddle train_ch3 loss check failed ({e}); '
f'verify lr=0.1 and mean-reduced loss') from e Prevention
- Default to lr=0.1, batch_size=256, num_epochs=10 for Fashion-MNIST softmax regression.
- In custom Paddle updaters, divide accumulated gradients by batch_size.
- Confirm paddle's loss uses mean reduction so the 0.5 threshold applies.
- Inspect the Animator per epoch rather than waiting for the final assert.
When it happens
Trigger: Running train_ch3 with too-large lr (loss oscillates or explodes), too-small lr, or too few epochs; a custom updater that fails to average gradients per batch; loss reduction differences across Paddle versions scaling the reported loss upward.
Common situations: Modifying the sec_softmax_scratch notebook's lr/batch_size; writing a Paddle updater that skips param gradient application (clear_gradients/set_state_dict mistakes); training on a small slice of the dataset where convergence stalls above 0.5.
Related errors
- train_loss < 0.5
- train_acc <= 1 and train_acc > 0.7
- test_acc <= 1 and test_acc > 0.7
- train_loss < 0.5
- train_acc <= 1 and train_acc > 0.7
AI-assisted analysis of d2l-ai/d2l-zh@e6b18ccea7 (2026-08-14).
Data as JSON: /api/errors/98f02b66384a0ebf.
Report an issue: GitHub.