相似度度量怎么选

余弦、内积、欧氏三种度量的公式、直觉与适用边界;为什么归一化后内积等于余弦,以及建索引/查询度量必须一致的坑。

余弦相似度(Cosine Similarity)

衡量两个向量方向的一致程度,与长度无关。范围 [-1, 1],越大越相似(1 完全相同方向,0 正交不相关,-1 反向)。

cos(A,B) = (A·B) / (||A|| · ||B||)
θ 夹角 A B origin
图 1:余弦只看夹角 θ,不看向量长度。θ 越小越相似。

语义检索里最常用,因为"意思相近"更关心方向而非模长。例:长文档和短文档意思一样,余弦能对齐,纯内积会被长度带偏。

内积(Dot Product)与余弦的关系

A·B = ||A|| · ||B|| · cos(A,B)

内积 = 余弦 × 两个向量的模长。所以当 A、B 都做了 L2 归一化(模长=1)时,内积就完全等于余弦相似度:

若 ||A||=||B||=1,则 A·B = cos(A,B)

这就是为什么很多向量库默认要求你归一化:归一化后用内积检索,结果和余弦一致,但内积计算更快(少了两次开方/除法),且底层可以用内积专用的硬件加速。

欧氏距离(L2 / Euclidean)

||A-B|| = sqrt( Σ (A_i - B_i)² )

衡量向量在几何空间中的"直线距离",同时受方向和长度影响。范围 [0, +∞),越小越相似。适合对"绝对量"敏感的场景(如坐标、特征幅度有意义的任务)。在纯语义文本检索里用得比余弦少,因为它会被向量长度干扰。

怎么选度量(决策表)

你的数据推荐度量原因
语义文本(BGE/BERT 等)余弦 / 归一化内积只关心语义方向
已归一化、追求速度内积(IP)等价余弦,计算更快
图像/特征,幅度有意义L2 欧氏方向与长度都重要
需要"不相关=0、反向=-1"语义余弦有明确符号语义
坑:同一个向量库里,建索引时用的度量和查询时用的度量必须一致。用内积建的 HNSW,查询却按余弦距离排序,结果会错。

为什么通常先归一化

最佳实践:文本检索 → 模型输出后 L2 归一化 → 用内积(IP)建索引与查询。一行代码的事,但能避免一大类"相似度不对"的 bug。