Python
Matrix Multiplication
RuntimeError
Linear Algebra
Debugging

RuntimeError size mismatch m1 a x b, m2 c x d

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

The size mismatch runtime error in tensor frameworks usually means matrix multiplication was attempted with incompatible inner dimensions. In deep learning code, this often appears between flatten output and a linear layer, or after changing convolution settings without updating downstream shapes. The fastest fix is disciplined shape tracing, not trial-and-error edits.

Understand the Core Matrix Rule

For matrix multiplication between A and B:

  • A shape is m x n,
  • B shape is n x p,
  • output shape is m x p.

The inner dimensions must match. If they do not, frameworks raise errors such as size mismatch.

Minimal PyTorch example:

python
1import torch
2
3a = torch.randn(32, 64)
4b = torch.randn(128, 10)
5
6# Fails because 64 does not match 128.
7# c = a @ b
8
9print(a.shape, b.shape)

Most Common Deep Learning Cause

A very common failure path:

  1. convolution and pooling change feature map size,
  2. tensor is flattened,
  3. nn.Linear(in_features, out_features) still uses old in_features.

If flatten size is wrong, first linear layer fails immediately.

python
1import torch
2import torch.nn as nn
3
4class Net(nn.Module):
5    def __init__(self):
6        super().__init__()
7        self.conv = nn.Conv2d(3, 8, kernel_size=3)
8        self.pool = nn.MaxPool2d(2)
9        self.fc = nn.Linear(8 * 15 * 15, 10)  # must match real flatten size
10
11    def forward(self, x):
12        x = self.pool(self.conv(x))
13        x = torch.flatten(x, 1)
14        return self.fc(x)

The 8 * 15 * 15 value depends on input resolution and upstream layer parameters.

Shape Debugging Workflow

Use explicit shape prints or assertions at module boundaries.

python
1
2def debug_forward(model, x):
3    with torch.no_grad():
4        y = model.conv(x)
5        print("after conv", y.shape)
6        y = model.pool(y)
7        print("after pool", y.shape)
8        y = torch.flatten(y, 1)
9        print("after flatten", y.shape)
10
11x = torch.randn(4, 3, 32, 32)

For production-quality checks, raise descriptive errors early.

python
if y.shape[1] != model.fc.in_features:
    raise ValueError(f"expected {model.fc.in_features}, got {y.shape[1]}")

This turns opaque runtime crashes into actionable diagnostics.

Robust Fix Patterns

Useful ways to avoid manual mistakes:

  • compute flatten size with a dummy forward pass in model init,
  • use adaptive pooling to normalize spatial dimensions,
  • keep shape-transform logic in one helper method.

Dummy-pass pattern:

python
1class SafeNet(nn.Module):
2    def __init__(self):
3        super().__init__()
4        self.features = nn.Sequential(
5            nn.Conv2d(3, 8, 3),
6            nn.ReLU(),
7            nn.MaxPool2d(2),
8        )
9        with torch.no_grad():
10            dummy = torch.zeros(1, 3, 32, 32)
11            n = torch.flatten(self.features(dummy), 1).shape[1]
12        self.fc = nn.Linear(n, 10)
13
14    def forward(self, x):
15        x = self.features(x)
16        x = torch.flatten(x, 1)
17        return self.fc(x)

This is safer when upstream architecture changes often.

Batch and Sequence Shape Confusion

Another frequent source is swapped dimensions in sequence models.

Example confusion:

  • expected batch x features,
  • got sequence x batch x features.

Always document expected shape convention per module and keep it consistent.

Quick Shape Assertions in Training Loops

In custom training loops, add lightweight assertions before forward pass and before loss computation. Early checks prevent long runs from failing deep in the stack.

python
1def assert_batch_feature(x, expected_features):
2    if x.dim() != 2:
3        raise ValueError(f\"expected rank-2 tensor, got rank {x.dim()}\")
4    if x.shape[1] != expected_features:
5        raise ValueError(f\"expected feature size {expected_features}, got {x.shape[1]}\")

These guards are especially useful when input preprocessing changes independently from model code.

Common Pitfalls

  • Editing conv or pooling layers without updating linear input size.
  • Using incorrect flatten call and collapsing batch dimension by accident.
  • Assuming input image size never changes across data loaders.
  • Ignoring dimension ordering conventions in sequence models.
  • Debugging only final error line instead of tracing intermediate shapes.

Summary

  • Size mismatch errors are shape-contract violations, not random runtime issues.
  • Inner dimensions must align for matrix multiplication.
  • Trace shapes at each stage, especially before linear layers.
  • Use adaptive patterns or dummy-forward computation to prevent manual misconfiguration.
  • Keep explicit shape conventions and assertions to make failures easy to diagnose.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms