Embedding 向量归一化后应该用点积还是余弦相似度
来源:17golang原创
时间:2026-09-05 12:05:29 103浏览 收藏
做向量检索时,最容易被忽略的不是公式,而是“向量到底有没有被统一归一化”。如果查询向量和文档向量都经过 L2 归一化,那么点积与余弦相似度在数学上等价;在 Sentence Transformers 这类链路里,通常可以直接用点积,避免再次计算范数。只要有一侧没归一化、模型输出混用,或索引是旧数据,就不能只凭标题判断。
选择原则很简单:确认查询和文档向量都已按同一规则归一化,就用点积;输入状态不确定,或者需要在接口层自我保护,就用余弦并显式统一预处理。真正要审计的是归一化边界,而不是“点积”和“余弦”哪个听起来更高级。
- 单位向量满足 ||q||=||d||=1 时,q·d 与 cos(q,d) 相等。
- 归一化后的批量检索优先点积,未归一化或混合输入优先余弦。
- 模型、索引、查询、阈值必须共享同一预处理配置,不能只改计算函数。
归一化到底改变了什么?
Embedding 的方向通常承载语义关系,长度则可能受到文本长度、模型池化方式或业务输入差异影响。L2 归一化会把向量缩放到单位长度,方向不变,范数被固定为 1。于是相似度计算关注“夹角”,不会再因为某条向量数值整体偏大而改变排序。
这里有一个需要先划清的资产边界:查询侧与文档侧都必须使用同一模型、同一维度、同一归一化规则。只归一化查询向量,或者把旧索引里的原始向量与新生成的单位向量混在一起,都会让分数失去可比性。

为什么归一化后点积等于余弦?
余弦相似度的公式是:
cos(q, d) = (q · d) / (||q|| × ||d||)
当 q 和 d 都已经做 L2 归一化时,两个范数都是 1,分母就变成 1,因此:
cos(q, d) = q · d
Sentence Transformers 的官方文档把 cosine、dot、euclidean 和 manhattan 列为可选相似度函数,并特别说明:如果模型末尾已有 Normalize 模块,选择 dot 是合理的,因为对归一化向量来说两者等价,而 cosine 还会再次归一化。这个结论是性能和一致性的工程提示,不代表所有 Embedding 都默认满足单位范数。

检索链路中应该怎样选?
如果使用 Sentence Transformers,可以在编码阶段明确归一化,再用点积计算矩阵相似度:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
queries = model.encode(["如何给向量归一化"], normalize_embeddings=True)
documents = model.encode(
["使用 L2 范数把 Embedding 缩放到单位长度"],
normalize_embeddings=True,
)
scores = queries @ documents.T
这段代码的关键不在运算符,而在两个 normalize_embeddings=True。如果文档向量已经提前入库,查询侧必须复用当时的模型和预处理约定。若无法保证这一点,则先统一输入,再使用框架提供的余弦函数:
import torch import torch.nn.functional as F q = torch.tensor([[0.8, 0.6]]) d = torch.tensor([[0.6, 0.8]]) score = F.cosine_similarity(q, d, dim=1)
不要把点积当作“总是更快的余弦”。只有在向量已归一化、矩阵乘法和阈值都按同一分数定义建立时,点积才是更直接的选择。
| 输入状态 | 建议计算 | 主要风险 |
|---|---|---|
| 查询、文档均已 L2 归一化 | 点积 | 索引重建后忘记沿用归一化 |
| 任一侧未归一化 | 余弦 | 把向量长度误当成语义相似度 |
| 输入状态未知或多来源混合 | 先统一,再决定 | 分数阈值与历史数据不可比 |
上线前怎样做一致性检查?
把它当成一次小型威胁建模:要保护的是召回排序和阈值判断,攻击路径则是预处理漂移。发布前至少留下以下记录:
- 模型指纹:记录模型名称、版本或提交标识、向量维度和编码参数。
- 归一化状态:明确索引构建、离线导入、在线查询三条路径是否都做 L2 归一化。
- 分数抽样:对同一批 q、d 同时计算余弦和点积;只有两者都接近单位范数时,才预期分数一致。
- 阈值复核:切换相似度函数后重新检查召回阈值,不要直接复用未经比较的旧阈值。
一个实用的审计结论是:分数不一致时,先查范数和数据来源,再查函数名。函数换对了但索引没重建,结果仍然可能错误。
相关问题
归一化后点积的分数范围是多少?
当两边都是单位向量时,点积等于余弦相似度,范围通常在 -1 到 1 之间。具体分布仍取决于模型和数据,不能把某个固定阈值套到所有模型上。
只对查询向量做归一化可以吗?
不建议。此时点积仍然会受到文档向量长度影响;除非业务明确需要长度参与排序,否则应让查询和文档共享同一预处理链路。
向量数据库里写 dot 还是 cosine?
先看入库向量和查询向量是否都已归一化,以及数据库索引对度量的要求。两边都是单位向量时可选 dot;状态不确定时,优先统一数据并重新确认阈值。
参考资料:Sentence Transformers Semantic Textual Similarity、SentenceTransformer API、PyTorch cosine_similarity。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
299 收藏
-
科技周边 · 人工智能 | 1天前 | oauth · 人工智能 · mcp · Agent 工程 · resource MCP OAuth 2.1 RFC 8707 token audience 远程 MCP123 收藏
-
119 收藏
-
293 收藏
-
科技周边 · 人工智能 | 1天前 | 异步任务 · mcp · 协议扩展 · MCP Tasks io.modelcontextprotocol/tasks tasks/get tasks/update260 收藏
-
305 收藏
-
377 收藏
-
398 收藏
-
科技周边 · 人工智能 | 2天前 | 人工智能 · api设计 · gemini · AI Agent Gemini Interactions API previous_interaction_id store=false 多轮状态432 收藏
-
427 收藏
-
140 收藏
-
216 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习