向量检索的相似度计算方式详解


一、为什么要算"相似度"?

向量检索的核心就是:把文本/图像等内容变成向量(embedding),然后用"向量之间的相似度"来判断两段内容有多相关。

用户提问 → 向量化 → 与向量库中所有 chunk 的向量算相似度 → 取 Top-K 最相似的。

所以相似度计算方式直接决定了"什么算相关、排序怎么排",是检索系统的核心算法。

相似度计算方式的本质

不同度量方法衡量的是向量之间不同的几何关系

度量 本质衡量 关注点
余弦相似度(Cosine) 向量夹角 方向是否一致(语义是否相关)
内积(Dot Product) 向量方向 + 长度 方向一致 + 匹配强度
欧氏距离(L2) 向量空间距离 绝对距离远近

二、常见相似度计算方式有哪些?

1. 余弦相似度(Cosine Similarity)

公式:

cosine(A, B) = (A · B) / (|A| × |B|)
  • 分子是内积,分母是两个向量模长的乘积
  • 结果范围:[-1, 1](对非负 embedding 通常为 [0, 1])。
  • 只关心方向(夹角),不看长度

几何意义:向量 A、B 指向的方向是否一致。夹角越小越相似;即使 A 是 B 的 10 倍长,只要方向一致,余弦相似度 = 1。

特点

  • 向量长度不敏感 → 天然不受文本长度影响(短句和长段只要语义相同,得分就高)。
  • 最直观、最常用,绝大多数 embedding 模型的默认相似度。

2. 内积(Dot Product / Dot)

公式:

dot(A, B) = Σ(aᵢ × bᵢ) = a₁b₁ + a₂b₂ + ... + aₙbₙ
  • 结果是标量,范围无上下限(可为正、负、任意大)。
  • 既看方向,又看长度:方向一致时值大;同时向量越长,值越大。

几何意义:A 在 B 方向上的投影长度 × B 的长度。等价于 |A| × |B| × cosθ

特点

  • 向量长度敏感 → 长向量(通常对应长文本或高频词)天然得分更高。
  • 计算比余弦快(少一步归一化/除法),常用于大规模索引加速。

3. 欧氏距离(Euclidean Distance / L2)

公式:

dist(A, B) = √(Σ(aᵢ − bᵢ)²)
  • 结果是距离,越小越相似(注意:是"距离"不是"相似度",用法相反)。
  • 范围 [0, +∞)。

特点

  • 衡量绝对空间距离,对向量长度高度敏感。
  • 在 embedding 检索中用得较少,但在某些聚类、NN 搜索场景使用。

4. 曼哈顿距离 / 其他

  • 曼哈顿距离(L1):坐标差的绝对值之和,对异常值更鲁棒。
  • 汉明距离:用于二进制向量(哈希向量),按位不同个数。
  • 杰卡德相似度:集合相似度,用于稀疏/布尔向量(如 BOW)。

工程上主流的向量检索(FAISS、Milvus、Qdrant、pgvector 等)最常配置的就是 内积余弦相似度 两种。下面重点讲这两个。


三、余弦相似度 vs 内积:详细对比

维度 余弦相似度(Cosine) 内积(Dot Product)
公式 `A·B / ( A
是否归一化 是(除模长)
取值范围 [-1, 1](非负 embedding 为 [0,1]) 无上限(可为负/任意大)
关心什么 只关心方向 既关心方向也关心长度
对向量长度敏感 不敏感 敏感
对文本长度影响 短句长段同语义 → 得分接近 长文本 → 得分天然偏高
计算开销 稍高(多一次除法/归一化) 低(直接点积)
典型用途 通用语义相似度 已归一化向量的相似度 / 大规模检索加速

关键区别的本质

余弦 = 归一化后的内积。

如果先把所有向量做 L2 归一化v = v / |v|,使每个向量模长=1),那么:

归一化后:dot(A', B') = A'·B' = cos(A, B)

也就是说:在向量都已归一化的前提下,内积 ≡ 余弦相似度,两者结果完全一致。

这正是两个概念最容易混淆的地方,也是工程上的核心结论:

  • 余弦相似度 = "先归一化,再内积"
  • 内积 = "不归一化,直接点积"

所以到底用哪个,取决于你的向量库里的向量是否被归一化


四、何时选择哪种?(决策指南)

4.1 核心决策规则

情况 建议
向量已做 L2 归一化(模长=1) 内积(Dot),等价于余弦且更快
向量未归一化,且希望不受文本长度影响 余弦相似度(Cosine)
需要体现"匹配强度/频次"(长文本更相关) 内积(不归一化时)
追求大规模检索速度 用内积(向量归一化后配合内积,兼得正确性与速度)

4.2 按实际场景细分

① 文本 Embedding(RAG 最常见场景)

  • 强烈建议:对 embedding 向量做 L2 归一化 + 使用内积(Dot)
  • 原因:
    • 归一化后消除了文本长度干扰,内积=余弦,语义相关性一致;
    • 同时享受内积的计算速度(向量检索库普遍对 dot 优化更好)。
  • 主流实践(OpenAI Embedding、Milvus、Qdrant、FAISS 官方教程)都推荐这种组合。

② 向量库默认配置的坑

  • Milvus、Qdrant、pgvector 等默认常用 L2/欧氏距离内积,且假设输入已归一化
  • 如果你直接塞未归一化的文本向量还用 dot,长度会影响结果 → 结果不准
  • 对策:要么喂之前先归一化,要么明确选 Cosine。

③ 什么时候真的该用"纯余弦"而非"归一化+内积"?

  • 当向量无法归一化或不想改动向量时(例如使用已有向量、跨系统迁移)。
  • 实现简单直观,便于调试(得分范围固定 [0,1],容易设阈值)。
  • 缺点:每次查询都要算模长(或在索引端归一化),略慢。

④ 什么时候该用"纯内积"(不归一化)?

  • 故意希望长度参与:如词频加权、匹配强度加权、推荐系统中希望"更热门的项"更相关。
  • 输入向量本身已归一化时(归一化内积=余弦,直接用 dot)。

⑤ 欧氏距离/L2 什么时候用?

  • 几何任务(聚类、最近邻几何分析)而非语义相似度。
  • 对"绝对位置"敏感的任务(如坐标、图像特征)。

4.3 一张决策流程图

embedding 向量是否已经 L2 归一化(模长=1)?
├─ 是 → 用内积 Dot(=余弦,更快)✅
└─ 否
     ├─ 希望检索结果不受文本长度影响 → 归一化后内积 或 直接用余弦 ✅
     ├─ 希望长文本/高频词天然更相关 → 直接用内积(不归一化)
     └─ 需要固定得分范围做阈值过滤 → 直接用余弦([0,1])

五、工程实践细节与常见坑

5.1 常用向量库的相似度配置

支持的度量 推荐配置(文本 RAG)
FAISS L2, InnerProduct(内积) IndexFlatIP + 预先归一化向量
Milvus IP(内积), COSINE, L2 IP + 归一化;或 COSINE
Qdrant Dot, Cosine, Euclid Dot(假设归一化)或 Cosine
pgvector inner_product, cosine, l2 cosine,或用 normalized dot
Chroma l2, ip, cosine cosine(默认即余弦)
Weaviate dot, cosine, l2 dot(已归一化)或 cosine

⚠️ 不同库对 dot/ip前提假设不同(有的默认向量已归一化,有的不检查),务必看文档确认,否则容易出现"配置了 IP 但结果像余弦又像内积"的迷惑行为。

5.2 归一化在哪里做?

  • 写入时归一化:入库前统一 v = v / |v|,索引里存的都是单位向量(推荐,检索时零开销)。
  • 查询时归一化:query 向量也做同样归一化,保证与库中向量可比。
  • 一致性要求入库和查询必须用同一套归一化规则,否则相似度计算错乱。

5.3 常见坑

  1. 库里同时有归一化和未归一化的向量 → 相似度计算结果完全失真。
  2. 换了 Embedding 模型没重新归一化 → 不同模型的向量尺度不同,混用必错。
  3. 阈值设错
    • 余弦阈值取 0.7~0.8 往往合理;
    • 内积阈值无固定范围,需按实际分布统计(如取 Top-K 分位数),不能用余弦的直觉设内积阈值
  4. 内积得分可能为负:不归一化 + 向量含负值时,dot 可能为负,别用负数直接当"不相似=0"处理,要看排序而非绝对分。
  5. 归一化损失信息:归一化丢掉长度信息。如果任务中文本长度本身是重要特征(如长文档重要性更高),归一化会损失这部分信号(对 RAG 语义检索通常无妨)。

5.4 计算量对比(实际影响)

  • 余弦:O(n) 除法 + 内积,每次查询需对 query 算模长(但 query 只有 1 个,可忽略),库端若未预归一化则每次比较都要除法。
  • 内积(归一化向量):O(n) 纯乘法累加,无除法 → 在 HNSW/量化索引里通常更快
  • 结论:归一化 + 内积在保证正确性(=余弦)的同时更快,是推荐组合。

六、与 RAG 其他环节的关系

6.1 相似度计算 vs 混合检索

  • 向量检索用相似度(余弦/内积)算语义相似度;
  • BM25 用 TF-IDF 算关键词匹配分;
  • 两者分数量纲不同(向量 0~1 vs BM25 无上限),融合时需要归一化(MinMax/Z-score)或用 RRF 排名融合,否则权重失衡。

6.2 相似度计算 vs Rerank

  • 向量相似度(余弦/内积)衡量的是"语义相近";
  • Rerank 模型衡量的是"能否回答这个问题";
  • 两者目标不同 → 先向量召回大池子,再 Rerank 精排,是标准做法。

6.3 归一化后的余弦阈值经验

  • 语义相关(强相关):余弦 > 0.8
  • 一般相关:0.6~0.8
  • 弱相关/不相关:< 0.6
  • (不同 Embedding 模型分布不同,需实测统计,以上仅为经验参考)

七、总结速查

结论 一句话
余弦 vs 内积的本质 余弦 =归一化后的内积;归一化时两者完全等价
RAG 文本检索推荐 L2 归一化向量 + 内积(Dot),正确且快
什么时候选纯余弦 向量无法归一化 / 想要固定 [0,1] 得分做阈值
什么时候选纯内积 想要长度/强度参与排序(非语义检索场景)
最大坑 库中向量混用归一化与未归一化,或混用不同模型的向量
评估方式 用 Recall@K / MRR 对比不同度量的检索效果

一句话总结:做 RAG 向量检索,默认组合是"embedding 归一化 + 内积";它既等价于余弦相似度的语义效果,又享受内积的计算速度。理解"归一化是连接两者的桥梁",就不会选错。