当前位置:首页 > 文章列表 > 科技周边 > 人工智能 > Embedding 向量归一化怎样影响相似度计算

Embedding 向量归一化怎样影响相似度计算

来源:17golang原创 2026-10-18 11:35:34 0浏览 收藏

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||)。它把长度因素拿掉,保留夹角信息。对语义检索来说,这通常更适合比较文本方向,但是否应该这样做仍取决于模型训练目标和索引端的距离定义。

原始 Embedding、L2 归一化、单位向量、点积和余弦相似度的关系说明图
图1:Embedding 归一化与相似度度量的关系说明图,区分方向和长度对分数的影响;这是静态说明图,不是运行截图。

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。

对于单位向量,欧氏距离与余弦相似度也存在固定的单调关系,因此在同一批单位向量中,按余弦从高到低或按欧氏距离从低到高,通常会得到一致的排序。这个结论依赖“双方都已归一化”,一旦把原始向量混进来,就不能继续套用。

模型训练目标、查询文档向量、单位长度约定与三种检索度量的关系说明图
图2:向量检索度量选择说明图,展示归一化约定与 dot、cosine、euclidean 的关系;这是静态说明图,不是运行截图。

接入前要避免的三个分数误读

  • 把点积当成天然的余弦。只有两个输入都为单位向量时,二者才数学等价。
  • 只归一化一侧。查询和文档必须使用相同的归一化口径,否则阈值和排序都难以解释。
  • 忽略模型训练目标。度量方式是模型和索引契约的一部分,换度量后应重新评估召回与排序,而不是只比较分数大小。

落地时可以把三个字段写进配置或模型卡:是否归一化、使用哪种度量、分数是越大越相似还是越小越接近。这样迁移向量库、替换 embedding 模型或调整阈值时,才不会把不同口径的分数混在一起。

常见问题

归一化会让 embedding 的语义信息丢失吗?

它会舍弃向量长度这一维度信息,但保留方向信息。是否适合舍弃,要看长度是否承载了模型训练希望利用的信号;语义检索不能只凭公式做决定。

已经归一化后还可以调用 cosine 吗?

可以,结果在数学上仍是余弦相似度,但计算时通常会再次处理范数。Sentence Transformers 官方建议在确定输入已归一化时使用 dot,以减少重复操作。

为什么换成 dot 后阈值不能照搬?

如果前后输入状态或分数方向发生变化,阈值就不再代表同一件事。应先固定归一化约定,再在目标数据上重新确定阈值和排序指标。

总结

Embedding 归一化的核心影响只有一句话:它把点积中的向量长度因素固定掉,让单位向量的点积等价于余弦相似度。工程上不要孤立选择 cosine 或 dot,而要同时记录模型训练目标、向量是否归一化、查询与文档是否同口径,以及距离排序方向;这四项一致,分数才有可解释性。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Chrome DevTools 怎样复制带请求头的网络请求Chrome DevTools 怎样复制带请求头的网络请求
上一篇
Chrome DevTools 怎样复制带请求头的网络请求
RAG 检索怎样选择 top-k 并避免上下文过长
下一篇
RAG 检索怎样选择 top-k 并避免上下文过长
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    521次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    578次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    604次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    554次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    375次使用