C.W.K.
Stream
Lesson 05 of 08 · published

Matrix Multiplication: The Ritual of Combining Spells

~10 min · matrix-multiplication, broadcasting, shapes

Level 0Math Novice
0 XP0/59 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete

Why It's Not Element-Wise

Adding matrices is element-wise — easy. Multiplying matrices is not element-wise. It's a careful dance of rows and columns: each cell of the output is the dot product of one row of the left matrix and one column of the right matrix.

The shape rule: . Inner dimensions must match; outer dimensions form the result. Get this rule wrong and your code crashes; get it right and you've built a neural network layer.

Composing Transformations

Matrix multiplication encodes composing transformations. Rotate, then scale, then translate — each is a matrix; multiplying them gives a single matrix that does all three at once. Order matters: is generally not equal to . Rotate-then-scale ≠ scale-then-rotate (in 3D, vividly so).

Broadcasting Sneaks Back In

NumPy/PyTorch let you "multiply" a matrix by a vector with * (element-wise) — and broadcasting will silently apply the vector across rows or columns of the matrix. This is not matrix multiplication; it's element-wise op with broadcasting. Use @ for true matrix multiplication.

The bug that bit me. Early in deep-learning work I wrote output = weights * inputs in a forward pass. The shapes happened to broadcast, the loss came out as a number, training even improved a bit. It took an hour to realize my "linear layer" was element-wise multiplication and not a real linear transformation. Use @. Every time.

Code

The two operations that look similar and aren't·python
import numpy as np

A = np.array([[1, 2],
              [3, 4]])
B = np.array([[5, 6],
              [7, 8]])

# Element-wise — wrong for linear layers
print(A * B)          # [[ 5 12] [21 32]]

# Matrix multiplication — what neural networks do
print(A @ B)          # [[19 22] [43 50]]

# Verify by hand on (0, 0): 1*5 + 2*7 = 19 ✓
Composition is multiplication, order matters·python
import torch

# Composing transformations: rotate-then-scale
theta = np.pi / 4
R = torch.tensor([[np.cos(theta), -np.sin(theta)],
                  [np.sin(theta),  np.cos(theta)]], dtype=torch.float32)
S = torch.tensor([[2.0, 0.0],
                  [0.0, 0.5]])

# Composite transformation: rotate first, then scale
T = S @ R                       # apply R first, then S (read right to left)
v = torch.tensor([1.0, 0.0])
print(T @ v)                    # [√2, √2/2] — rotated 45° then scaled

External links

Exercise

Define a 90° rotation matrix R and a doubling scale matrix S. Compute R @ S and S @ R applied to vector [1, 0]. Are the results the same? Explain in one sentence why or why not.
Hint
R = [[0, -1], [1, 0]], S = 2*np.eye(2). Both produce the same result for these specific matrices because S is a scalar multiple of identity (it commutes with everything). Try with a non-uniform scaling like diag([2, 0.5]) and the order will matter.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 2

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.
  1. Elechemist
    Elechemist

    import numpy as np

    R = np.array([[0., -1.], [1., 0.]]) S = np.array([[2., 0.], [0., 2.]]) v = np.array([1., 0.])

    print('(R @ S) @ v =', (R @ S) @ v) print('(S @ R) @ v =', (S @ R) @ v) print('same:', np.allclose((R @ S) @ v, (S @ R) @ v))

    💛 by Pippawarm
    1. Pippa
      Pippa· warmElechemistElechemist

      좋아요. 여기서는 S2I라서 모든 방향을 똑같이 키우는 균일 스케일이고, 그래서 R @ SS @ R 결과가 같아요. S = np.diag([2., 0.5])처럼 방향마다 다르게 스케일하면 순서 차이가 바로 보일 거예요.