{"record":{"id":"e2af2e8509a5cc31","repo":"d2l-ai/d2l-zh","slug":"train-loss-0-5-e2af2e","errorCode":null,"errorMessage":"train_loss < 0.5","messagePattern":"train_loss < 0\\.5","errorType":"validation","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"d2l/tensorflow.py","lineNumber":319,"sourceCode":"        self.axes[0].cla()\n        for x, y, fmt in zip(self.X, self.Y, self.fmts):\n            self.axes[0].plot(x, y, fmt)\n        self.config_axes()\n        display.display(self.fig)\n        display.clear_output(wait=True)\n\ndef train_ch3(net, train_iter, test_iter, loss, num_epochs, updater):\n    \"\"\"训练模型（定义见第3章）\n\n    Defined in :numref:`sec_softmax_scratch`\"\"\"\n    animator = Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9],\n                        legend=['train loss', 'train acc', 'test acc'])\n    for epoch in range(num_epochs):\n        train_metrics = train_epoch_ch3(net, train_iter, loss, updater)\n        test_acc = evaluate_accuracy(net, test_iter)\n        animator.add(epoch + 1, train_metrics + (test_acc,))\n    train_loss, train_acc = train_metrics\n    assert train_loss < 0.5, train_loss\n    assert train_acc <= 1 and train_acc > 0.7, train_acc\n    assert test_acc <= 1 and test_acc > 0.7, test_acc\n\nclass Updater():\n    \"\"\"用小批量随机梯度下降法更新参数\n\n    Defined in :numref:`sec_softmax_scratch`\"\"\"\n    def __init__(self, params, lr):\n        self.params = params\n        self.lr = lr\n\n    def __call__(self, batch_size, grads):\n        d2l.sgd(self.params, grads, self.lr, batch_size)\n\ndef predict_ch3(net, test_iter, n=6):\n    \"\"\"预测标签（定义见第3章）\n\n    Defined in :numref:`sec_softmax_scratch`\"\"\"","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/d2l-ai/d2l-zh/blob/e6b18ccea71451a55fcd861d7b96fddf2587b09a/d2l/tensorflow.py#L301-L337","documentation":"An AssertionError raised at the end of d2l.tensorflow.train_ch3, the chapter-3 softmax-regression training loop. After num_epochs finish, it sanity-checks the final training metrics; train_loss must be below 0.5 for Fashion-MNIST softmax regression. If the loss is >= 0.5 the model diverged or undertrained, and the assert converts that into a loud failure instead of silently returning bad weights.","triggerScenarios":"Running train_ch3 with an lr that is too large (divergence) or too small/too few epochs (undertrained); passing a fresh net whose weights were never trained because updater was a no-op; calling train_ch3 with a different loss (e.g. unaveraged sum reduction) so the reported metric scale is wrong; running on a tiny subset of Fashion-MNIST.","commonSituations":"Users experimenting with learning rates (e.g. lr=10) or batch sizes in the sec_softmax_scratch notebook; replacing the Updater with one that forgets to divide by batch_size, inflating the loss; TF version changes altering default loss reduction; training a deeper/worse model through the same helper.","solutions":["Use the book's standard hyperparameters for softmax regression: lr=0.1 (or 0.03 for from-scratch SGD on Fashion-MNIST), batch_size=256, num_epochs=10.","If you wrote your own updater, make sure gradients are averaged per batch (divide by batch_size) as the d2l.Updater does.","Verify the loss uses reduction='mean' (d2l.loss: tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True, reduction='mean')).","Increase num_epochs or lower lr if the curve in the Animator is still descending or oscillating at the end."],"exampleFix":"# before\nupdater = Updater([W, b], lr=10.0)  # diverges -> AssertionError\n# after\nupdater = Updater([W, b], lr=0.1)\ntrain_ch3(net, train_iter, test_iter, loss, 10, updater)","handlingStrategy":"validation","validationCode":"loss_hist = []\nfor epoch in range(num_epochs):\n    train_metrics = train_epoch_ch3(net, train_iter, loss, updater)\n    loss_hist.append(train_metrics[0])\nif loss_hist[-1] >= 0.5:\n    raise ValueError(f'loss did not converge below 0.5: {loss_hist[-1]:.3f}; '\n                     f'check lr/updater and raise num_epochs')","typeGuard":null,"tryCatchPattern":"try:\n    train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)\nexcept AssertionError as e:\n    raise RuntimeError(f'train_ch3 sanity check failed (loss={e}); '\n                       f'verify lr=0.1, batch_size=256, mean-reduced loss') from e","preventionTips":["Start from the book's hyperparameters (lr=0.1, batch_size=256, num_epochs=10) before experimenting.","If writing a custom updater, verify gradients are divided by batch_size.","Use d2l.loss with reduction='mean' so the 0.5 threshold is meaningful.","Watch the Animator each epoch; fix divergence early instead of waiting for the final assert."],"tags":["d2l","tensorflow","training","softmax-regression","assertion","hyperparameters"],"backgroundTag":null,"analyzedSha":"e6b18ccea71451a55fcd861d7b96fddf2587b09a","analyzedAt":"2026-08-14T20:05:26.414Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}