计算机怎么比较两句话的意思
「猫吃鱼」和「小猫捕食鱼类」,字面几乎不重叠,意思却相近;「猫吃鱼」和「今天股市上涨」,字面都很短,意思毫无关系。人一眼可判,程序则需要一个可计算的「意思」表示。Embedding(嵌入)就是目前最成功的答案:把一段文本送进模型,输出一个几百到几千维的浮点数向量。从此「意思相近」变成「向量方向相近」,比较语义变成比较几何。
从 one-hot 到稠密向量
最早的文本表示是 one-hot:词表里每个词占一个维度,词对应的位置是 1,其余全是 0。它有两个致命问题。一是稀疏且维度等于词表大小,几万词就是几万维,向量里几乎全是 0。二是无语义:任何两个词的 one-hot 向量都互相正交,「猫」和「小猫」的相似度与「猫」和「股票」的相似度相等,都精确地等于零。
稠密向量把几万维压到几百上千维,每一维不再对应某个具体的词,而是模型学出来的某种语义因子。语义从此变成几何:意思相近的文本,向量方向相近。衡量方向相近程度的标准工具是余弦相似度——两个向量的点积除以各自的长度,取值负一到一,越大越相近。
手算一个小例子。为了演示取二维向量:A「猫吃鱼」= [0.9, 0.1],B「小猫捕食鱼类」= [0.8, 0.2],C「今天股市上涨」= [0.1, 0.9]。cos(A, B) = (0.9×0.8 + 0.1×0.2) ÷ (√0.82 × √0.68) ≈ 0.74 ÷ 0.75 ≈ 0.99;cos(A, C) = (0.9×0.1 + 0.1×0.9) ÷ (√0.82 × √0.82) ≈ 0.18 ÷ 0.82 ≈ 0.22。两句谈猫的话几乎同向,与股市那句明显不同。实际系统会先把向量归一化(缩放到长度为一),此后点积就等于余弦相似度,检索系统几乎都这么做。
顺带一提,向量空间还有更好玩的性质:经典演示里,词向量做加减能反映语义关系,「国王」减「男人」加「女人」会落在「女王」附近。这是训练把共现模式压进几何结构的副产品,不是精确运算,但足以说明「方向承载语义」并非比喻。
这些向量是怎么学出来的
训练目标一句话:对比学习。从语料构造「正样本对」(同一段话与它的改写、问题与对应答案)和大量「负样本对」,训练模型把正对的向量拉近、负对的推远。推到最后,向量空间自然长成一张语义地图,方向就是意思。负样本的规模与难度是主要工程量:负对越多、越难(比如拿同主题文本当困难负样本),学出的边界越精细,各家 embedding 模型的差距主要就是在数据构造上下功夫。
两个常被忽略的细节:维度高低不直接决定效果,几百维用好了一样够用;归一化之后所有向量都落在单位球面上,检索问题在数学上是「球面上的最近邻搜索」,向量数据库的 ANN 索引(近似最近邻索引,牺牲一点召回换千百倍提速)处理的正是这个问题。
十几行代码跑通全流程
# pip install sentence-transformers
from sentence_transformers import SentenceTransformer
import numpy as np
model = SentenceTransformer("all-MiniLM-L6-v2") # 任一开源 embedding 模型
docs = ["猫吃鱼", "小猫捕食鱼类", "今天股市上涨", "猫咪进食"]
embs = model.encode(docs, normalize_embeddings=True)
query = model.encode(["猫吃什么"], normalize_embeddings=True)
sims = embs @ query.T # 归一化后点积即余弦相似度
top_k = np.argsort(sims.ravel())[-3:][::-1]
print([docs[i] for i in top_k]) # 语义排序,不依赖字面重合
流程三步:encode 把库中每条文本变成向量存起来;查询来了,encode 进同一个向量空间;算相似度取 top-k。数据量大时,第三步交给向量数据库完成。
有一个容易踩的坑:查询与文档必须用同一个模型编码。两个不同模型的向量空间互不相通,跨模型算距离毫无意义;换模型就得全量重编码,这是向量库迁移成本的主要来源。
两个边界
第一,语义匹配不是精确匹配。Embedding 会误召回「形近义远」的内容:搜「苹果手机的价格」,可能召回一篇水果选购指南——字面共享「苹果」,语义完全是两回事。反过来,订单号、错误码这类精确查询也不该走向量检索,等值过滤用传统数据库索引更快更准。生产系统常做混合检索:关键词一路保精确,向量一路保语义,两路结果合并。
第二,Embedding 模型不知道训练截止之后的世界。新出现的产品名与术语在语义地图上没有位置,会被硬塞进最相近的旧概念里。语义地图会过时,选型与使用都要有这个意识。
收尾
最后一句话说清它与 RAG 的关系:Embedding 是 RAG 的地基,检索阶段的本质就是「用问题向量在知识库向量里找最近邻」,把最相关的片段交给生成模型作答。建立起这篇的几何直觉,后面读 RAG 调优的文章,就不会觉得那些参数是玄学。
读者留言
COMMENTS 暂无还没有留言,来说第一句?