Back to all notes

Note 13 Sept 2026 9 min read

How Does the Dot Product Measure Similarity?

A step-by-step journey from vectors and the law of cosines to why the dot product of normalised vectors measures directional similarity.


I was studying Build a Large Language Model (From Scratch) the other day when I came across the idea of using dot products to calculate similarity between two normalised vectors.

I found that intriguing.

The dot product is simply the sum of the pairwise products of two vectors’ components. How would that indicate similarity?

This article is my research written up. To be honest, proving why this works isn’t necessary to use it. If you’re like me, however, you value understanding why things are the way they are. Knowledge for knowledge’s sake ;)

Before we go on this adventure, let’s start with some basics.

What do we mean by similarity?

A vector can be represented as a collection of numbers. Geometrically, we can think of it as an arrow with a magnitude (length) and a direction.

Take a vector called AA, defined as (4,5)(4, 5). This vector has two dimensions, although vectors can have many more. On a graph, vector AA looks like this:

Vector A from the origin to (4, 5).

Starting at the origin, it extends 4 steps along the x-axis and 5 steps along the y-axis.

Now imagine another vector, BB, defined as (2,1)(2, 1).

Vectors A = (4, 5) and B = (2, 1), with the angle between them.

If I wanted to calculate how similar AA is to BB, a good first question would be: similar based on what metric?

I could, for instance, measure the distance between their endpoints. A smaller distance would indicate greater similarity. Notice what’s happening here, though: the lengths of the vectors matter, as well as their directions. If AA were shorter, that distance would change.

If I were interested only in direction, I could measure the angle θ\theta (theta) between the vectors. That’s the approach we’ll use here.

On our two-dimensional graph, we could measure the angle with a protractor:

  • At 00^\circ, the vectors point in the same direction.
  • At 9090^\circ, they’re orthogonal (perpendicular).
  • At 180180^\circ, they point in opposite directions.

Cosine turns these angles into a similarity score:

cos(0)=1cos(90)=0cos(180)=1\begin{aligned} \cos(0^\circ) &= 1 \\ \cos(90^\circ) &= 0 \\ \cos(180^\circ) &= -1 \end{aligned}

Plotting vectors and measuring angles isn’t a practical approach for computers, especially when vectors have hundreds of dimensions. We need a way to compute this score directly from their components.

Thankfully, maths can help us here.

giggles in trigonometry

Start with the law of cosines

There’s a mathematical rule that lets us calculate the cosine of an angle in a triangle, provided we know the lengths of all three sides. It’s called the law of cosines.

c2=a2+b22abcos(θ)2abcos(θ)=a2+b2c2cos(θ)=a2+b2c22abθ=arccos(a2+b2c22ab)\begin{aligned} c^2 &= a^2 + b^2 - 2ab\cos(\theta) \\ 2ab\cos(\theta) &= a^2 + b^2 - c^2 \\ \cos(\theta) &= \frac{a^2 + b^2 - c^2}{2ab} \\ \theta &= \arccos\left(\frac{a^2 + b^2 - c^2}{2ab}\right) \end{aligned}

Here, aa, bb, and cc are the side lengths. The angle θ\theta lies between the sides of lengths aa and bb, opposite the side of length cc.

The law of cosines generalises Pythagoras’ theorem:

c2=a2+b2c^2 = a^2 + b^2

Pythagoras’ theorem applies to right-angled triangles. When θ=90\theta = 90^\circ, the cosine term is zero, leaving us with the equation above.

How does this relate to our vectors AA and BB? That’s what we’re about to find out.

Find the lengths of the vectors

We know the components of AA and BB, but we haven’t calculated their lengths yet.

For AA, the horizontal component is 4 and the vertical component is 5. Its length is the hypotenuse of the right triangle below.

The right triangle formed by the horizontal and vertical components of vector A.

Pythagoras’ theorem gives us a way to calculate that length:

z2=x2+y2z=x2+y2\begin{aligned} z^2 &= x^2 + y^2 \\ z &= \sqrt{x^2 + y^2} \end{aligned}

Plugging in the components of AA:

z2=42+52z=16+25=416.403\begin{aligned} z^2 &= 4^2 + 5^2 \\ z &= \sqrt{16 + 25} \\ &= \sqrt{41} \\ &\approx 6.403 \end{aligned}

We write the length of AA as A|A|, so:

A=416.403|A| = \sqrt{41} \approx 6.403

More generally, we can write:

A2=Ax2+Ay2|A|^2 = A_x^2 + A_y^2

Here, AxA_x and AyA_y are the x and y components of AA. Keep this relationship in mind; we’ll use it again shortly.

The same calculation for B=(2,1)B = (2, 1) gives B=52.236|B| = \sqrt{5} \approx 2.236.

Find the third side

Okay, now that we have A|A| and B|B|, how do we calculate the distance between their endpoints? Remember, we need all three side lengths to use the law of cosines.

It turns out there’s a neat way to do this. Subtract BB from AA to get a new vector, C=ABC = A - B:

AB=(4,5)(2,1)=(42,51)=(2,4)A - B = (4, 5) - (2, 1) = (4 - 2, 5 - 1) = (2, 4)

This vector connects the endpoint of BB to the endpoint of AA. That makes sense: to get from BB to AA, move 2 steps along the x-axis and 4 steps along the y-axis.

We can now use Pythagoras’ theorem to calculate its length, C=AB|C| = |A - B|.

Vector C = A − B = (2, 4), connecting the endpoint of B to the endpoint of A.

Let’s write the calculation in terms of the components, using A=(Ax,Ay)A = (A_x, A_y) and B=(Bx,By)B = (B_x, B_y):

AB2=(AxBx)2+(AyBy)2=(AxBx)(AxBx)+(AyBy)(AyBy)=Ax22AxBx+Bx2+Ay22AyBy+By2=(Ax2+Ay2)+(Bx2+By2)2(AxBx+AyBy)=A2+B22(AxBx+AyBy)\begin{aligned} |A - B|^2 &= (A_x - B_x)^2 + (A_y - B_y)^2 \\ &= (A_x - B_x)(A_x - B_x) \\ &\quad + (A_y - B_y)(A_y - B_y) \\ &= A_x^2 - 2A_xB_x + B_x^2 \\ &\quad + A_y^2 - 2A_yB_y + B_y^2 \\ &= (A_x^2 + A_y^2) + (B_x^2 + B_y^2) \\ &\quad - 2(A_xB_x + A_yB_y) \\ &= |A|^2 + |B|^2 - 2(A_xB_x + A_yB_y) \end{aligned}

A brief clarification on the last step: remember the relationship I asked you to keep in mind?

A2=Ax2+Ay2|A|^2 = A_x^2 + A_y^2

That’s how we replace the sums of squared components with A2|A|^2 and B2|B|^2.

Now we need to connect this result to the angle between the vectors.

Connect the two formulas

Remember the law of cosines:

c2=a2+b22abcos(θ)c^2 = a^2 + b^2 - 2ab\cos(\theta)

For our triangle, the side lengths are A|A|, B|B|, and C|C|, so:

C2=A2+B22ABcos(θ)|C|^2 = |A|^2 + |B|^2 - 2|A||B|\cos(\theta)

Since C=ABC = A - B, we can rewrite this as:

AB2=A2+B22ABcos(θ)|A - B|^2 = |A|^2 + |B|^2 - 2|A||B|\cos(\theta)

We now have two expressions for AB2|A - B|^2. One uses the components of the vectors; the other uses their lengths and the angle between them. Because they describe the same quantity, we can set them equal:

A2+B22ABcos(θ)=A2+B22(AxBx+AyBy)\begin{aligned} &|A|^2 + |B|^2 - 2|A||B|\cos(\theta) \\ &\qquad = |A|^2 + |B|^2 - 2(A_xB_x + A_yB_y) \end{aligned}

Subtract A2+B2|A|^2 + |B|^2 from both sides, then divide by 2-2:

ABcos(θ)=AxBx+AyByAxBx+AyBy=ABcos(θ)\begin{aligned} |A||B|\cos(\theta) &= A_xB_x + A_yB_y \\ A_xB_x + A_yB_y &= |A||B|\cos(\theta) \end{aligned}

Look at the left-hand side of the last equation. That’s exactly the dot product!

For A=(Ax,Ay)A = (A_x, A_y) and B=(Bx,By)B = (B_x, B_y), the dot product is AB=AxBx+AyByA \cdot B = A_xB_x + A_yB_y. Therefore:

AB=ABcos(θ)A \cdot B = |A||B|\cos(\theta)

The dot product equals the length of AA multiplied by the length of BB, multiplied by the cosine of the angle between them.

Check it with our example

Let’s test the formula using our original vectors:

A=(4,5),B=(2,1)AB=4×2+5×1=13AB=415=205cos(θ)=132050.908θ24.8\begin{aligned} A &= (4, 5), \quad B = (2, 1) \\ A \cdot B &= 4 \times 2 + 5 \times 1 = 13 \\ |A||B| &= \sqrt{41}\sqrt{5} = \sqrt{205} \\ \cos(\theta) &= \frac{13}{\sqrt{205}} \approx 0.908 \\ \theta &\approx 24.8^\circ \end{aligned}

Now let’s check this with the law of cosines, keeping the squared lengths exact to avoid rounding too early:

AB2=22+42=20cos(θ)=41+5202415=132050.908θ24.8\begin{aligned} |A - B|^2 &= 2^2 + 4^2 = 20 \\ \cos(\theta) &= \frac{41 + 5 - 20}{2\sqrt{41}\sqrt{5}} \\ &= \frac{13}{\sqrt{205}} \approx 0.908 \\ \theta &\approx 24.8^\circ \end{aligned}

We get the same answer.

Why normalisation makes the difference

If we’re dealing with normalised vectors—that is, vectors with a length of 1—the formula becomes:

AB=ABcos(θ)=1×1×cos(θ)=cos(θ)\begin{aligned} A \cdot B &= |A||B|\cos(\theta) \\ &= 1 \times 1 \times \cos(\theta) \\ &= \cos(\theta) \end{aligned}

This is really beautiful, actually.

The dot product of two normalised vectors equals their cosine similarity. Without normalisation, the lengths of the vectors also affect the dot product.

We don’t need to calculate the angle first, or find the vector connecting the endpoints of AA and BB.

Let’s normalise our original vectors. To normalise a non-zero vector, divide each component by the vector’s length:

Anorm=(4,5)41(0.625,0.781)Bnorm=(2,1)5(0.894,0.447)\begin{aligned} A_{\mathrm{norm}} &= \frac{(4, 5)}{\sqrt{41}} \approx (0.625, 0.781) \\ B_{\mathrm{norm}} &= \frac{(2, 1)}{\sqrt{5}} \approx (0.894, 0.447) \end{aligned}

Their dot product gives us:

cos(θ)=AnormBnorm=4×2+5×1415=132050.908θ24.8\begin{aligned} \cos(\theta) &= A_{\mathrm{norm}} \cdot B_{\mathrm{norm}} \\ &= \frac{4 \times 2 + 5 \times 1}{\sqrt{41}\sqrt{5}} \\ &= \frac{13}{\sqrt{205}} \approx 0.908 \\ \theta &\approx 24.8^\circ \end{aligned}

The same angle again! We’ve kept the exact values in the calculation; using the rounded components would give a slightly different approximation.

That, my friends, is the beauty of mathematics.

Let me stop now because my head hurts, lol!

Do you have any thoughts, corrections or questions? I'd love to hear from you.

Reply by email samuelagbede@outlook.com