嵌入(Embedding)
嵌入把文本等对象编码成数值向量,使程序能够计算它们的相似程度。向量表示有助于检索,但相似并不等于事实相同。
理解与应用
嵌入是一种把对象表示为数值向量的方法。在文本检索中,编码模型把句子或文档映射到一组数字,查询也经过相应编码;程序随后比较向量之间的距离或相似度。训练会影响哪些对象在这个空间里接近,因此向量通常不能靠逐个数字直接读出一句话的含义。
例如员工问“酒店钱能报多少”,文档写的是“住宿费用标准”。两者用词不同,但与报销住宿相关,适合文本检索的嵌入模型有机会把它们放到相近位置。不过,“可以报销住宿费”和“不可以报销住宿费”也围绕同一主题,可能同样接近。向量能够帮助寻找候选,是否满足问题仍要阅读原文中的否定、日期和适用条件。
相似度的计算方法也会影响排序。余弦相似度比较方向,点积还受到向量长度影响;把向量归一化为单位长度后,点积与余弦值相同。实际使用哪一种,应与编码模型的训练方式和索引设置一致,不能只因为某个数值看起来更大就认为检索更好。
向量通常需要由兼容的模型和配置生成。更换编码模型后,即使维度相同,新旧坐标也未必可比较,往往需要重新编码资料并验证检索结果。选择模型时,中文、领域术语、文档长度和任务类型都比单看维度更有意义;保存模型版本和原文来源,才能在结果异常时追查表示是怎样生成的。
动手试一试:余弦与点积为什么可能给出不同偏好
这些是手工设置的二维向量,不是文本编码结果。同方向的两个向量余弦相同,点积却随长度改变。这个几何差异解释了为什么编码模型、归一化方式和检索度量需要配套。
将代码保存为 example.py,使用 Python 3.10+ 运行 python3 example.py。仅使用标准库,无需密钥,不会调用外部模型。
Python 代码
from math import sqrt
query = (1.0, 0.0)
vectors = {
"同方向,长度1": (1.0, 0.0),
"同方向,长度3": (3.0, 0.0),
"偏离45度": (1.0, 1.0),
}
def dot(a, b):
return sum(x * y for x, y in zip(a, b))
def norm(v):
return sqrt(dot(v, v))
for name, vector in vectors.items():
cosine = dot(query, vector) / (norm(query) * norm(vector))
print(f"{name}: 点积={dot(query, vector):.1f},余弦={cosine:.3f}")运行结果
同方向,长度1: 点积=1.0,余弦=1.000 同方向,长度3: 点积=3.0,余弦=1.000 偏离45度: 点积=1.0,余弦=0.707
常见误区
- 把高度相似的向量当成内容一致的证明,可能漏掉否定词、版本或生效日期的差别。
- 混用不同编码模型产生的向量,即使它们长度相同,也可能使相似度失去可解释性。
前置与延伸
建议先读
相关概念
参考与版本
Apollo 原创讲解与教学示例。参考资料用于核对技术定义;核验日不代表资料的发布日期。
- Sentence Transformers:Semantic Textual Similarity ↗
已核对官方文档对向量与相似度的说明;不采用文档里的模型分数作为本文实验结果。 · 核验:2026-10-10