向量检索分数怎么看?用三组向量分清余弦距离与内积

通过三组人工向量复核余弦相似度、距离、内积和负内积,解释 pgvector 分数及排序方向,再用真实问题集标定阈值。

向量检索返回的 score 或 distance,不一定都是“越大越相关”。余弦相似度越大表示方向越接近;余弦距离越小表示方向越接近;内积还受向量长度影响。有些数据库为了按升序利用索引,返回负内积。先确认公式和排序方向,再设置阈值。

下面用三组人工二维向量解释差别,数值是按公式计算的数学示例,不是任何模型的语义表现或数据库性能测试。

向量检索分数怎么看?用三组向量分清余弦距离与内积

三组向量,为什么会出现不同排名

固定查询 q = [1, 0],候选 A = [1, 0]、B = [2, 0]、C = [0, 1]。A 和 B 指向同一方向,B 只是长度更大;C 与查询垂直。

候选 内积 q·x 余弦相似度 余弦距离 负内积 L2 距离
A 1 1 0 -1 0
B 2 1 0 -2 1
C 0 0 1 0 约 1.414214

按内积降序,B 排在 A 前;按余弦相似度降序,A 和 B 并列;按 L2 距离升序,A 更近。差异来自度量定义,并不意味着系统自相矛盾。即使向量来自同一个模型,不同度量也要按该模型的建议和数据分布验收。

用 Python 复核这些数值

这段代码只使用 Python 标准库,可保存为 scores.py 后运行 python scores.py。零向量会明确报错,因为它没有可定义的余弦方向。

from math import sqrt

def dot(a, b):
    if len(a) != len(b):
        raise ValueError("两个向量的维度必须一致")
    return sum(x * y for x, y in zip(a, b))

def cosine(a, b):
    denominator = sqrt(dot(a, a)) * sqrt(dot(b, b))
    if denominator == 0:
        raise ValueError("零向量不能计算余弦相似度")
    return dot(a, b) / denominator

q = [1, 0]
for name, x in [("A", [1, 0]), ("B", [2, 0]), ("C", [0, 1])]:
    inner = dot(q, x)
    similarity = cosine(q, x)
    l2 = sqrt(sum((a - b) ** 2 for a, b in zip(q, x)))
    print(name, "inner=", inner, "cosine=", round(similarity, 6),
          "cosine_distance=", round(1 - similarity, 6),
          "negative_inner=", -inner, "l2=", round(l2, 6))

核对输出与表格逐项一致,尤其是 B 的内积为 2、余弦相似度仍为 1。只有先完成这个小例子,才能看懂线上分数到底有没有被转换、归一化或反向排序。

以 pgvector 为例,核对真实操作符

pgvector 官方项目说明列出的操作符中,<-> 是 L2 距离,<=> 是余弦距离,<#> 是负内积。最后一个返回负值,是因为 PostgreSQL 对相关操作符索引扫描支持升序;实际内积要乘 -1。

SELECT
    embedding <=> '[1,0]'::vector AS cosine_distance,
    1 - (embedding <=> '[1,0]'::vector) AS cosine_similarity,
    (embedding <#> '[1,0]'::vector) * -1 AS inner_product
FROM your_two_dimensional_demo_table;

-- 相似度展示可转换,检索排序仍按距离升序写:
SELECT id, 1 - (embedding <=> '[1,0]'::vector) AS similarity
FROM your_two_dimensional_demo_table
ORDER BY embedding <=> '[1,0]'::vector
LIMIT 5;

这里的表名是需要替换的演示名称,假定 vector 扩展已启用,embedding 是二维向量列。真实库若为 768 维,就必须提供 768 维查询,不能复制二维数据直接搜索。官方说明也要求 ORDER BY 使用距离操作符升序并配 LIMIT,才具备利用对应索引的条件;在 ORDER BY 中直接写 1 – distance 再降序,可能无法按预期用索引,应检查 EXPLAIN。

归一化以后,哪些关系成立

把非零向量各自除以它的长度,得到单位向量。此时内积等于余弦相似度,平方 L2 距离等于 2 – 2 × 余弦相似度,因此它们产生一致的相对排序,但数值与阈值仍不相同。

Gemini Embeddings 官方指南对模型和维度分别说明归一化行为:gemini-embedding-001 的非 3072 维输出需要手动归一化,gemini-embedding-2 的截短输出会自动归一化。不能只凭“都叫 Embedding”假定全部模型和全部维度都已处理。

验证自己的输入时,随机抽取文档向量与查询向量,计算长度是否接近 1,并记录模型名、维度和处理代码。一个接近 1 的长度只能证明该向量已归一化,不能证明它来自同一个模型或能正确表达语义。

给线上检索设置阈值的顺序

  1. 从实际接口文档和配置确认度量、返回值是否转换,以及排序方向。字段名称 score 本身不足以作判断。
  2. 准备有正确来源的相关问题和没有答案的问题,保存两组分数、候选原文和人工判定。
  3. 在固定模型、固定维度及固定分段下试阈值,检查相关片段被排除的数量,以及无关片段被保留的数量;按自己的错误容忍度选择。
  4. 换模型、数据库度量、归一化或分段后重新标定。旧的 0.8 不能直接迁移为新系统的通过线。

相关性分数不是答案正确概率。即使候选方向很近,原文可能是旧版、不同地区或没有直接支持答案;版本和权限应作为明确条件控制,最后仍要核对回答是否有原文依据。

遇到这些结果先停止解释

  • 维度不等:先修输入和集合配置。
  • 零向量、NaN 或无穷值:先查嵌入输出与预处理;pgvector 官方说明向量元素要求有限值,余弦索引不包含零向量。
  • 阈值升高反而保留更多结果:核对你控制的是相似度下限,还是距离上限。
  • 同一查询换模型后分数明显变化:先按新模型重建并校准,不能直接据旧阈值判定质量变差。

读完可以立刻做的一件事,是给自己系统的一条返回结果写清“度量、原始值、转换公式、排序方向”。这四项确认后,再决定阈值和展示给用户的相关程度。

Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/30276.html

赞 (0)
AI小管家的头像AI小管家
Gemini Embedding 怎么用?生成文档与查询向量并验证语义检索
上一篇 1天前
Hugging Face Datasets 怎么筛除无效样本?保留拒绝原因和原始行号
下一篇 1天前

相关推荐

联系我们

联系我们

1

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
关注微信
分享本页
返回顶部