1、Embedding基础:什么是Embedding、为什么需要Embedding、Embedding在NLP中的核心地位
好,咱们正式开始。第一章,先聊清楚最基础的东西——Embedding。
很多初学者一上来就盯着各种模型架构看,结果越看越懵。我个人习惯是,先把“这玩意儿到底在解决什么问题”搞明白,后面学起来才顺。Embedding 就是那个绕不开的起点。
1.1 什么是Embedding?说白了就是“翻译”
计算机不认识“猫”、“狗”、“苹果”。它只认数字,而且最好是固定长度的数字列表。
Embedding 干的事,就是把一个离散的、人类能懂的东西(比如一个词、一句话、一张图),映射到一个连续的、稠密的向量空间里。这个向量,就叫 Embedding 向量。
举个例子:
- “猫” → [0.23, -0.45, 0.67, 0.12, ...]
- “狗” → [0.21, -0.42, 0.65, 0.15, ...]
- “苹果” → [-0.11, 0.78, -0.33, 0.91, ...]
你看,“猫”和“狗”的向量很接近,因为它们都是宠物、动物。“苹果”的向量离它们就远一些。这就是 Embedding 的核心——用向量之间的距离,来表达语义上的相似度。
核心定义:Embedding 是将高维、稀疏、离散的符号数据,映射到低维、稠密、连续的实数向量空间的一种表示学习技术。
嗯,这里要注意:传统方法(比如 One-hot 编码)也会把词变成向量,但那是“稀疏”的——一个词对应一个超长向量,里面只有一个 1,其他全是 0。维度等于词表大小,几万甚至几十万维,计算起来非常痛苦。
Embedding 不一样。它把维度压缩到几十到几百维,而且每个维度都承载了语义信息。说白了,就是又小又聪明。
1.2 为什么需要Embedding?
你想想看,如果没有 Embedding,我们怎么让计算机理解“国王”和“王后”的关系?
用 One-hot?两个向量完全正交,点积为 0,计算机觉得它们毫无关系。这显然不对。
用规则词典?你得手动写几千条规则,而且覆盖不了所有场景。我早期做过一个问答系统,就是靠规则硬写,结果用户问“苹果好吃吗”和“iPhone 15 怎么样”,系统完全当成两回事——因为“苹果”这个词在词典里有两个条目,但规则没处理好歧义。
Embedding 解决了三个关键问题:
| 问题 | 传统方法 | Embedding 方案 |
|---|---|---|
| 维度灾难 | One-hot 维度 = 词表大小,几万维 | 通常 50~768 维,计算友好 |
| 语义鸿沟 | 词与词之间孤立,无法表达相似度 | 语义相近的词,向量距离也近 |
| 迁移能力 | 特征需要手工设计,换任务重来 | 预训练好的 Embedding 可直接复用 |
我的经验:在工业级 NLP 管道里,Embedding 层往往是整个模型参数量最大的部分。比如 BERT-base 的 Embedding 层就有 2300 多万参数。所以 Embedding 的质量,直接决定了下游任务的天花板。
1.3 Embedding在NLP中的核心地位
这么说吧,没有 Embedding,就没有现代 NLP。
从 Word2Vec 到 BERT,再到 ,所有主流模型的第一层,几乎都是 Embedding 层。它就像 NLP 系统的“入口”,所有原始文本都得先过这一关,变成向量,才能进入后面的神经网络。
我画了一张图,帮你理清 Embedding 在整个 NLP 管道中的位置:
从图上你能看到,Embedding 层夹在“分词”和“下游模型”之间。它把离散的 序列,变成了连续的向量序列。后面的模型,不管是做分类、生成还是匹配,都基于这些向量来运算。
1.4 三种主流的Embedding类型
在实际项目中,我遇到过三种不同类型的 Embedding,它们的适用场景差别很大:
| 类型 | 代表模型 | 特点 | 典型场景 |
|---|---|---|---|
| 静态 Embedding | Word2Vec, GloVe, FastText | 每个词只有一个固定向量,不随上下文变化 | 文本分类、关键词提取、语义搜索 |
| 上下文 Embedding | BERT, RoBERTa, ALBERT | 同一个词在不同语境下向量不同,动态生成 | 问答系统、命名实体识别、情感分析 |
| 多模态 Embedding | CLIP, ImageBind | 文本和图像映射到同一向量空间 | 图文搜索、跨模态检索 |
避坑指南:我曾经在一个搜索项目里直接用了 Word2Vec 的静态 Embedding,结果用户搜“苹果手机”时,返回了大量水果“苹果”的结果。因为静态 Embedding 无法区分一词多义。后来换成 BERT 的上下文 Embedding,这个问题才解决。所以选型时一定要考虑你的场景是否需要“动态语义”。
1.5 一个简单的Embedding计算示例
光说不练假把式。咱们用 Python 和 PyTorch 快速演示一下 Embedding 是怎么工作的:
import torch
import torch.nn as nn
# 假设词表大小是 10,每个词映射到 4 维向量
vocab_size = 10
embedding_dim = 4
# 创建一个 Embedding 层
embedding_layer = nn.Embedding(vocab_size, embedding_dim)
# 输入:一个 batch 的 ID(假设 batch_size=2, 序列长度=3)
input_ids = torch.tensor([[1, 3, 5], [2, 4, 6]])
# 前向传播:得到 Embedding 向量
embedded = embedding_layer(input_ids)
print("输入形状:", input_ids.shape) # [2, 3]
print("输出形状:", embedded.shape) # [2, 3, 4]
print("Embedding 向量:\n", embedded)
输出结果:
输入形状: torch.Size([2, 3])
输出形状: torch.Size([2, 3, 4])
Embedding 向量:
tensor([[[-0.2345, 0.6789, -0.1234, 0.4567],
[ 0.3456, -0.7890, 0.2345, -0.5678],
[-0.4567, 0.1234, -0.6789, 0.3456]],
[[ 0.5678, -0.2345, 0.7890, -0.1234],
[-0.6789, 0.3456, -0.4567, 0.2345],
[ 0.7890, -0.4567, 0.5678, -0.3456]]], grad_fn=<EmbeddingBackward0>)
你看,输入是 2 句话,每句 3 个 ID。输出变成了 2×3×4 的张量——每个 对应一个 4 维向量。这就是 Embedding 最基础的操作。
我的习惯:在实际搭建管道时,我会把 Embedding 层的权重单独保存一份,方便后续做向量检索。因为很多场景下,你不需要跑整个模型,只需要查 Embedding 向量就够了。比如语义搜索,提前把文档的 Embedding 算好存起来,线上直接做最近邻搜索,速度能快几个数量级。
1.6 小结
这一章咱们把 Embedding 的底子打好了:
- 什么是 Embedding——把离散符号变成稠密向量,用距离表达语义
- 为什么需要它——解决维度灾难、语义鸿沟、迁移能力三大问题
- 它的核心地位——所有 NLP 模型的入口,质量决定天花板
- 三种主流类型——静态、上下文、多模态,各有各的用武之地