Embedding 向量归一化怎样影响相似度计算
来源:17golang原创
时间:2026-10-18 11:35:34 144浏览 收藏
Embedding 做相似度计算时,最容易混淆的是“向量方向相近”和“向量长度较大”。如果直接使用点积,长度也会参与分数;如果先做 L2 归一化,所有向量长度都变成 1,此时点积就与余弦相似度等价。实际项目应该先确认模型和向量库采用的约定,再决定是否归一化,不能只看一个分数名称。
官方资料:https://www.sbert.net/docs/sentence_transformer/usage/semantic_textual_similarity.html
官方任务文档:https://huggingface.co/docs/transformers/main/en/tasks/sentence_transformers
为什么同一个方向的点积还会变大变小
设两个向量为 a 和 b。点积可以写成 a·b = ||a|| ||b|| cos(θ),它同时受夹角和两个向量长度影响。两个文本的语义方向可能接近,但只要其中一个向量的范数更大,点积就可能更高。因此,原始点积回答的是“方向和长度合在一起有多大”,并不只是“方向有多像”。
余弦相似度会除以两个向量的范数:cos(a,b) = (a·b) / (||a|| ||b||)。它把长度因素拿掉,保留夹角信息。对语义检索来说,这通常更适合比较文本方向,但是否应该这样做仍取决于模型训练目标和索引端的距离定义。

L2 归一化为什么能让点积等价于余弦
L2 归一化就是把向量除以自身的 L2 范数:a' = a / ||a||。归一化后的 a' 和 b' 长度都是 1,所以 a'·b' = cos(θ)。这不是把语义重新编码了一次,而是改变了比较时保留的因素:向量方向保留,长度差异被压平。
Sentence Transformers 的 Normalize 模块正是把 embedding 处理为单位长度向量。官方文档还特别说明:如果模型输出末尾已经有归一化模块,选择 dot 度量即可,因为 cosine 会再次归一化输入,dot 可以少做一次重复工作。
下面的写法把归一化和度量显式放在同一处,避免查询向量和文档向量走不同分支。示例只展示调用关系,不代表已经在本机运行。
from sentence_transformers import SentenceTransformer, SimilarityFunction
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
sentences = ["如何重置数据库连接池", "数据库连接池怎样恢复"]
# 让查询和文档使用同一套 L2 归一化约定。
embeddings = model.encode(sentences, normalize_embeddings=True)
# 单位向量的点积就是余弦相似度,避免再次做归一化。
model.similarity_fn_name = SimilarityFunction.DOT_PRODUCT
scores = model.similarity(embeddings[:1], embeddings[1:])
print(scores)
把未归一化点积、余弦和单位向量点积分开
可以把三种结果放在同一张对照表里。未归一化点积保留范数影响;余弦相似度在计算时主动消除范数影响;单位向量点积则把消除范数的动作提前到 embedding 生成或写入向量库之前。
| 输入状态 | 计算方式 | 分数主要表达 | 注意点 |
|---|---|---|---|
| 原始向量 | dot | 方向与长度的联合贡献 | 长度差异可能改变排序 |
| 原始向量 | cosine | 方向接近程度 | 计算时会做范数处理 |
| 单位向量 | dot | 方向接近程度 | 与 cosine 数学等价,适合固定约定 |
| 单位向量 | euclidean | 单位球面上的距离关系 | 排序方向要按距离大小正确处理 |
用 Sentence Transformers 时,normalize_embeddings 和 similarity_fn_name 要一起记录。只在写入向量库时归一化、查询时忘记归一化,会让两侧分数失去可比性;反过来,如果模型本身已经输出单位向量,又在检索组件中重复转换,通常只是增加不必要的计算。
from sentence_transformers import SentenceTransformer, util
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
sentences = ["向量检索需要统一度量", "检索系统要固定分数定义"]
# 保留一份原始向量,用来观察范数是否参与点积。
raw = model.encode(sentences, normalize_embeddings=False)
# 另一份固定为单位向量,适合与 dot_score 配套。
unit = model.encode(sentences, normalize_embeddings=True)
# cosine 会按公式处理范数;raw_dot 会保留长度影响。
cosine = util.cos_sim(raw[0], raw[1])
raw_dot = util.dot_score(raw[0], raw[1])
# 单位向量点积与 cosine 的语义口径一致。
unit_dot = util.dot_score(unit[0], unit[1])
print(cosine, raw_dot, unit_dot)
在实际检索中怎样选度量
选择顺序应该是“先看模型说明,再看存储约定,最后看查询代码”。有些模型明确按 dot-product 训练或提供已经归一化的向量,这时直接使用 dot 更自然;如果系统以余弦相似度定义阈值,就要确保查询和文档向量都按相同规则计算。不能因为某个库支持 cosine,就把所有模型都无条件改成 cosine。
对于单位向量,欧氏距离与余弦相似度也存在固定的单调关系,因此在同一批单位向量中,按余弦从高到低或按欧氏距离从低到高,通常会得到一致的排序。这个结论依赖“双方都已归一化”,一旦把原始向量混进来,就不能继续套用。

接入前要避免的三个分数误读
- 把点积当成天然的余弦。只有两个输入都为单位向量时,二者才数学等价。
- 只归一化一侧。查询和文档必须使用相同的归一化口径,否则阈值和排序都难以解释。
- 忽略模型训练目标。度量方式是模型和索引契约的一部分,换度量后应重新评估召回与排序,而不是只比较分数大小。
落地时可以把三个字段写进配置或模型卡:是否归一化、使用哪种度量、分数是越大越相似还是越小越接近。这样迁移向量库、替换 embedding 模型或调整阈值时,才不会把不同口径的分数混在一起。
常见问题
归一化会让 embedding 的语义信息丢失吗?
它会舍弃向量长度这一维度信息,但保留方向信息。是否适合舍弃,要看长度是否承载了模型训练希望利用的信号;语义检索不能只凭公式做决定。
已经归一化后还可以调用 cosine 吗?
可以,结果在数学上仍是余弦相似度,但计算时通常会再次处理范数。Sentence Transformers 官方建议在确定输入已归一化时使用 dot,以减少重复操作。
为什么换成 dot 后阈值不能照搬?
如果前后输入状态或分数方向发生变化,阈值就不再代表同一件事。应先固定归一化约定,再在目标数据上重新确定阈值和排序指标。
总结
Embedding 归一化的核心影响只有一句话:它把点积中的向量长度因素固定掉,让单位向量的点积等价于余弦相似度。工程上不要孤立选择 cosine 或 dot,而要同时记录模型训练目标、向量是否归一化、查询与文档是否同口径,以及距离排序方向;这四项一致,分数才有可解释性。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
191 收藏
-
296 收藏
-
317 收藏
-
375 收藏
-
216 收藏
-
174 收藏
-
144 收藏
-
391 收藏
-
199 收藏
-
133 收藏
-
349 收藏
-
318 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习