Embedding与词表示技术:从OneHot到FastText的演进
Embedding与词表示技术:从OneHot到FastText的演进
本文较长,建议点赞收藏,以免遗失。更多AI大模型开发 学习视频/籽料/面试题 都在这>>Github<< >>Gitee<<
一、Embedding:让机器“读懂”数据的核心技术
Embedding,即“嵌入”,本质是一种单射且同构的映射关系——它能将文字、图像、语言等非结构化数据,转化为计算机可识别的低维数值向量,且在转化过程中最大程度保留原始数据的信息。这种映射的物理意义可通过“地图”类比理解:现实地理是高维复杂的,但地图通过颜色、等高线等设计,将其压缩为二维平面,却仍能准确传递地形、位置等关键信息;Embedding则是为数据构建“数字地图”,让机器能通过向量理解数据的语义、特征关联。
从技术定义来看,Embedding是将高维数据(如百万级词表的文本)转换为低维稠密向量的技术。其实现依赖一个可学习的参数矩阵(本质是全连接层):以离散的OneHot向量为输入,输出固定维度的稠密向量(即“词向量”)。为提升计算效率,实际工程中常用“lookup查找表”替代矩阵乘积——例如PyTorch中通过nn.Embedding(vocab_size, embed_dim)
实现,其中vocab_size
为词表总大小,embed_dim
为词向量的维度(需根据任务自定义)。
二、基础词表示:OneHot编码的功与过
在Embedding技术普及前,OneHot编码是处理离散文本特征的主流方式。它的核心逻辑是:为词表中的每个词分配一个唯一索引,再生成一个长度等于词表的向量,向量中仅对应索引的位置为1,其余均为0。
1. OneHot的核心特性与应用价值
以词表["apple", "banana", "cherry"]
为例:
- “apple”的OneHot编码为
[1, 0, 0]
- “banana”的OneHot编码为
[0, 1, 0]
- “cherry”的OneHot编码为
[0, 0, 1]
这种编码方式的价值在于:
- 解决离散特征偏序问题:非偏序的离散变量(如“苹果”“香蕉”无大小关系)经OneHot编码后,各向量到原点距离相等,避免算法误判变量间的优先级。
- 适配机器学习算法:将离散特征映射到欧式空间后,可直接用于回归、分类、聚类等算法——这些算法的距离(如余弦相似度)、相似度计算均依赖欧式空间的向量运算。
- 特征扩充与归一化:编码后的每一列可视为独立连续特征,能与其他连续特征(如词频)结合,且支持归一化(如缩放到[-1,1]或标准化为均值0、方差1)。
其Python实现逻辑如下:
# 1. 定义词汇表与词-索引映射
vocab = ["apple", "banana", "cherry"]
word_to_index = {word: idx for idx, word in enumerate(vocab)}# 2. OneHot编码函数
def one_hot_encoding(word, vocab, word_to_index):# 初始化全0向量,长度等于词表encoding = [0] * len(vocab)# 获取词的索引(未找到则返回-1)idx = word_to_index.get(word, -1)if idx != -1:encoding[idx] = 1 # 对应索引置1return encoding# 3. 测试编码结果
print("OneHot编码结果:")
for word in vocab:print(f"'{word}': {one_hot_encoding(word, vocab, word_to_index)}")
2. OneHot的局限性:高维与语义缺失
OneHot的缺陷随词表规模扩大而凸显:
- 高维稀疏问题:若词表达百万级,每个OneHot向量的长度即达百万,其中仅1个非零值——存储和计算时会消耗大量资源,甚至导致“维度灾难”。虽可通过PCA降维缓解,但会损失部分信息。
- 语义关联缺失:所有OneHot向量彼此正交(点积为0),无法体现词与词的相似性。例如“苹果”和“香蕉”均为水果,但OneHot编码无法反映这种语义关联,这对需要理解语境的NLP任务(如文本分类、机器翻译)极为不利。
三、分布式表示革命:Word2Vec技术详解
为解决OneHot的痛点,2013年Mikolov团队在论文《Efficient Estimation of Word Representations in Vector Space》(https://arxiv.org/pdf/1301.3781)中提出Word2Vec——其核心是分布式表示:将每个词映射到低维稠密向量(如50~300维),向量的距离可反映词的语义相似度(如“苹果”与“香蕉”的向量距离小于“苹果”与“汽车”)。
Word2Vec的本质是单隐藏层神经网络:输入为OneHot向量,隐藏层无激活函数,输出层通过softmax(或其优化版本)预测目标词,最终取隐藏层输出作为词向量。根据任务目标不同,分为CBOW和Skip-gram两种模型。
1. CBOW:根据语境预测当前词
CBOW(Continuous Bag-of-Words)的核心逻辑是“用上下文词预测中心词”。例如给定句子“the quick brown fox jumps”,若以“fox”为中心词,上下文为“quick”“brown”“jumps”,CBOW会通过这些上下文词的向量,预测中心词“fox”。
CBOW的模型结构与实现
- 输入层:多个上下文词的OneHot向量(维度为
voc_size
)。 - 隐藏层:将上下文词的OneHot向量通过线性层(无偏置)转换为词向量,再对所有词向量取均值,得到隐藏层向量(维度为
embed_dim
)。 - 输出层:通过线性层将隐藏层向量映射回
voc_size
维度,预测中心词的概率分布。
PyTorch实现代码如下:
import torch
import torch.nn as nnclass CBOW(nn.Module):def __init__(self, voc_size, embedding_size):super(CBOW, self).__init__()# 输入→隐藏层:OneHot→词向量(无偏置)self.input_to_hidden = nn.Linear(voc_size, embedding_size, bias=False)# 隐藏层→输出层:词向量→预测中心词self.hidden_to_output = nn.Linear(embedding_size, voc_size, bias=False)def forward(self, X):# X: [num_context_words, voc_size],上下文词的OneHot向量embeddings = self.input_to_hidden(X) # 上下文词向量:[num_context_words, embedding_size]hidden_layer = torch.mean(embeddings, dim=0) # 上下文词向量均值:[embedding_size]output_layer = self.hidden_to_output(hidden_layer.unsqueeze(0)) # 预测输出:[1, voc_size]return output_layer# 实例化模型(词表大小设为1000,嵌入维度设为2便于展示)
voc_size = 1000
embedding_size = 2
cbow_model = CBOW(voc_size, embedding_size)
print("CBOW模型结构:", cbow_model)
2. Skip-gram:根据当前词预测语境
与CBOW相反,Skip-gram的逻辑是“用中心词预测上下文词”。仍以“the quick brown fox jumps”为例,若中心词为“fox”,Skip-gram会通过“fox”的向量,预测其上下文“quick”“brown”“jumps”。
Skip-gram的模型结构与实现
- 输入层:中心词的OneHot向量(维度为
voc_size
)。 - 隐藏层:通过参数矩阵将OneHot向量转换为词向量(维度为
embed_dim
)。 - 输出层:通过另一参数矩阵将词向量映射回
voc_size
维度,预测上下文词的概率分布。
PyTorch实现代码如下:
import torch
import torch.nn as nn
import torch.optim as optimclass Skip_gram(nn.Module):def __init__(self, voc_size, embedding_size, dtype=torch.float32):super(Skip_gram, self).__init__()# 输入→隐藏层参数:voc_size×embedding_sizeself.W = nn.Parameter(torch.randn(voc_size, embedding_size).type(dtype))# 隐藏层→输出层参数:embedding_size×voc_sizeself.V = nn.Parameter(torch.randn(embedding_size, voc_size).type(dtype))def forward(self, X):# X: [batch_size, voc_size],中心词的OneHot向量hidden_layer = torch.matmul(X, self.W) # 词向量:[batch_size, embedding_size]output_layer = torch.matmul(hidden_layer, self.V) # 预测上下文:[batch_size, voc_size]return output_layer# 实例化模型与训练组件
voc_size = 1000
embedding_size = 2
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = Skip_gram(voc_size, embedding_size).to(device)
criterion = nn.CrossEntropyLoss().to(device) # 多分类交叉熵损失
optimizer = optim.Adam(model.parameters(), lr=1e-3) # Adam优化器
print("Skip-gram模型结构:", model)
3. Word2Vec的加速:解决softmax计算瓶颈
传统Word2Vec的输出层需计算所有词的softmax概率(复杂度为O(V)
,V
为词表大小),当V
达百万级时,训练效率极低。为此,Word2Vec提出两种加速方案:
(1)Hierarchical Softmax(霍夫曼树)
核心思路:用霍夫曼树替代全连接的输出层,将“多分类问题”转化为“一系列二分类问题”。
- 霍夫曼树构建:根据词频排序,高频词靠近树根,低频词靠近树叶,树叶总数等于词表大小
V
。 - 计算逻辑:从树根到目标词的树叶,每经过一个内部节点,通过sigmoid函数判断“左/右子树”(对应0/1),最终通过
log2V
次二分类完成预测。 - 优势:计算复杂度从
O(V)
降至O(log2V)
,高频词检索更快,符合贪心优化逻辑。 - 缺陷:低频词需经过更多节点,检索效率仍较低。
(2)Negative Sampling(负采样)
核心思路:每次训练仅更新“正样本”和少量“负样本”的权重,而非所有词的权重。
- 样本定义:给定中心词
w
和上下文Context(w)
,(Context(w), w)
为正样本;随机选择少量与Context(w)
无关的词作为负样本(记为NEG(w)
)。 - 计算逻辑:用sigmoid函数优化正样本的预测概率(趋近1),同时优化负样本的预测概率(趋近0),每次仅更新正样本+负样本的权重(通常共5~20个样本)。
- 优势:计算量大幅降低——例如
V=10000
、嵌入维度=300时,每次仅更新300×(1+5)=1800
个权重(原需更新300×10000=3e6
个)。 - 采样技巧:按“词频的0.75次幂”采样,平衡高频词与低频词的采样概率,避免高频无意义词(如“的”)过度出现。
四、文本分类利器:FastText技术
2016年,Facebook团队在论文《Bag of Tricks for Efficient Text Classification》(https://arxiv.org/pdf/1607.01759)中提出FastText——它基于Word2Vec的CBOW模型改进,专门用于快速文本分类,在处理短文本(如评论、新闻标签)时表现优异。
1. FastText与CBOW的异同
FastText的核心结构与CBOW一致(输入层→隐藏层→输出层),但在任务目标和输入特征上有显著差异:
对比维度 | CBOW | FastText |
---|---|---|
任务目标 | 预测中心词(词表示学习) | 预测文档类标(文本分类) |
输入特征 | 上下文词的OneHot向量 | 单词+n-gram特征的Embedding向量 |
隐藏层计算 | 上下文词向量均值 | 单词+n-gram向量均值 |
输出层 | 词表概率分布 | 类别概率分布 |
2. FastText的核心优化
(1)N-gram特征:捕捉局部语义
FastText引入“N-gram特征”(如2-gram“quick brown”、3-gram“the quick brown”),弥补了“词袋模型”忽略词序的缺陷。例如“not good”和“good not”的词袋特征相同,但N-gram特征不同,FastText可通过此区分负面与正面语义。
- 优化策略:过滤低频N-gram、用哈希表存储特征,减少内存占用。
(2)Hierarchical Softmax:适配多分类场景
与Word2Vec类似,FastText用霍夫曼树处理多分类问题——当类别数达数千时,将计算复杂度从O(C)
(C
为类别数)降至O(log2C)
,大幅提升训练速度。
(3)高效训练:兼顾速度与精度
FastText的输入特征直接使用Embedding向量(而非OneHot),减少了输入层的维度;同时支持批量训练和多线程优化,在百万级文本数据集上,训练时间可缩短至分钟级,且精度接近传统深度学习模型(如CNN、RNN)。
五、总结:词表示技术的演进逻辑
从OneHot到Word2Vec,再到FastText,词表示技术的发展始终围绕“更高效、更精准地传递语义信息”展开:
- OneHot解决了“离散特征机器可识别”的基础问题,但受限于高维和语义缺失;
- Word2Vec通过分布式表示,首次让词向量具备语义关联,再通过霍夫曼树、负采样突破计算瓶颈;
- FastText则在Word2Vec基础上,针对文本分类场景优化,引入N-gram特征,实现“速度与精度的平衡”。
这些技术不仅是Embedding的核心组成,更是后续大模型(如BERT、GPT)词表示能力的基础——理解它们的原理,能帮助我们更深入地掌握大模型处理文本的底层逻辑。