Embedding 模型与语义搜索
从文本 Embedding 到多模态 Embedding,深入理解语义搜索的核心技术
什么是 Embedding
Embedding 是将离散的符号化数据(如文字、图像、音频)映射到连续的高维向量空间中的一种表示学习方法。其核心思想是:在向量空间中,语义相近的对象应当具有相近的向量表示。
形式化地,一个 Embedding 模型可以看作一个函数 $f: X \rightarrow \mathbb{R}^d$,它将输入 $x$(如一个句子或一张图片)映射到一个 $d$ 维的实数向量。这个向量被称为 Embedding 向量 或 特征向量。
Embedding 的核心特性包括:
- 语义保留:相似的输入在向量空间中距离相近,例如 "猫" 和 "狗" 的向量距离远小于 "猫" 和 "汽车"。
- 维度压缩:将高维的离散表示(如 One-hot 编码,维度为词表大小)压缩为低维稠密向量(通常为 128~4096 维)。
- 可计算性:Embedding 向量支持向量化运算,可高效地进行相似度计算和检索。
在现代 RAG(检索增强生成)系统中,Embedding 模型是整个流水线的基石——它将文档库中的文本转换为向量索引,再将用户查询编码为同一语义空间下的向量,通过最近邻搜索召回最相关的上下文。
文本 Embedding 模型对比
目前主流的文本 Embedding 模型主要来自三个方向:开源社区(BGE、E5、Instructor)、商业 API(OpenAI text-embedding-3)以及多语言模型(multilingual-E5)。下表从多个维度进行对比:
| 模型 | 参数量 | 输出维度 | 最大输入长度 | MTEB 基准(平均) | 特点 |
|---|---|---|---|---|---|
| BGE-base-zh-v1.5 | 102M | 768 | 512 tokens | 58.5 | 中文优化,支持 Dense + Sparse 混合检索 |
| BGE-large-zh-v1.5 | 326M | 1024 | 512 tokens | 60.2 | 中文场景最强开源模型之一 |
| E5-mistral-7b-instruct | 7B | 4096 | 4096 tokens | 66.6 | 基于 LLM 的 Embedding,维度极高 |
| text-embedding-3-small | 未知 | 512/1536 可调 | 8191 tokens | 62.3 | OpenAI API,性价比高 |
| text-embedding-3-large | 未知 | 256/1024/3072 可调 | 8191 tokens | 64.6 | OpenAI API,质量最优 |
| Instructor-XL | 1.5B | 768 | 512 tokens | 61.3 | 支持指令(Instruction)定制任务类型 |
| multilingual-E5-large | 335M | 1024 | 512 tokens | 64.4 | 覆盖 100+ 语言,跨语言检索首选 |
选型建议:
- 中文场景优先选择 BGE 系列(尤其是 bge-large-zh-v1.5)。
- 需要多语言支持时选择 multilingual-E5。
- 追求最佳质量且有 API 预算时选择 text-embedding-3-large。
- 需要对检索任务类型进行细粒度控制时选择 Instructor 系列。
多模态 Embedding
随着多模态大模型的发展,Embedding 技术已从纯文本扩展到图像、音频、视频等多种模态。
CLIP(Contrastive Language-Image Pre-training)
CLIP 由 OpenAI 提出,是单模态 Embedding 向多模态扩展的代表性工作。它使用双塔架构:
- 文本编码器(通常为 Transformer):将文本映射为向量 $v_t$
- 图像编码器(通常为 ViT 或 ResNet):将图像映射为向量 $v_i$
训练时使用 4 亿对(图像,文本)数据,通过对比学习拉近匹配对的向量距离,推远非匹配对的向量距离。训练完成后,CLIP 可以将图像和文本投影到同一语义空间,直接计算跨模态的相似度。
ImageBind
Meta 提出的 ImageBind 进一步将 Embedding 空间扩展到六种模态:图像、文本、音频、深度、热成像、IMU 数据。其核心思路是利用"配对数据链"——例如(图像,音频)对和(图像,文本)对——间接对齐非直接配对的模态(如音频与文本)。
多模态 Embedding 的关键公式可以表示为:
$$ \text{sim}(x, y) = \frac{f(x) \cdot g(y)}{|f(x)| \cdot |g(y)|} $$
其中 $f$ 和 $g$ 分别是模态 $x$ 和 $y$ 的编码器,当 $f = g$ 时即为单模态场景。
语义相似度度量
将输入映射为 Embedding 向量后,需要通过相似度度量来判断两个向量的语义接近程度。常用的度量方法有三种:
余弦相似度(Cosine Similarity)
$$ \text{cosine_sim}(a, b) = \frac{a \cdot b}{|a| |b|} = \frac{\sum_{i=1}^{d} a_i b_i}{\sqrt{\sum_{i=1}^{d} a_i^2} \sqrt{\sum_{i=1}^{d} b_i^2}} $$
取值范围 $[-1, 1]$,关注向量的方向而非长度。这是语义搜索中最常用的度量方式,因为 Embedding 向量通常经过 L2 归一化,余弦相似度退化为点积。
点积(Dot Product)
$$ \text{dot}(a, b) = a \cdot b = \sum_{i=1}^{d} a_i b_i $$
取值范围 $(-\infty, +\infty)$。当向量已归一化时,点积等价于余弦相似度;当未归一化时,点积会同时受向量方向和长度影响。
欧氏距离(Euclidean Distance)
$$ |a - b|2 = \sqrt{\sum^{d} (a_i - b_i)^2} $$
取值范围 $[0, +\infty)$,度量向量在欧几里得空间中的绝对距离。值越小表示越相似。
度量对比与选型
| 度量方法 | 取值范围 | 是否受长度影响 | 归一化后 | 适用场景 |
|---|---|---|---|---|
| 余弦相似度 | $[-1, 1]$ | 否 | 不变 | 语义搜索的默认选择 |
| 点积 | $(-\infty, \infty)$ | 是 | 等价于余弦 | 向量未归一化时的替代方案 |
| 欧氏距离 | $[0, \infty)$ | 是 | 等价于余弦(单调) | 聚类算法常用 |
实践中:大多数 Embedding 模型输出后都会进行 L2 归一化,此时余弦相似度和点积等价,欧氏距离与余弦相似度呈单调负相关。因此在不涉及距离敏感算法(如 K-Means)时,直接使用余弦相似度即可。
Embedding 模型的训练
对比学习(Contrastive Learning)
对比学习是训练 Embedding 模型的核心范式。其基本思路是:给定一个查询 $q$,从候选池中区分出正样本 $p$(与 $q$ 语义相关)和负样本 $n$(与 $q$ 语义无关)。模型学习到的 Embedding 应当使得 $\text{sim}(q, p) > \text{sim}(q, n)$。
InfoNCE Loss
InfoNCE(Info Noise Contrastive Estimation)是对比学习中最常用的损失函数:
$$ \mathcal{L}{\text{InfoNCE}} = -\log \frac{\exp(\text{sim}(q, p) / \tau)}{\exp(\text{sim}(q, p) / \tau) + \sum^{N} \exp(\text{sim}(q, n_i) / \tau)} $$
其中 $\tau$ 是温度系数(temperature),控制对负样本的惩罚力度。$\tau$ 越小,模型对负样本的区分越严格;$\tau$ 越大,负样本间差距被平滑。
Batch Negative 策略
Batch Negative(也称为 In-Batch Negative)是一种高效的负样本构建方式:在一个 Batch 中,每个样本的配对样本为正例,Batch 内其他样本自动成为该样本的负例。假设 Batch size 为 $B$,每个样本的负例数量从 $1$ 提升至 $B-1$,显著提高了训练效率。
# 伪代码:Batch Negative 下的对比损失
scores = sim_matrix(query_embeddings, doc_embeddings) # [B, B]
labels = torch.arange(B) # 对角线为正例
loss = cross_entropy(scores / temperature, labels)这种策略是当前几乎所有 SOTA Embedding 模型的标准训练方式。
实际应用代码示例
以下使用 sentence-transformers 库演示如何加载 Embedding 模型并计算文本相似度:
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
# 加载中文 Embedding 模型(首次运行会自动下载)
model = SentenceTransformer("BAAI/bge-base-zh-v1.5")
# 定义待比较的文本
sentences = [
"今天天气真不错,适合出去散步。",
"明日将会下雨,建议带伞出门。",
"阳光明媚,微风习习,是个户外运动的好日子。",
"Mistral AI 发布了新一代大模型,性能大幅提升。",
]
# 计算 Embedding 向量
embeddings = model.encode(sentences, normalize_embeddings=True)
# 计算余弦相似度矩阵
sim_matrix = cosine_similarity(embeddings)
# 打印相似度结果
for i in range(len(sentences)):
for j in range(i + 1, len(sentences)):
print(
f"[{i}] vs [{j}]: {sim_matrix[i][j]:.4f} "
f"| {sentences[i][:16]:16s} <-> {sentences[j][:16]}"
)输出示例:
[0] vs [1]: 0.4321 | 今天天气真不错,适合出... <-> 明日将会下雨,建议带...
[0] vs [2]: 0.7812 | 今天天气真不错,适合出... <-> 阳光明媚,微风习习,...
[0] vs [3]: 0.1234 | 今天天气真不错,适合出... <-> Mistral AI 发布了新...
[1] vs [2]: 0.5102 | 明日将会下雨,建议带... <-> 阳光明媚,微风习习,...
[1] vs [3]: 0.0978 | 明日将会下雨,建议带... <-> Mistral AI 发布了新...
[2] vs [3]: 0.0891 | 阳光明媚,微风习习,... <-> Mistral AI 发布了新...可以看到,描述天气的文本(0 和 2)之间的相似度高达 0.78,而与技术新闻(3)的相似度均在 0.12 以下,充分体现了 Embedding 模型对语义信息的捕捉能力。
在 RAG 系统中使用 Embedding
from sentence_transformers import SentenceTransformer
import numpy as np
model = SentenceTransformer("BAAI/bge-base-zh-v1.5")
# 文档库
documents = [
"Python 是一种广泛使用的高级编程语言。",
"Transformers 是深度学习中的一种重要架构。",
"RAG 结合了检索和生成两种技术。",
"余弦相似度用于衡量两个向量的相似程度。",
]
# 构建向量索引
doc_embeddings = model.encode(documents, normalize_embeddings=True)
def search(query: str, top_k: int = 2):
"""基于 Embedding 的语义搜索"""
q_emb = model.encode([query], normalize_embeddings=True)
scores = np.dot(q_emb, doc_embeddings.T)[0]
top_indices = np.argsort(scores)[::-1][:top_k]
return [(documents[i], scores[i]) for i in top_indices]
# 检索示例
results = search("Transformer 在 NLP 中有哪些应用?")
for doc, score in results:
print(f" [{score:.4f}] {doc}")输出示例:
[0.7123] Transformers 是深度学习中的一种重要架构。
[0.4512] RAG 结合了检索和生成两种技术。即便查询中没有出现 "深度学习" 或 "架构" 等关键词,模型依然能正确召回相关文档,这正是语义搜索相较于传统关键词搜索的核心优势。
总结
Embedding 模型将非结构化的文本、图像等数据转化为结构化的向量表示,是语义搜索、RAG、推荐系统等应用的基础。本文从 Embedding 的定义出发,对比了主流文本 Embedding 模型,介绍了多模态 Embedding 的进展,分析了相似度度量的选型,并讨论了对比学习的训练原理。通过代码示例展示了 Embedding 模型在实际语义搜索中的使用方法。掌握 Embedding 技术,是构建现代 AI 系统的关键一步。