跳到主要内容

相似度与距离度量

问题

向量检索中有哪些常用的相似度计算方法?它们各自适用什么场景?

答案

一、三种主要度量方式

度量公式值域含义
余弦相似度cos(θ)=ABAB\cos(\theta) = \frac{A \cdot B}{\|A\| \|B\|}[-1, 1]方向相似性
欧氏距离d=(aibi)2d = \sqrt{\sum(a_i - b_i)^2}[0, ∞)空间距离
点积AB=aibiA \cdot B = \sum a_i \cdot b_i(-∞, +∞)方向 + 幅度

二、余弦相似度

最常用的 Embedding 相似度度量,只关注向量方向,不关注大小:

import numpy as np

def cosine_similarity(a: np.ndarray, b: np.ndarray) -> float:
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

# 示例:语义相似的句子余弦相似度高
v1 = embed("如何退款") # [0.12, 0.85, ...]
v2 = embed("退货退款流程") # [0.11, 0.83, ...]
v3 = embed("Python 教程") # [0.72, 0.05, ...]

cosine_similarity(v1, v2) # ≈ 0.92(语义相近)
cosine_similarity(v1, v3) # ≈ 0.15(语义不相关)
为什么余弦相似度最常用?

大多数 Embedding 模型在训练时已对输出向量做了归一化(L2 norm = 1),此时余弦相似度等价于点积,计算更高效。

三、欧氏距离

衡量两个向量在空间中的绝对距离

d(A,B)=i=1n(aibi)2d(A, B) = \sqrt{\sum_{i=1}^{n}(a_i - b_i)^2}
  • 距离越小 → 越相似
  • 对向量的幅度敏感:即使方向一致,长度不同也会导致距离大
  • 适合向量已归一化的场景(归一化后等价于余弦距离)

四、点积(Inner Product / Dot Product)

AB=i=1naibi=ABcos(θ)A \cdot B = \sum_{i=1}^{n} a_i \cdot b_i = \|A\| \|B\| \cos(\theta)
  • 同时考虑方向幅度
  • 向量归一化后,点积 = 余弦相似度
  • MaxSim(ColBERT 等 late-interaction 模型)使用点积

五、三者关系

当向量已归一化(A=B=1\|A\| = \|B\| = 1)时:

cosine(A,B)=AB=1d(A,B)22\text{cosine}(A, B) = A \cdot B = 1 - \frac{d(A, B)^2}{2}
面试重点

大多数 Embedding 模型输出已归一化,三种度量在排序结果上完全等价。面试中说清楚"归一化后等价"即可。

六、选择建议

场景推荐度量理由
语义检索(默认)余弦相似度不受向量长度干扰
归一化向量点积计算最快(无需除法)
推荐系统点积向量幅度可表示热度/权重
图像特征匹配欧氏距离空间距离有物理意义

常见面试问题

Q1: 余弦相似度和点积有什么区别?什么时候等价?

答案

  • 余弦相似度只衡量方向,点积同时衡量方向和幅度
  • 当向量 L2 归一化后,二者完全等价
  • 大多数 Embedding 模型默认输出归一化向量,所以实践中常用点积(更快)

Q2: 为什么向量数据库默认使用余弦相似度?

答案

  • 语义检索关注的是语义方向,而非向量绝对大小
  • 余弦相似度天然忽略幅度,更符合语义匹配直觉
  • 即使模型输出未归一化,余弦相似度也能正确工作

Q3: 向量检索中如何提高计算效率?

答案

  • 归一化后用点积替代余弦相似度(省去归一化计算)
  • 降维:PCA 或 Matryoshka Embedding 减少维度
  • 量化:将 float32 量化为 int8(参考 Embedding 优化
  • 近似搜索:HNSW、IVF 等索引算法(参考 向量数据库

相关链接