第二章 · 向量表示与相似性度量 本章要回答的三个问题:一个向量在被写进数据库之前经历了什么,哪些坑在生成阶段就已埋下?内积、欧氏距离、余弦相似度这三个几乎相同的公式,分别该在什么时候用?入库前的规范化与预处理,到底解决了什么真问题、又有哪些是以讹传讹? 为什么会有这一章 线上故障复盘里有一类反复出现的剧本:召回率莫名偏低,排查索引参数、机器负载、过滤条件,最后发现问题出在入库之前——文本被整篇塞进模型导致截断、查询向量没做归一化而库里的向量都归一化了、新旧两批数据用了不同版本的嵌入模型。这类问题的恼人之处在于它们不报错:维度对得上、距离算得出、结果看起来"也还行",只是质量悄悄烂掉了。 表示层就是向量检索的地基。
本章要回答的三个问题:一个向量在被写进数据库之前经历了什么,哪些坑在生成阶段就已埋下?内积、欧氏距离、余弦相似度这三个几乎相同的公式,分别该在什么时候用?入库前的规范化与预处理,到底解决了什么真问题、又有哪些是以讹传讹?
线上故障复盘里有一类反复出现的剧本:召回率莫名偏低,排查索引参数、机器负载、过滤条件,最后发现问题出在入库之前——文本被整篇塞进模型导致截断、查询向量没做归一化而库里的向量都归一化了、新旧两批数据用了不同版本的嵌入模型。这类问题的恼人之处在于它们不报错:维度对得上、距离算得出、结果看起来"也还行",只是质量悄悄烂掉了。
表示层就是向量检索的地基。嵌入模型决定了"语义相近则向量相近"这条公理在多大程度上成立,度量口径决定了"相近"用哪把尺子量,预处理决定了进入索引的数据是否自洽。地基歪一层,上面所有的索引优化都在放大误差而不是缩小误差。这一章把生成、度量、预处理三件事依次讲清,让你在动第三章的索引之前,先确保进库的东西是对的。
读完本章,你应当能做这些判断和操作:为一个新场景选择嵌入模型时,说清维度、语言覆盖、最大输入长度、更新频率这几个约束怎么权衡;把一批文本正确切块、批量编码、校验维度与数值范围,而不是整篇硬塞;在欧氏距离、内积、余弦三者之间做出有依据的选择,并能解释"归一化之后内积序等价于余弦序"这条性质在工程上省了多少事;建立向量入库前的校验清单——维度一致、类型统一、归一化策略统一、模型版本标记,把上一段说的那类静默故障挡在门外。
这些能力看似朴素,却是最容易被跳过的一层。第三章讲的所有索引算法,都默认输入向量是"干净的、可比的";本章就是负责这个默认成立。
还要提醒本章内容的性质:它产生的收益平时隐形——一切正常时没有人记得归一化的好;失灵时却让全部下游优化一起失效。这种"正收益不可见、负故障全局化"的地基层,值得用最高的评审标准对待,也值得在团队内把本章的清单固化为入库代码与例行巡检,而不是留在某个人的记忆里。
三节按数据流顺序排布。2.1 讲嵌入怎么生成:从模型的编码与池化机制,到维度与成本怎么权衡,再到多模态双塔结构为什么能让文字和图片落进同一空间;你会看到一个批量编码的完整会话,包括切块策略和版本标记。2.2 讲相似性度量:用同一组手算得出的数字,把三种度量的计算过程完整走一遍,看它们在什么情况下给出一致结论、什么情况下翻脸不认;再给出选型表——什么数据用什么尺子。2.3 讲预处理与规范化:归一化为什么能让内积和余弦合二为一,float32 与半精度之间怎么取舍,重复向量与脏维度怎么清理。
三节的依赖关系是单向的:度量口径的选择(2.2)会反过来约束预处理策略(2.3),而两者都建立在 2.1 产出的向量质量之上。
需要的数学不超过高中范围:知道向量长度怎么算、内积是逐项相乘再求和、余弦定理描述夹角。本章会用一段可运行的代码把三个度量的计算逐步展开,每个中间值都打印出来对照,不要求任何机器学习背景。唯一的前置是第一章的 1.1——你需要先接受"向量相似即语义相似"这个公理及其边界。
本章的知识流如下:
走出本章后有两条去向:带着"干净的向量与选定的口径"进入第三章,看索引怎么在这个基础上把检索加速几个数量级;或者直接进入第五章 5.5,因为度量口径一旦改变,评估基线必须重算。无论如何,请记住本章的一个反复出现的结论:表示层的错误不会报错,只会让后面的优化悄悄失效——值得在每个项目立项时花一个下午把清单过一遍。