d2l-ai/d2l-zh · error · AssertionError

test_acc <= 1 and test_acc > 0.7

Error message

test_acc <= 1 and test_acc > 0.7

What it means

Python AssertionError from d2l.mxnet.train_ch3's final sanity check: test accuracy must be in (0.7, 1] after training on Fashion-MNIST. It verifies the trained model generalizes as the book claims (~0.83 test acc); failure means underfitting, divergence, or an evaluation-path bug rather than a library defect.

Source

Thrown at d2l/mxnet.py:316

            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):
    """评估给定数据集上模型的损失

    Defined in :numref:`sec_model_selection`"""
    metric = d2l.Accumulator(2)  # 损失的总和,样本数量

View on GitHub (pinned to e6b18ccea7)

Solutions

  1. Rerun with the book's hyperparameters: num_epochs=10, lr=0.1, batch_size=256, and a freshly initialized net
  2. Verify net.initialize(mx.init.Xavier()) executed before training/eval
  3. Rebuild test_iter with the same transforms as train_iter (only shuffle differs)
  4. If the animator shows good train acc but ~0.1 test acc, check that evaluate_accuracy uses the same net instance and that test labels are not one-hot when argmax comparison expects an index

Example fix

// before
net = d2l.Sequential()  # never initialized, random weights
train_ch3(net, train_iter, test_iter, loss, 10, updater)  # test_acc ~0.1 -> AssertionError
// after
net.initialize()
train_ch3(net, train_iter, test_iter, loss, 10, updater)  # test_acc ~0.83
Defensive patterns

Strategy: validation

Validate before calling

# pre-check evaluation path and data consistency
assert evaluate_accuracy(net, train_iter) is not None
assert same_transforms(train_iter, test_iter), 'train/test transforms differ'
net.initialize()  # ensure parameters exist before eval
acc0 = evaluate_accuracy(net, test_iter)
assert 0 <= acc0 <= 1, 'sanity: random-init accuracy should be ~0.1'

Type guard

def evaluation_ready(net, test_iter) -> bool:
    return any(True for _ in iter(test_iter)) and net.collect_params() is not None

Try / catch

try:
    train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
except AssertionError as e:
    print(f'test_acc out of (0.7, 1]: {e.args[0]}')
    raise
finally:
    print('animator history saved for inspection')

Prevention

When it happens

Trigger: Calling train_ch3 then having evaluate_accuracy(net, test_iter) return <= 0.7: too few epochs, diverged lr, net evaluated before parameters were initialized, or test_iter built with a different normalization than train_iter (e.g. transform applied to only one of the two).

Common situations: CPU-only environments where users trim num_epochs; reusing a net across notebook runs without re-initialization so it was already overfit/corrupted; batch_size or shuffle differences between train_iter and test_iter; using the mxnet loop on data already consumed as a torch DataLoader (empty iterator -> accuracy 0).

Related errors


AI-assisted analysis of d2l-ai/d2l-zh@e6b18ccea7 (2026-08-14). Data as JSON: /api/errors/4247601219bee41a. Report an issue: GitHub.