Définition
Similarité cosinus : mesurer la proximité de deux embeddings
Similarité cosinus, produit scalaire ou distance euclidienne : ce que mesure chacun, quand ils sont équivalents, et l'opérateur à choisir dans pgvector.
Mis à jour le
La similarité cosinus mesure l'angle entre deux vecteurs : 1 quand ils pointent exactement dans la même direction, 0 quand ils sont sans rapport (perpendiculaires), -1 quand ils sont opposés. Appliquée à deux embeddings, elle dit si deux textes parlent de la même chose, indépendamment de la « longueur » des vecteurs. C'est la mesure la plus utilisée en recherche par le sens.
La formule, en clair
cos(A, B) = (A · B) / (‖A‖ × ‖B‖)
- A · B est le produit scalaire : on multiplie les valeurs deux à deux et on additionne.
- ‖A‖ est la longueur (la norme) du vecteur A.
Prenons deux vecteurs illustratifs à deux dimensions, A = (1, 2) et B = (2, 4) : B est deux fois plus long que A, mais dans la même direction. Leur similarité cosinus vaut 1. Leur distance euclidienne, elle, n'est pas nulle. C'est tout l'intérêt du cosinus : il ignore la longueur et ne regarde que la direction.
Trois mesures, souvent équivalentes
| Mesure | Ce qu'elle compare | Plus c'est… |
|---|---|---|
| Similarité cosinus | l'angle | grand, plus c'est proche |
| Produit scalaire | l'angle et la longueur | grand, plus c'est proche |
| Distance euclidienne | l'écart en ligne droite | petit, plus c'est proche |
Quand les vecteurs sont normalisés, c'est-à-dire ramenés à une longueur de 1, les trois donnent le même classement. Les éditeurs le disent :
- OpenAI recommande la similarité cosinus, note que le choix « n'a généralement pas beaucoup d'importance », et précise que ses vecteurs étant de longueur 1, le cosinus se calcule par un simple produit scalaire et donne le même classement que la distance euclidienne ;
- Mistral AI écrit que, ses plongements étant de norme 1, similarité cosinus, produit scalaire et distance euclidienne sont équivalents ;
- Ollama renvoie des vecteurs normalisés et recommande le cosinus pour la plupart des recherches par le sens.
En pratique : quel opérateur
En Python, avec Sentence Transformers. La documentation indique que la similarité par défaut est le cosinus, et que pour un modèle qui normalise ses sorties, le produit scalaire ("dot") est équivalent et plus rapide, puisque le cosinus refait la normalisation.
Dans PostgreSQL, avec pgvector. Les opérateurs renvoient des distances (plus petit = plus proche), pas des similarités (documentation) :
| Opérateur | Mesure | Classe d'index à créer |
|---|---|---|
<=> |
distance cosinus | vector_cosine_ops |
<#> |
produit scalaire négatif | vector_ip_ops |
<-> |
distance euclidienne (L2) | vector_l2_ops |
Pour afficher une similarité cosinus, la documentation donne :
SELECT 1 - (embedding <=> '[3,1,2]') AS cosine_similarity FROM items;
Elle ajoute que pour des vecteurs normalisés, le produit scalaire offre les meilleures performances.
Les pièges
- L'index doit correspondre à l'opérateur. La documentation de pgvector demande d'ajouter un index pour chaque fonction de distance utilisée : un index créé avec
vector_l2_opsest prévu pour<->, pas pour une requête triée par<=>. - Les scores ne sont pas des pourcentages. Chaque modèle a sa propre échelle ; un seuil fixé pour un modèle ne vaut pas pour un autre.
- Les vecteurs raccourcis ne sont plus normalisés. Après une réduction de dimension, renormalisez avant d'utiliser le produit scalaire (voir Dimensions et Matryoshka).
Pour aller plus loin : la proximité calculée ici est celle qu'accélèrent les index HNSW.
Questions fréquentes
Une similarité cosinus de 0,8 veut-elle dire que deux textes sont très proches ?
Cela dépend du modèle : chaque modèle a sa propre échelle de scores. Comparez les scores entre eux pour un même modèle, et fixez un éventuel seuil après essais sur vos données.
Cosinus ou produit scalaire, lequel choisir ?
Si les vecteurs sont normalisés (longueur 1), les deux donnent le même classement et le produit scalaire est plus rapide. Sinon, utilisez le cosinus.
Sources
Pages consultées pour écrire cet article :