Skip to content
AI Engineering
Embeddings & Retrieval

Measuring similarity: cosine, dot product, distance

Search ranks vectors by a score. The three common scores are cosine similarity, dot product and Euclidean distance.

Chapter 8: Embeddings & RetrievalLesson 3 of 13Level: CoreAbout 12 min

Dot product and cosine similarity

ab

a · b = 3.86  |  cosine = 0.64

Partly aligned. Lengths: a = 3, b = 2.

Words on this page (5)
vector
: An ordered list of numbers. Embeddings and model activations are vectors.
cosine similarity
: A score from -1 to 1 for how much two vectors point the same way, ignoring their length.
dot product
: Multiply matching entries of two vectors and add them up. Large when they point the same way.
embedding
: A list of numbers that represents the meaning of a piece of text or an image, so similar things sit close together.
recommender
: A system that suggests items such as videos or products to each user.

The scores

multiplies matching entries and adds them. It grows with both direction match and length. divides out the lengths, so only direction counts, from -1 to 1. Euclidean distance is the straight-line distance between the two points: the square root of the sum of squared differences. Smaller means closer.

d(a,b)=∑i(ai−bi)2d(a,b) = \sqrt{\sum_i (a_i - b_i)^2}

Example

a = [3, 4], b = [6, 8], c = [4, -3]. Dot a·b = 18 + 32 = 50. Cosine a,b = 50 / (5 × 10) = 1: same direction. Euclidean a,b = √(9 + 16) = 5: they differ in length. Dot a·c = 12 - 12 = 0, cosine 0: unrelated.

Which to use

Most text models are trained for cosine similarity or produce vectors of length 1, in which case dot product and cosine give the same ranking. Use the metric the model's documentation recommends. If you normalize vectors to length 1, all three metrics give the same ordering.

A worked example: why cosine ignores length

a = [1, 2] and b = [10, 20]. They point the same way, b is just ten times longer. Dot product: 1×10 + 2×20 = 50, large. Cosine: 50 / (√5 × √500) = 50 / 50 = 1, a perfect match. Euclidean distance: √(81 + 324) = 20.1, far apart. For comparing meaning you usually want cosine, so a long document is not penalized or favored for its length.

A third example: when length is a feature

Some systems learn vectors where a longer vector means a more popular item. Take a user u = [1, 1] and two items p = [2, 2] and q = [1, 1]. Dot product: u·p = 2 + 2 = 4 and u·q = 1 + 1 = 2, so p ranks first. Cosine is 1 for both, a tie. Here the dot product is what you want, because the model deliberately stored popularity in the length. The metric must match how the vectors were trained.

What goes wrong

Suppose your vectors are not normalized and you rank with the dot product. Use query [1, 1], item x = [10, 0] and item y = [1, 1.2]. Dot product: x scores 10 and y scores 2.2, so x wins. Cosine: x is 10 / (10 × 1.414) = 0.71 and y is 2.2 / (1.414 × 1.562) = 0.996. Item y points almost exactly where the query points, yet x wins on length alone.

The symptom is results that feel off-topic but oddly confident, often the same items with the longest vectors showing up for many queries. Most text-embedding models return unit-length vectors, so this applies when yours do not. To confirm, compute the length of 100 stored vectors. If the lengths vary a lot and you use the dot product, length is steering the ranking.

Reading the scores

A cosine score has no universal meaning. 0.8 can be a strong match with one model and a weak one with another. Do not copy a cutoff such as "keep results above 0.75" from a blog post. Look at the scores for 20 of your own queries, mark which results were right, and pick a cutoff from that.

Try it yourself

In a spreadsheet, enter the vectors a = [1, 2], b = [10, 20] and c = [2, 1]. Compute dot product, cosine and Euclidean distance for a against b and a against c. You should find that cosine says b is a perfect match for a (1.0) and c is 0.8, while Euclidean distance says c is closer. Check: a·c = 2 + 2 = 4, and 4 / (√5 × √5) = 0.8. Seeing the two metrics disagree on the same data explains why the choice matters.

Common mistake

Mixing metrics between indexing and querying.

Check yourself

a = [3, 4] and b = [6, 8]. What is their cosine similarity?

After normalizing all vectors to length 1, how do cosine and dot product rank results?

You index with cosine but query with Euclidean distance. What is the problem?

Go deeper

Spotted a mistake or something unclear? Report it on GitHub.

On this page