d2l-ai/d2l-zh · error · AssertionError

X.shape[0] == y.shape[0]

Error message

X.shape[0] == y.shape[0]

What it means

An AssertionError in d2l.paddle.split_batch verifying that the feature tensor X and label tensor y have identical first dimensions (batch size). split_batch scatters X and y across multiple GPU/CPU devices for multi-device training (sec_multi_gpu); mismatched batch sizes would misalign samples with labels on the devices, so it refuses to proceed.

Source

Thrown at d2l/paddle.py:1483

class Benchmark:
    """用于测量运行时间"""
    def __init__(self, description='Done'):
        """Defined in :numref:`sec_hybridize`"""
        self.description = description

    def __enter__(self):
        self.timer = d2l.Timer()
        return self

    def __exit__(self, *args):
        print(f'{self.description}: {self.timer.stop():.4f} sec')

def split_batch(X, y, devices):
    """将X和y拆分到多个设备上

    Defined in :numref:`sec_multi_gpu`"""
    assert X.shape[0] == y.shape[0]
    return (paddlescatter(X, devices),
            paddlescatter(y, devices))

def resnet18(num_classes, in_channels=1):
    """稍加修改的ResNet-18模型

    Defined in :numref:`sec_multi_gpu_concise`"""
    def resnet_block(in_channels, out_channels, num_residuals,
                     first_block=False):
        blk = []
        for i in range(num_residuals):
            if i == 0 and not first_block:
                blk.append(d2l.Residual(in_channels, out_channels,
                                        use_1x1conv=True, strides=2))
            else:
                blk.append(d2l.Residual(out_channels, out_channels))
        return nn.Sequential(*blk)

View on GitHub (pinned to e6b18ccea7)

Solutions

  1. Draw X and y from the same batch tuple: for X, y in train_iter: X, y = split_batch(X, y, devices) — never assemble them separately.
  2. If building batches manually, assert X.shape[0] == y.shape[0] yourself before split_batch with a message including both shapes.
  3. Fix custom collate/transpose functions that change one tensor's leading dimension (e.g. reshape without -1).
  4. Verify no drop_last=True/False asymmetry between multiple iterators feeding the same step.

Example fix

# before (X, y from different batches)
X = next(it_x); y = next(it_y)
split_batch(X, y, devices)  # AssertionError if sizes differ
# after (aligned batch)
for X, y in train_iter:
    X_shards, y_shards = split_batch(X, y, devices)
Defensive patterns

Strategy: validation

Validate before calling

if X.shape[0] != y.shape[0]:
    raise ValueError(f'batch size mismatch: X={X.shape[0]} vs y={y.shape[0]}; '
                     f'load X and y from the same batch tuple')
X_shards, y_shards = split_batch(X, y, devices)

Type guard

def is_aligned_batch(X, y) -> bool:
    return X.shape[0] == y.shape[0]

Try / catch

try:
    split_batch(X, y, devices)
except AssertionError:
    raise ValueError(f'X batch {X.shape[0]} != y batch {y.shape[0]}; '
                     f'check data pipeline alignment') from None

Prevention

When it happens

Trigger: Passing X and y produced by different data pipelines (e.g. y from a previous batch); a custom collate that pads X but not y; off-by-one slicing when manually batching (X = batch[:256], y = batch[1:257]); mixing a shuffled iterator for X with an unshuffled one for y.

Common situations: Hand-rolled training loops around train_batch_ch13/split_batch in the multi-GPU chapter; datasets where __getitem__ returns misaligned pairs; copying single-GPU code that never checked the invariant and only failing when moving to multiple devices.

Related errors


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