AI 基础 | | 约 16 分钟 | 6,153 字

Embedding 向量嵌入详解

理解文本如何变成向量,以及 Embedding 在搜索、推荐、RAG 中的核心作用

什么是 Embedding

我们知道,计算机只能处理数字。那文本、图片、音频这些非结构化数据,怎么让机器”理解”呢?

答案就是 Embedding——把任意数据映射到一个固定维度的向量空间中。

"猫"    → [0.21, -0.45, 0.78, 0.12, ...]   (1536 维)
"狗"    → [0.19, -0.42, 0.81, 0.15, ...]   (1536 维)
"汽车"  → [-0.55, 0.33, -0.12, 0.67, ...]  (1536 维)

注意看,“猫”和”狗”的向量非常接近,而”汽车”的向量和它们差距很大。这就是 Embedding 的核心价值——语义相近的内容,在向量空间中距离也近。


为什么需要 Embedding

传统方法的局限

在 Embedding 出现之前,我们处理文本通常用这些方法:

方法原理缺点
One-Hot Encoding每个词一个维度,只有 0 和 1维度爆炸,无法表达语义关系
Bag of Words统计词频丢失词序信息,无法理解语义
TF-IDF词频 × 逆文档频率仍然是稀疏表示,无法捕捉语义

这些方法的共同问题:它们不理解”含义”。在 One-Hot 编码里,“开心”和”快乐”的距离,跟”开心”和”悲伤”的距离是一样的。

Embedding 解决了什么

Embedding 是一种稠密的、低维的、连续的向量表示。它能:

  1. 捕捉语义关系——“国王 - 男人 + 女人 ≈ 女王”
  2. 支持相似度计算——找到语义最接近的内容
  3. 作为下游任务的输入——分类、聚类、搜索、推荐

文本如何变成向量

Word2Vec 时代

2013 年 Google 发布的 Word2Vec 是 Embedding 的里程碑。它有两种训练方式:

  • CBOW (Continuous Bag of Words):用上下文预测中心词
  • Skip-gram:用中心词预测上下文
训练语料: "我 喜欢 吃 苹果"

Skip-gram 的思路:
  输入 "喜欢" → 预测 "我", "吃"
  输入 "吃"   → 预测 "喜欢", "苹果"

通过大量语料训练后,语义相近的词自然会被映射到相近的位置。

现代 Embedding 模型

现在我们用的 Embedding 模型已经远超 Word2Vec,它们基于 Transformer 架构,能理解整个句子甚至段落的语义:

模型维度提供方特点
text-embedding-3-small1536OpenAI性价比高,适合大多数场景
text-embedding-3-large3072OpenAI精度更高,适合高要求场景
voyage-31024Voyage AI代码和技术文档表现优秀
BGE-M31024BAAI开源,多语言支持好
Cohere embed-v31024Cohere多语言,支持压缩
all-MiniLM-L6-v2384Sentence Transformers开源轻量,本地部署首选

距离度量:如何衡量”相似”

有了向量,我们需要一种方式来衡量两个向量有多”接近”。常用的有三种:

1. 余弦相似度 (Cosine Similarity)

最常用的度量方式。它衡量的是两个向量的方向是否一致,不关心长度。

import numpy as np

def cosine_similarity(a, b):
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

# 值域: [-1, 1]
# 1 = 完全相同方向
# 0 = 正交(无关)
# -1 = 完全相反

2. 欧氏距离 (Euclidean Distance)

衡量两个点在空间中的直线距离。

def euclidean_distance(a, b):
    return np.linalg.norm(a - b)

# 值越小越相似
# 注意:受向量长度影响

3. 点积 (Dot Product)

def dot_product(a, b):
    return np.dot(a, b)

# 同时考虑方向和大小
# 适合向量已归一化的场景

该用哪个?

场景推荐度量原因
文本语义搜索余弦相似度不受文本长度影响
图像相似度欧氏距离特征向量通常已归一化
推荐系统点积需要考虑向量大小(热度)
已归一化的向量三者等价归一化后三种度量排序一致

实战:使用 Embedding API

使用 OpenAI Embedding

from openai import OpenAI
import numpy as np

client = OpenAI()

def get_embedding(text, model="text-embedding-3-small"):
    """获取文本的 Embedding 向量"""
    response = client.embeddings.create(
        input=text,
        model=model
    )
    return response.data[0].embedding

# 获取几个句子的 Embedding
sentences = [
    "我喜欢吃苹果",
    "苹果是我最爱的水果",
    "今天天气真好",
    "Python 是一门编程语言"
]

embeddings = [get_embedding(s) for s in sentences]

# 计算相似度矩阵
for i in range(len(sentences)):
    for j in range(i + 1, len(sentences)):
        sim = np.dot(embeddings[i], embeddings[j]) / (
            np.linalg.norm(embeddings[i]) * np.linalg.norm(embeddings[j])
        )
        print(f"「{sentences[i]}」 vs 「{sentences[j]}」")
        print(f"  相似度: {sim:.4f}")
        print()

输出大概是这样的:

「我喜欢吃苹果」 vs 「苹果是我最爱的水果」
  相似度: 0.8921

「我喜欢吃苹果」 vs 「今天天气真好」
  相似度: 0.3142

「我喜欢吃苹果」 vs 「Python 是一门编程语言」
  相似度: 0.1523

语义相近的句子,相似度确实更高。

使用 Sentence Transformers(本地部署)

from sentence_transformers import SentenceTransformer

# 加载模型(首次会自动下载)
model = SentenceTransformer('all-MiniLM-L6-v2')

sentences = [
    "How to learn machine learning",
    "Best resources for studying ML",
    "I want to buy a new car"
]

# 批量编码
embeddings = model.encode(sentences)

# embeddings.shape = (3, 384)
print(f"向量维度: {embeddings.shape[1]}")

Embedding 的核心应用场景

传统关键词搜索只能匹配字面内容。Embedding 搜索能理解语义:

用户搜索: "头疼怎么办"

关键词搜索结果: 包含"头疼"的文档
Embedding 搜索结果: "头疼"、"偏头痛缓解方法"、"头部疼痛的家庭疗法"
def semantic_search(query, documents, top_k=3):
    """简单的语义搜索实现"""
    query_embedding = get_embedding(query)
    doc_embeddings = [get_embedding(doc) for doc in documents]

    # 计算相似度
    similarities = []
    for i, doc_emb in enumerate(doc_embeddings):
        sim = np.dot(query_embedding, doc_emb) / (
            np.linalg.norm(query_embedding) * np.linalg.norm(doc_emb)
        )
        similarities.append((i, sim))

    # 按相似度排序
    similarities.sort(key=lambda x: x[1], reverse=True)

    return [(documents[i], score) for i, score in similarities[:top_k]]

2. 推荐系统

把用户和物品都映射到同一个向量空间,距离近的就是推荐候选:

用户 A 的兴趣向量: [0.8, 0.2, -0.3, ...]
商品 X 的特征向量: [0.75, 0.25, -0.28, ...]  ← 距离近,推荐!
商品 Y 的特征向量: [-0.5, 0.9, 0.1, ...]     ← 距离远,不推荐

3. RAG(检索增强生成)

这是目前最火的应用。把知识库文档 Embedding 后存入向量数据库,用户提问时先检索相关文档,再交给 LLM 生成回答。我们会在本系列的第三篇文章中详细讲解。

4. 聚类与分类

把文本 Embedding 后,可以用 K-Means 等算法自动聚类,或者用少量标注数据训练分类器。


可视化:高维向量怎么看

1536 维的向量我们没法直接看,但可以用降维算法投影到 2D/3D 空间:

from sklearn.manifold import TSNE
import matplotlib.pyplot as plt

# 假设 embeddings 是 (n, 1536) 的数组
tsne = TSNE(n_components=2, random_state=42)
reduced = tsne.fit_transform(embeddings)

plt.scatter(reduced[:, 0], reduced[:, 1])
for i, label in enumerate(labels):
    plt.annotate(label, (reduced[i, 0], reduced[i, 1]))
plt.title("Embedding 可视化 (t-SNE)")
plt.show()

降维后你会发现,语义相近的点确实聚在一起。这不是巧合,而是 Embedding 模型学到的语义结构。


使用 Embedding 的注意事项

1. 选择合适的模型

不同模型擅长不同任务:

  • 通用文本搜索:OpenAI text-embedding-3-small 够用
  • 代码搜索:Voyage AI 的 voyage-code-3 更合适
  • 多语言场景:BGE-M3 或 Cohere embed-v3
  • 本地部署:all-MiniLM-L6-v2 或 BGE 系列

2. 文本预处理

# 好的做法
text = "如何在 Python 中实现快速排序?"  # 清晰、完整的句子

# 不好的做法
text = "快排 py"  # 太短,语义信息不足

3. 分块策略

长文档需要切分成合适大小的块再 Embedding:

  • 太短:语义信息不足
  • 太长:语义被稀释
  • 推荐:200-500 个 token 一块,带适当重叠

4. 成本控制

模型价格 (每百万 token)适合场景
text-embedding-3-small$0.02大规模索引
text-embedding-3-large$0.13高精度需求
开源模型 (本地)硬件成本数据敏感场景

总结

Embedding 是连接人类语言和机器理解的桥梁。理解了它,你就理解了语义搜索、推荐系统、RAG 等一系列 AI 应用的基础。

核心要点:

  • Embedding 把非结构化数据映射为稠密向量
  • 语义相近的内容在向量空间中距离也近
  • 余弦相似度是最常用的度量方式
  • 选择模型时要考虑任务类型、语言、成本和部署方式

向量是 AI 理解世界的方式。当我们学会用向量思考,就打开了一扇通往智能应用的大门。下一篇我们来聊聊这些向量该存在哪里——向量数据库。

评论

加载中...

相关文章

分享:

评论

加载中...