Cosine similarity calculator and vector search
Embeddings turn text, images and users into vectors, and “similar” becomes a question of angle or distance. Paste two vectors to get every common similarity measure, worked out, then run an approximate nearest-neighbour index to see how much accuracy it gives up for speed.
cos(A, B) = A·B / (|A| |B|) = 0.82 / (0.922 × 0.911) = 0.97626
| Dot product A·B | 0.82 |
| Length |A|, |B| | 0.922, 0.911 |
| Cosine similarity | 0.97626 |
| Cosine distance (1 − cosine) | 0.0237 |
| Angle between them | 12.51° |
| Euclidean distance | 0.2 |
| Euclidean distance, both normalised | 0.2179 |
| Manhattan distance | 0.4 |
Drawn in the plane of A and B, both at the same length: cosine similarity only sees this angle.
| Lists scanned (nprobe) | Recall@10 | Vectors scanned |
|---|---|---|
| 1 | 59.8% | 2.3% |
| 2 | 86.0% | 3.9% |
| 4 | 99.0% | 6.6% |
| 8 | 100.0% | 13.1% |
| 16 | 100.0% | 25.7% |
| 64 | 100.0% | 100.0% |
How to use the calculator
Type or paste two vectors as lists of numbers, separated by commas or spaces; brackets are ignored, so a vector copied from Python or JSON works as it is. The table shows every common measure with the cosine similarity worked out step by step. Below it, the nearest-neighbour experiment builds an IVF index over random clustered vectors and measures how many of the true ten nearest neighbours each setting finds.
What is a vector embedding?
An embedding represents an item, such as a word, a sentence, an image or a user, as a vector of numbers produced by a trained model, arranged so that items with similar meaning get vectors that point in similar directions. Mikolov and colleagues’ word2vec (2013) learned such vectors for words from large amounts of text; today sentence and document embeddings drive semantic search, recommendations and the retrieval step of retrieval-augmented generation.
Using embeddings comes down to two operations: measuring how similar two vectors are, and finding the most similar vectors to a query among millions.
Cosine, dot product and distance
The dot product A·B multiplies matching entries and adds them up. It is large when the vectors point the same way and are long. Cosine similarity divides out the lengths, cos(A, B) = A·B / (|A| |B|), and so depends only on the angle: 1 for the same direction, 0 for perpendicular, −1 for opposite. Euclidean distance measures the straight-line gap between the points.
For vectors scaled to length 1 the three agree: the dot product equals the cosine, and the squared Euclidean distance is 2 − 2·cos, so all three rank neighbours identically. That is why embedding pipelines usually normalise vectors once and then use the cheapest measure. Without normalising they can disagree sharply: (1, 2, 3) and (10, 20, 30.5) have a cosine similarity of 0.99997 yet are 34.08 apart, while (1, 2, 3) and (2, 4, 6) have a cosine of exactly 1 and a distance of 3.74.
Distances in many dimensions
Embeddings have hundreds or thousands of dimensions, and high-dimensional space behaves strangely: the distances from a point to random others bunch together. For 1,000 random points in a unit cube, the relative gap between the farthest and nearest point from a random query, (farthest − nearest) / nearest, averaged over 20 queries:
| Dimensions | (farthest − nearest) / nearest |
|---|---|
| 2 | 106.64 |
| 10 | 3.11 |
| 100 | 0.44 |
| 1,000 | 0.12 |
In 1,000 dimensions the nearest random point is barely closer than the farthest. Embeddings escape this because they are not random: related items cluster, and the clusters sit far apart, so a query’s neighbours are genuinely closer than everything else. That structure is also what approximate indexes exploit.
Approximate nearest-neighbour search
Finding the exact nearest neighbours means comparing the query with every vector, which is too slow for millions of them. Approximate methods look at a small part of the collection and accept missing a few true neighbours. An inverted file (IVF) index, one of the structures in the Faiss library, runs k-means to split the vectors into nlist clusters; a query is compared with the cluster centres and then only with the vectors in the nprobe closest clusters. On 5,000 vectors in 32 dimensions with 64 lists:
| nprobe | Recall@10 | Vectors scanned |
|---|---|---|
| 1 | 59.8% | 2.3% |
| 2 | 86% | 3.9% |
| 4 | 99% | 6.6% |
| 8 | 100% | 13.1% |
| 16 | 100% | 25.7% |
| 64 | 100% | 100% |
Recall climbs quickly while only a small share of the vectors is scanned, then the last few percent cost the most. HNSW, the graph-based index of Malkov and Yashunin, is the other common choice: it links each vector to near neighbours in a layered graph and walks greedily toward the query. It stores a list of links for every vector, so it needs more memory than an inverted file over the same data.
Vector similarity questions and answers
How do you calculate cosine similarity?
Divide the dot product of the two vectors by the product of their lengths: cos(A, B) = A·B / (|A| |B|). For A = (1, 2, 3) and B = (4, 5, 6), A·B = 32, |A| = √14 and |B| = √77, so the cosine similarity is 32 / √1078 ≈ 0.9746. It ranges from −1 (opposite directions) through 0 (perpendicular) to 1 (same direction).
What is the difference between cosine similarity and dot product?
The dot product grows with the vectors’ lengths as well as with the angle between them; cosine similarity divides the lengths out and keeps only the angle. For vectors normalised to length 1 the two are equal, which is why many embedding systems normalise once and then use the faster dot product.
Cosine similarity or Euclidean distance?
For unit-length vectors they rank neighbours the same way, because the squared Euclidean distance is 2 − 2·cos. Without normalising they differ: (1, 2, 3) and (10, 20, 30.5) point almost the same way (cosine 0.99997) but are 34.08 apart.
What is approximate nearest neighbour search?
Searching an index that finds most of the true nearest neighbours while looking at a small fraction of the vectors. In this page’s test of an IVF index on 5,000 vectors, scanning the 4 closest of 64 clusters looked at 6.6% of the vectors and found 99% of the true 10 nearest neighbours.
What is the curse of dimensionality?
In many dimensions, distances between random points become nearly equal, so “nearest” means less. For 1,000 random points in a unit cube, the relative gap between the farthest and the nearest point from a query, (farthest − nearest) / nearest, averaged 106.64 in 2 dimensions and only 0.12 in 1,000. Real embeddings are not random, which is why nearest-neighbour search still works on them.
Further reading
- Mikolov et al., 2013Efficient estimation of word representations in vector spaceThe word2vec paper.
- Johnson, Douze and JégouBillion-scale similarity search with GPUsThe Faiss library and its inverted-file indexes.
- Malkov and YashuninEfficient and robust approximate nearest neighbor search using HNSW graphsThe hierarchical navigable small world index.