Linear algebra for LLMsPart 4: Tensors, shapes and einsum

Broadcasting

7 min

The rule

padded on the left to (1, 1, 4)
  1. Line the shapes up from the right; missing axes on the left count as size 1.
  2. Each pair of sizes must be equal, or one of them must be 1.
  3. Size-1 axes stretch to match. Nothing is copied; the same numbers are reused.

Write

Align from the right. Sizes must match or be 1. Size 1 stretches.

Adding a bias to every token

+=

bb has shape (4,)(4,), padded to (1,4)(1, 4), then stretched down all 3 rows. Every token gets the same bias. With a batch, (B,T,d)+(d,)(B, T, d) + (d,) works the same way.

Two stretches at once

+=

A column and a row both stretch: (3,1)+(1,4)→(3,4)(3, 1) + (1, 4) \to (3, 4). Entry (i,j)(i, j) is ai+bja_i + b_j, an “outer sum”.

Shapes that broadcast, and one that doesn't

  • (B,T,d)+(d,)→(B,T,d)(B, T, d) + (d,) \to (B, T, d): a bias or gain.
  • (B,h,T,T)+(T,T)→(B,h,T,T)(B, h, T, T) + (T, T) \to (B, h, T, T): the causal mask.
  • (B,T,d)×(B,T,1)→(B,T,d)(B, T, d) \times (B, T, 1) \to (B, T, d): one scale per token (norms).
  • (B,T,d)+(T,)(B, T, d) + (T,): an error, unless T=dT = d happens to hold.

Write

Mask (T,T)(T, T) broadcasts over (B,h)(B, h). Per-token scale needs (B,T,1)(B, T, 1).

The silent bug: (T,) is not (T, 1)

row maxima S−m  =S - m \;= wrongS−m[:, None]=S - m_{[:,\,\text{None}]} = right

You want to subtract each row’s maximum. mm has shape (2,)(2,), which aligns with the last axis: it subtracts mjm_j from column jj. With a square matrix the shapes still fit, so nothing complains. Keeping the axis, shape (2,1)(2, 1), subtracts per row.

Write

Reductions you broadcast back need keepdim=True: (T,1)(T, 1), not (T,)(T,).

✏️ Your turn

Broadcast or not?

(4,1,3)+(5,3)=  ?\displaystyle (4, 1, 3) + (5, 3) = \;?
(2,3)+(3,2)=  ?\displaystyle (2, 3) + (3, 2) = \;?

Line them up from the right and write each result shape, or “error”.

Work it out on paper, then go to the next card to check.

Answer

(4,1,3)+(1,5,3)=(4,5,3)\displaystyle (4, 1, 3) + (1, 5, 3) = (4, 5, 3)
(2,3)+(3,2):  3 vs 2  ⇒  error\displaystyle (2, 3) + (3, 2): \;3 \text{ vs } 2 \;\Rightarrow\; \text{error}

(5,3)(5, 3) is padded to (1,5,3)(1, 5, 3); the 1s stretch. In the second, the last axes are 3 and 2: neither is 1.

In PyTorch

x + bias                                   # (B, T, d) + (d,)
scores + mask                              # (B, h, T, T) + (T, T)
x / x.norm(dim=-1, keepdim=True)           # (B, T, d) / (B, T, 1)
torch.broadcast_shapes((4, 1, 3), (5, 3))  # (4, 5, 3)

📌 Recap

Broadcasting in one card

  • Align shapes from the right; sizes must match or be 1; size 1 stretches.
  • Bias (d,)(d,), mask (T,T)(T, T) and per-token scale (B,T,1)(B, T, 1) all broadcast.
  • (T,)(T,) aligns with the last axis. Keep reduced axes (keepdim=True) before broadcasting back.

Write

The three lines above.