Topic 14.5
Vectors and Matrices: The Maths AI Runs On
In one line
A vector is a list of numbers that can describe anything from a point on a map to the meaning of a sentence. The dot product, norm, cosine similarity and matrix multiplication (@) are the four operations behind embeddings, search and every neural-network layer.
Think of it like this
Describing fruit with numbers. Give each fruit three scores: sweetness, sourness, crunch. Apple is [7, 3, 8], a lemon is [1, 9, 2], an orange [6, 5, 3]. Each fruit is now a vector, a point in a space with three directions. Fruit that taste alike sit close together. This is exactly how AI represents words, images and documents: as vectors called embeddings, with hundreds or thousands of numbers instead of three.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Vector
- A list of numbers, which you can think of as a point or an arrow in space.
- Activation function
- A simple function applied to each output of a layer. ReLU turns negatives into 0.
- Gradient
- The numbers that say which way, and how much, to nudge each weight to improve a model.
- Embedding
- A vector that represents the meaning of something, such as a word, sentence or image.
- Dot product
- Multiply matching positions of two vectors and add everything up: one number.
- Norm
- The length of a vector.
- Unit vector
- A vector of length 1.
- Cosine similarity
- How closely two vectors point in the same direction: from -1 to 1.
- Matrix multiplication
- Combine every row of one matrix with every column of another using dot products. Written A @ B.
- Transpose
- Swap rows and columns. Written A.T.
- Weights and bias
- The numbers a layer learns: W is multiplied with the inputs and b is added.
- Top-k
- The k items with the highest scores.
Step by step
01Dot product and length
v @ w for v = [3, 4] and w = [1, 2] is 3*1 + 4*2 = 11. np.linalg.norm(v) is sqrt(3*3 + 4*4) = 5. Divide by it to get [0.6, 0.8], a unit vector with length 1 that points the same way.
v = np.array([3.0, 4.0])
w = np.array([1.0, 2.0])
print(v @ w) # 11.0
print(np.linalg.norm(v)) # 5.0
print(v / np.linalg.norm(v)) # [0.6 0.8]02Matrix multiplication and its shape rule
A @ B for two (2, 2) matrices is a (2, 2) result where each entry is a dot product of a row of A and a column of B. In bill terms: each row of A is one shopper's basket, B holds prices, and every entry of the result is one finished bill. A * B is element-wise and gives a different answer. Shapes must satisfy (n, k) @ (k, m); (2, 3) @ (2, 3) fails because 3 does not equal 2, and NumPy says so in a matmul error.
03Embeddings are vectors
The example below uses tiny 4-number embeddings. They are invented to show the mechanics: real embeddings come from a model and have hundreds of numbers. "cat" and "kitten" point in almost the same direction (cosine 0.995), "car" does not (0.116).
04Top-k search in three lines
Normalise every row with emb / np.linalg.norm(emb, axis=1, keepdims=True). Then unit @ query is a vector of cosine scores, one per item (a (5, 4) @ (4,) product gives (5,)). np.argsort(-scores) lists indices from best to worst. The item that is the query itself comes first with score 1.0.
unit = emb / np.linalg.norm(emb, axis=1, keepdims=True)
scores = unit @ unit[0]
order = np.argsort(-scores)[:3]05A neural-network layer
The layer below takes 4 examples with 3 features and produces 2 outputs per example. W has shape (3, 2): 3 inputs by 2 outputs. b has shape (2,) and broadcasts. After ReLU, any negative output becomes 0. The weights here are random (seeded), but in a real network they are learned.
Try it yourself
- 1
Find the closest to dog
In the search example, set the query to the dog row (index 2) and print the top three. Does puppy come second, as you would expect?
- 2
Dot product of unit vectors
Check that
unit[0] @ unit[1]equals the cosine from the first line. Why do they match? - 3
Break the shape rule
In the layer example change
Wto shape(4, 2)and read the error. What mustW's first dimension be equal to?
Code & diagrams
Swap A and B in A @ B: the answer changes, because matrix multiplication is not commutative.
Expected output
dot: 11.0 11.0
norm: 5.0
unit: [0.6 0.8] length: 1.0
A @ B: [[2.0, 1.0], [4.0, 3.0]]
A * B: [[0.0, 2.0], [3.0, 0.0]]
A.T: [[1.0, 3.0], [2.0, 4.0]]
A @ I equals A: True
ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0These 4-number embeddings are made up to show the mechanics. Change the query to emb[3] (car) and see the order change.
Expected output
cat vs kitten: 0.995
cat vs car : 0.116
cat 1.000
kitten 0.995
puppy 0.656Change the shape of W to (3, 5) and watch the output shape and bias both need to become 5 long.
Expected output
X (4, 3) W (3, 2) b (2,) -> Z (4, 2)
after ReLU, negatives become 0: True
first row Z: [ 0.024 -0.633]
first row A: [0.024 0. ]The dot product is what a bill does: multiply each price by its quantity and add. Then the matrix form gives three shoppers' bills in one @, the same shape idea as a neural-network layer: (3 baskets, 3 items) @ (3 prices) gives 3 bills.
Expected output
line totals: [120. 84. 84.]
bill (dot product): 288.0
same by hand: 288.0
three bills: [288. 196. 300.]
shapes: (3, 3) @ (3,) -> (3,)Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Element-wise multiply instead of matrix multiply
Use * where @ is meant.
import numpy as np
X = np.ones((4, 3))
W = np.ones((3, 2))
print((X * W).shape)Myth vs fact
Myth
Embeddings are only for text.
Fact
Any item can be turned into a vector: images, audio, products, users, code. Similar items end up with nearby vectors.
Myth
Cosine similarity and dot product are the same thing.
Fact
They are equal only for unit vectors. Otherwise the dot product also depends on length.
Myth
A neural network is magic.
Fact
A layer is a matrix multiplication plus a bias plus a simple function. The skill is in how the numbers are learned.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Real vector databases do not score every row. They use approximate nearest-neighbour indexes (graph or clustering methods) that trade a small loss in recall for large speed-ups. The scoring maths is still dot products or cosine.
- ▸
Matrix multiplication costs about
n * k * mmultiplications. NumPy hands@on floats to optimised BLAS libraries (cache-blocked, multi-threaded on desktops), which is why@beats hand-written loops by orders of magnitude. GPUs do it even faster for large sizes. - ▸
Precision matters: models use
float32,float16orbfloat16. Normalise embeddings and compare floats with a tolerance. Do not use==. After normalising afloat32vector its length is only close to 1 (for example 0.9999999), so a cosine can come out as 1.0000001. Passing that tonp.arccosgivesnan, sonp.clip(cos, -1.0, 1.0)first. - ▸
Edge cases of cosine: a zero vector has length 0, so dividing by its norm gives
nan(with a warning). Guard against it or add a tiny epsilon to the norm. If your embedding model already returns unit vectors (many do, check its documentation), the plain dot product is the cosine and you can skip the normalising step. For unit vectors, squared Euclidean distance equals2 - 2 * cosine, so ranking by smallest distance and by largest cosine gives the same order. - ▸
@,np.dotand*are three different things.@(np.matmul) is matrix multiplication and, for arrays with more than 2 dimensions, treats the leading dimensions as a batch ((32, n, k) @ (k, m)gives(32, n, m)).np.dotagrees for 1-D and 2-D inputs but behaves differently for more dimensions, and accepts scalars.*is element-wise. Prefer@for readability. Integer arrays do not get the fast BLAS path that float arrays do, so@on integers is much slower than on floats. - ▸
np.linalg.norm(v)is the Euclidean (L2) length for a vector, and for a 2-D array the default is the Frobenius norm (the length of all the entries as one long vector), not a per-row length. For per-row lengths passaxis=1. Other norms exist:ord=1adds absolute values (the "taxi-cab" distance),ord=np.inftakes the largest absolute value.
Remember this
- 1
Recall from Topic 14.1: a vector is a 1-D array (one row of numbers) and a matrix is a 2-D array (rows and columns). You can also picture a vector as an arrow from the starting corner of a map to a point. The numbers say how far to go in each direction.
- 2
The dot product of two vectors multiplies matching positions and adds the results:
[3, 4] . [1, 2] = 3*1 + 4*2 = 11. The everyday version is a shopping bill. Put the prices in one vector and the quantities in another. Multiply each price by its quantity, add up the line totals, and you have the bill. In NumPy writea @ b(ornp.dot(a, b)). Noticea * bis something else: element-wise multiplication that gives another vector (the line totals). - 3
The norm (length) of a vector is
np.linalg.norm(v). For[3.0, 4.0]it is 5.0: walk 3 steps east and 4 steps north and the straight-line distance from the start is 5 (the longest side of a 3-4-5 right triangle). Dividing a vector by its norm gives a unit vector (length 1) that keeps the direction. Normalising embeddings to unit length makes comparisons simpler. - 4
Cosine similarity measures how closely two vectors point in the same direction, ignoring their length:
a @ b / (norm(a) * norm(b)). It is 1 for the same direction, 0 for unrelated (at right angles) and -1 for opposite. For unit vectors it is just the dot product. Search engines for text, images and chatbot memory use it to find the items whose embeddings are nearest to a question's embedding. - 5
A top-k search is then three lines: normalise the rows of the embedding matrix, compute
unit @ queryto get one score per item, and takenp.argsort(-scores)[:k]for the best k. This is what a vector database does, with clever indexes to avoid scoring every row. In Topic 16.8 you will use embeddings from a real model with exactly this code. - 6
Matrix multiplication
A @ Bcombines rows of A with columns of B using dot products. The shapes must fit:(n, k) @ (k, m)gives(n, m). The inner sizeskmust match, and they vanish. It is not element-wise, andA @ Bdiffers fromB @ A. The transposeA.Tswaps rows and columns, andnp.eye(n)is the identity matrix, which leaves a matrix unchanged under@. - 7
A neural-network layer is
Z = X @ W + b.Xhas shape(batch, inputs), one row per example.Whas shape(inputs, outputs), the learned weights.bhas shape(outputs,), the learned bias (a number added to each output), broadcast across the batch (Topic 14.3).Zhas shape(batch, outputs). An activation function such as ReLU (np.maximum(Z, 0), which turns every negative number into 0) is then applied element-wise. A deep network is many of these layers stacked. Training means adjustingWandbso the outputs get closer to the right answers. - 8
NumPy runs these on the CPU, in compiled code that uses optimised linear-algebra libraries. Frameworks such as PyTorch use the same ideas on GPUs (graphics chips that do huge amounts of arithmetic at once), with automatic gradients (the numbers that say which way to nudge each weight) for training. If you can read shapes, you can read their code.
Explain it without notes
What is an embedding and why is cosine similarity a useful way to compare two of them?
State the shape rule for A @ B and the shape of the result. How is it different from A * B?
Explain Z = X @ W + b with shapes for a layer that maps 128 inputs to 64 outputs on a batch of 32.
How do you find the top 3 most similar items to a query with NumPy?
When are cosine similarity, dot product and Euclidean distance equivalent for ranking, and when do they disagree?
What can go wrong when you normalise vectors, and how do you guard against it?
Practice
Write normalise(v) that returns v divided by its length. Test it on [3.0, 4.0].
Given A of shape (2, 3) and B of shape (3, 4), say what A @ B shape is and confirm it with np.ones.
Compute the cosine similarity between [1.0, 0.0] and [1.0, 1.0].
Given three embeddings as the rows of emb = np.array([[1.0, 0.0], [1.0, 1.0], [0.0, 1.0]]), compute the whole 3-by-3 table of cosine similarities between every pair with one matrix product, rounded to 3 places. Hint: unit @ unit.T.
Trade-offs
- ↔
Exact versus approximate search. Scoring every row is exact but slow for millions of items; indexes are fast but approximate.
- ↔
Cosine versus dot product versus distance. Cosine ignores length; the dot product rewards length; Euclidean distance suits some embeddings. Use what the model's authors recommend.
- ↔
Precision versus memory.
float32embeddings halve storage compared withfloat64, with negligible effect on ranking.
Done when you can
Done when you can compute dot products and norms and explain them.
Done when you can normalise vectors and compute cosine similarity by hand and with NumPy.
Done when you can write a top-k search with
@andargsort.Done when you can state the shape rule for
@and tell@from*.Done when you can describe
X @ W + band give the shape of every piece.