查看全课大纲(第 20 / 69 节)
- 1.NLP 的研究领域、应用与学习路径
- 2.自然语言的基本术语
- 3.信息论基础:信息熵与交叉熵
- 4.语言的进化与语义变迁
- 5.主观概率、客观概率与条件概率
- 6.贝叶斯原理与推理
- 7.随机变量:二项式、期望方差与联合概率
- 8.常见概率分布
- 9.辛普森悖论与贝叶斯解题实例
- 10.语言模型:语言概率与词袋模型
- 11.n-gram 语言模型(二元 / 三元 / N-Gram)
- 12.语言模型评价:交叉熵、困惑度与插值
- 13.朴素贝叶斯文本分类:垃圾邮件
- 14.拼写检查
- 15.中文分词:构词法、最大匹配、最优路径与 Jieba
- 16.词表示问题与语义相似度
- 17.TF-IDF 权重处理
- 18.One-Hot 表达与词表示的局限
- 19.Word2Vec 核心思想
- 20.Word2Vec 训练过程
- 21.Skip-gram 模型详解
- 22.词性标注任务与标注方法(规则 + N-Gram)
- 23.EM 算法与混合模型
- 24.高斯混合模型 GMM
- 25.从混合模型到隐马尔可夫模型
- 26.隐马尔可夫模型(HMM)推导与维特比解码
- 27.线性链条件随机场 CRF
- 28.贝叶斯网络与图模型
- 29.隐马尔可夫链与 HMM 推导
- 30.PLSA 主题模型
- 31.LSI 与 SVD 向量表达
- 32.LDA 与狄利克雷分布
- 33.主题模型实验复现(困惑度 / 分类 / 相似度 / 延展)
- 34.上下文无关文法(CFG)与句法分析
- 35.概率上下文无关文法 PCFG
- 36.统计机器翻译:词对齐与翻译模型
- 37.统计机器翻译中的对齐模型与参数估计
- 38.从统计机器翻译到神经机器翻译
- 39.神经元与反向传播速览(指向深度学习课)
- 40.CNN 原理及其在 NLP 中的应用
- 41.循环神经网络的基本原理与 Elman / Jordan 网络
- 42.LSTM:长短期记忆网络的核心思想与分步实现
- 43.Encoder-Decoder 框架
- 44.Seq2Seq 与早期注意力机制
- 45.注意力机制的背景与动机
- 46.注意力模型实现原理与匹配函数
- 47.记忆网络:组成与计算
- 48.注意力机制的应用与历史延展
- 49.Transformer 结构:Encoder-Decoder 栈与 Self-Attention
- 50.Multi-Head Attention、FFNN 与位置编码
- 51.层归一化、损失函数与 Universal Transformer 延展
- 52.预训练范式:从 ELMo 到 BERT
- 53.BERT 与掩码语言模型
- 54.BERT 下游任务微调与 GLUE 口径
- 55.GPT 与自回归语言建模
- 56.GPT-1 到 GPT-4 的演进
- 57.指令微调与 RLHF
- 58.分词器:BPE、WordPiece 与中文词表
- 59.上下文窗口与长文本处理
- 60.能力边界、成本与适用场景
- 61.文本分类实战:从朴素贝叶斯到逻辑回归
- 62.命名实体识别实战
- 63.文本生成与摘要实战
- 64.语义检索与向量库实战
- 65.RAG 知识库问答
- 66.NLP 评估指标:BLEU / ROUGE / BERTScore 与人工评估
- 67.幻觉与事实性问题
- 68.文本与知识结合(知识图谱压缩)
- 69.跨媒体信息检索与未来展望
Word2Vec 训练过程
小象实战讲义 · 自然语言处理
在上一节我们了解了 Word2Vec 的核心思想与两种模型架构(CBOW 和 Skip-gram)。本节我们将深入 CBOW 模型的训练过程,从数学公式推导到损失函数构建,完整揭示 Word2Vec 如何通过神经网络学习到高质量的分布式词向量。掌握这一过程,你将能真正理解词向量生成的原理,并为后续学习更复杂的神经网络模型打下坚实基础。
💡 核心导读
- CBOW 模型的目标:根据上下文词预测中心词,通过调整网络参数使预测概率最大化。
- 训练流程六步走:从 One-Hot 向量到词向量映射,再到上下文向量聚合、得分计算、概率转换,最终构建交叉熵损失函数。
- 核心参数:嵌入矩阵 (输入层到隐藏层的权重)和输出权重矩阵 (隐藏层到输出层的权重),两者共同决定了词向量的质量。
- 损失函数的意义:使用交叉熵来衡量模型预测的概率分布与真实 One-Hot 分布之间的差距,通过最小化损失来优化参数。
从 One-Hot 到词向量:嵌入矩阵
在 CBOW 模型中,输入是中心词 的上下文窗口内的 个词。首先,每个上下文词 都表示为一个 维的 One-Hot 向量,其中 是词汇表大小。
我们有一个可学习的嵌入矩阵 ,其中 是词向量的维度(通常远小于 )。将 One-Hot 向量 与嵌入矩阵 相乘,即可得到该词的 维稠密词向量 : 由于 是 One-Hot 向量,这个乘法操作本质上就是选取 矩阵中对应于该词索引的那一行。因此,嵌入矩阵 的每一行就是一个词的词向量。
# 示例:从 One-Hot 到词向量
import numpy as np
# 假设词汇表 V = 5,词向量维度 K = 3
V = 5
K = 3
np.random.seed(42) # 固定随机种子,确保输出可复现
# 嵌入矩阵 E,形状 (V, K)
E = np.random.randn(V, K).round(4)
print("Embedding matrix E (shape V x K):")
print(E)
print()
# 假设词汇表为 {0:'我', 1:'爱', 2:'北京', 3:'天安门', 4:'的'}
# 词"北京"的索引是2,其 One-Hot 向量为 [0, 0, 1, 0, 0]
x_beijing = np.array([0, 0, 1, 0, 0])
# 计算词向量 v_beijing = E^T * x_beijing
v_beijing = np.dot(x_beijing, E) # 等价于 E[2, :]
print(f"One-Hot vector for '北京': {x_beijing}")
print(f"Word vector for '北京' (v_beijing): {v_beijing.round(4)}")
print(f"Directly from row 2 of E: {E[2, :].round(4)}")Embedding matrix E (shape V x K):
[[ 0.4967 -0.1383 0.6477]
[ 1.523 -0.2342 -0.2341]
[ 1.5792 0.7674 -0.4695]
[ 0.5426 -0.4634 -0.4657]
[ 0.242 -1.9133 -1.7249]]
One-Hot vector for '北京': [0 0 1 0 0]
Word vector for '北京' (v_beijing): [ 1.5792 0.7674 -0.4695]
Directly from row 2 of E: [ 1.5792 0.7674 -0.4695]上下文向量的聚合:求平均得到
对于给定的上下文窗口,我们得到了 个上下文词向量 (不含中心词 )。CBOW 模型将这些上下文向量进行平均,得到一个聚合后的上下文表示 : 这个 是一个 维向量,它代表了整个上下文窗口的“中心”语义信息。模型的目标不是让 与输入矩阵 中中心词的行向量做最近邻,而是让 经输出矩阵 打分后,真实中心词在 对应列上的得分最高。
# —— 重新构建上文用到的微型数据(本节各代码块相互独立,可单独运行)
import numpy as np
np.random.seed(42) # 固定随机种子,确保输出可复现
V = 5
K = 3
E = np.random.randn(V, K).round(4)
# 示例:上下文向量聚合
# 假设上下文窗口 m=1,即用前一个和后一个词预测中心词。
# 句子:"我 爱 北京 天安门",中心词是"北京",上下文是"爱"和"天安门"。
# 假设词汇表索引:我:0, 爱:1, 北京:2, 天安门:3
# 上下文词"爱"和"天安门"的词向量就是 E 的第1行和第3行
v_ai = E[1, :] # "爱"的词向量
v_tiananmen = E[3, :] # "天安门"的词向量
print(f"Vector for '爱': {v_ai.round(4)}")
print(f"Vector for '天安门': {v_tiananmen.round(4)}")
# 求平均得到聚合向量 hat_v
hat_v = (v_ai + v_tiananmen) / 2
print(f"Aggregated context vector hat_v: {hat_v.round(4)}")Vector for '爱': [ 1.523 -0.2342 -0.2341]
Vector for '天安门': [ 0.5426 -0.4634 -0.4657]
Aggregated context vector hat_v: [ 1.0328 -0.3488 -0.3499]从隐藏层到输出层:得分计算与 Softmax
接下来,我们需要根据聚合向量 来预测中心词。这通过另一个可学习的权重矩阵 来实现。将 与 相乘,得到一个 维的得分向量 : 中的每一个元素 代表了聚合上下文 与词汇表中第 个词(通过 矩阵的第 列表示)的关联程度。点积值越大,表示相关性越强。
然而, 的值范围不确定(可能为任意实数),我们需要将其转换为一个概率分布,即词汇表中每个词作为中心词出现的概率。这里使用 Softmax 函数: 这样, 就是一个 维的概率向量,所有元素和为1。
# —— 重新构建上文用到的微型数据(本节各代码块相互独立,可单独运行)
import numpy as np
np.random.seed(42) # 固定随机种子,确保输出可复现
V = 5
K = 3
E = np.random.randn(V, K).round(4)
v_ai = E[1, :] # "爱"的词向量
v_tiananmen = E[3, :] # "天安门"的词向量
hat_v = (v_ai + v_tiananmen) / 2
# 示例:得分计算与 Softmax
# 输出权重矩阵 U,形状 (K, V)
U = np.random.randn(K, V).round(4)
print("Output weight matrix U (shape K x V):")
print(U)
print()
# 计算得分向量 z
z = np.dot(hat_v, U) # 等价于 hat_v^T * U
print(f"Score vector z (shape V): {z.round(4)}")
# 应用 Softmax 得到预测概率 y_hat
def softmax(x):
exp_x = np.exp(x - np.max(x)) # 减去最大值防止数值溢出
return exp_x / exp_x.sum()
y_hat = softmax(z)
print(f"Predicted probability distribution y_hat: {y_hat.round(4)}")
print(f"Sum of y_hat: {y_hat.sum():.4f}")Output weight matrix U (shape K x V):
[[-0.5623 -1.0128 0.3142 -0.908 -1.4123]
[ 1.4656 -0.2258 0.0675 -1.4247 -0.5444]
[ 0.1109 -1.151 0.3757 -0.6006 -0.2917]]
Score vector z (shape V): [-1.1307 -0.5645 0.1695 -0.2307 -1.1667]
Predicted probability distribution y_hat: [0.1015 0.1787 0.3724 0.2496 0.0979]
Sum of y_hat: 1.0000构建损失函数:交叉熵
现在,我们有了模型的预测概率分布 。真实的标签是什么?对于给定的上下文,真实的中心词是 ,我们可以用一个 维的 One-Hot 向量 来表示它,其中只有在 索引位置为1,其余为0。
我们的目标是让预测分布 尽可能接近真实分布 。衡量两个概率分布之间差异的常用方法是交叉熵(Cross-Entropy)。对于单个训练样本,损失函数 定义为: 由于 是 One-Hot 向量,只有索引 处 ,其他 ,因此上式简化为: 最小化这个损失函数,就等价于最大化真实中心词 的预测对数概率。
# —— 重新构建上文用到的微型数据(本节各代码块相互独立,可单独运行)
import numpy as np
np.random.seed(42) # 固定随机种子,确保输出可复现
V = 5
K = 3
E = np.random.randn(V, K).round(4)
v_ai = E[1, :] # "爱"的词向量
v_tiananmen = E[3, :] # "天安门"的词向量
hat_v = (v_ai + v_tiananmen) / 2
U = np.random.randn(K, V).round(4)
z = np.dot(hat_v, U) # 等价于 hat_v^T * U
def softmax(x):
exp_x = np.exp(x - np.max(x)) # 减去最大值防止数值溢出
return exp_x / exp_x.sum()
y_hat = softmax(z)
# 示例:计算交叉熵损失
# 假设真实的中心词是"北京",索引为2
true_index = 2
y_true = np.zeros(V)
y_true[true_index] = 1
# 计算交叉熵损失
loss = -np.log(y_hat[true_index])
print(f"True label vector y: {y_true.astype(int)}")
print(f"Predicted probability for '北京' (index {true_index}): {y_hat[true_index]:.6f}")
print(f"Cross-entropy loss L: {loss:.6f}")True label vector y: [0 0 1 0 0]
Predicted probability for '北京' (index 2): 0.372375
Cross-entropy loss L: 0.987855参数更新与训练
我们的模型有两个主要的参数集合需要学习:
- 嵌入矩阵 :它直接定义了每个词的词向量。
- 输出权重矩阵 :它定义了从隐藏层(上下文表示)到每个输出词的概率映射关系。
训练过程就是使用大量的(上下文,中心词)样本对,通过反向传播算法和梯度下降优化方法(如 SGD、Adam),不断计算损失 对 和 的梯度,并更新这两个矩阵,使得总损失不断减小。
训练伪代码流程(示意):
1. 初始化嵌入矩阵 E 和输出矩阵 U。
2. For epoch in range(num_epochs):
3. For each (context_words, center_word) in training_data:
4. # 前向传播
5. context_vectors = lookup(E, context_words) # 查找词向量
6. hat_v = average(context_vectors) # 求平均
7. z = dot(hat_v, U) # 计算得分
8. y_hat = softmax(z) # 得到概率
9. loss = -log(y_hat[center_word_index]) # 计算损失
10.
11. # 反向传播
12. grad_U, grad_E_context = compute_gradients(loss, U, E, context_words)
13.
14. # 参数更新
15. U = U - learning_rate * grad_U
16. # 注意:只更新上下文词对应的 E 中的行
17. for word in context_words:
18. E[word_index] = E[word_index] - learning_rate * grad_E_context[word]训练完成后,嵌入矩阵 就是我们最终得到的词向量查找表。若只是提取已训练好的词向量用于下游任务,通常只使用 ;但如果要运行中心词预测(对候选词打分、计算 Softmax 概率),输出矩阵 仍是必需参数。在一些改进方法(如负采样)中, 的列向量也被视为词的另一种“输出向量”,有时会与 中的向量结合使用。
📝 动手练一练
- 概念辨析:在 CBOW 模型的损失函数 中,如果模型预测完全正确,即 ,那么损失 是多少?这说明了交叉熵损失的什么性质?
👉 点击查看参考答案
如果模型预测完全正确,即预测中心词的概率为 1,则 。这说明交叉熵损失的下界是 0,当预测分布与真实分布完全一致时,损失达到最小值 0。损失值越小,表示模型预测得越好。
- 手算练习:假设一个极简词汇表 ,词向量维度 。上下文聚合向量 ,输出矩阵 。请计算得分向量 ,并手动计算 Softmax 后的概率分布 (保留4位小数)。如果真实中心词索引为 1(从0开始),此时的交叉熵损失是多少?
👉 点击查看参考答案
首先计算得分向量 :
接着计算 Softmax。先计算指数:。总和为 。
则 。
真实中心词索引为 1,其预测概率为 ,交叉熵损失 。
本章小结
本节我们深入剖析了 Word2Vec 中 CBOW 模型的完整训练过程。我们从上下文词的 One-Hot 表示出发,通过嵌入矩阵 得到词向量,聚合后得到上下文表示 。然后利用输出矩阵 计算与每个词的得分,并通过 Softmax 转换为概率分布。最终,我们使用交叉熵损失函数来衡量预测与真实中心词的差距,并通过优化 和 来最小化这个损失,从而学习到能够捕捉词语语义关系的词向量。
值得注意的是,在整个词表上做完整 Softmax 是高开销的基线方案,计算成本与词汇表大小 成正比;它并非原始 Word2Vec 论文的实现方式。为在大规模语料上训练,Word2Vec 采用了高效近似:负采样(Negative Sampling)由 Mikolov 等人提出;层次 Softmax(Hierarchical Softmax)则早由 Morin 和 Bengio(2005)引入,后被 Word2Vec 采用。这些优化技术我们将在后续章节中介绍。
📋 行动清单
- 理解 CBOW 模型前向传播的六个步骤:One-Hot -> 词向量 -> 平均 -> 得分 -> Softmax -> 损失。
- 掌握交叉熵损失函数在 One-Hot 标签下的简化形式 及其含义。
- 尝试在小规模数据上(如自己构造的几句话)手动推导一遍 CBOW 的计算过程,加深理解。
—— 小象教研组