d2l-ai/d2l-zh · error · AssertionError
train_loss < 0.5
Error message
train_loss < 0.5
What it means
This is a Python AssertionError raised by d2l.mxnet.train_ch3 after the training loop finishes. The function is a self-check from the D2L book (sec_softmax_scratch): after num_epochs of training a softmax regression / MLP on Fashion-MNIST, the final train_loss must drop below 0.5. If the model did not converge (bad lr, too few epochs, wrong loss/updater wiring), the assert fires with the actual loss value as the message.
Source
Thrown at d2l/mxnet.py:314
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
- Check the learning rate: use lr=0.1 (or d2l.sgd with the correct params) as in the book, and rerun
- Train for the full num_epochs=10 the section specifies instead of a shortened run
- Verify net, loss, updater come from the same framework (all mxnet) and the net's output dim equals the number of classes (10)
- If convergence is genuinely slow, lower lr or switch to Trainer-based d2l.train_ch3 counterparts, then only re-enable the assert once metrics stabilize
Example fix
// before
updater = lambda params: d2l.sgd(params, lr=10.0, batch_size=256)
train_ch3(net, train_iter, test_iter, loss, 10, updater) # AssertionError: train_loss
// after
batch_size = 256
trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': 0.1})
updater = lambda batch_size: d2l.sgd(net.collect_params().values(), lr=0.1, batch_size=batch_size)
train_ch3(net, train_iter, test_iter, loss, 10, updater) # converges, loss < 0.5 Defensive patterns
Strategy: validation
Validate before calling
# before calling train_ch3, verify hyperparameters and one-batch loss decrease
lr, num_epochs = 0.1, 10
assert num_epochs >= 10, 'book setting needs >=10 epochs'
assert 0.01 <= lr <= 0.5, f'suspicious lr={lr}'
assert len(updater_params) > 0, 'updater has no parameters to optimize'
# one-batch smoke: loss should backprop without error
for X, y in train_iter:
l = loss(net(X), y)
break Type guard
def is_converged_config(num_epochs: int, lr: float, n_classes: int = 10) -> bool:
return num_epochs >= 10 and 0.01 <= lr <= 0.5 and n_classes == 10 Try / catch
try:
train_ch3(net, train_iter, test_iter, loss, 10, updater)
except AssertionError as e:
print(f'training did not converge (train_loss={e.args[0]}); check lr/updater/epochs')
raise Prevention
- Pin the book's hyperparameters (lr=0.1, epochs=10, batch=256) before trusting the asserts
- Run a one-batch forward/backward smoke test before the full loop
- Ensure net, loss, updater all come from the mxnet d2l module
- Never shorten num_epochs in CI runs that include train_ch3's built-in asserts
When it happens
Trigger: Calling train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater) with an SGD updater whose learning rate is too large/small (e.g. 10.0 or 0.001 when 0.1 is expected), num_epochs < 10, a net whose output dimension does not match 10 Fashion-MNIST classes, or an updater from a different framework flavor (torch sgd passed to the mxnet train_ch3).
Common situations: Running the D2L chapter 3 notebooks in a fresh environment with mxnet not GPU-accelerated so the user cuts num_epochs to 1-3; typos in the lr schedule (d2l.sgd with wrong params list); using batch_size so large the loss plateaus; mixing d2l.torch and d2l.mxnet helpers in one session.
Related errors
- train_acc <= 1 and train_acc > 0.7
- train_loss < 0.5
- test_acc <= 1 and test_acc > 0.7
- train_acc <= 1 and train_acc > 0.7
- f"{name} 不存在于 {DATA_HUB}"
AI-assisted analysis of d2l-ai/d2l-zh@e6b18ccea7 (2026-08-14).
Data as JSON: /api/errors/8538064b4e0f8f60.
Report an issue: GitHub.