| Word2Vec 通常被认为是一种浅层神经网络模型(Shallow Neural Network)。其"浅层"体现在网络结构的简单性上,它移除了传统神经概率语言模型(NNLM)中计算昂贵的非线性隐藏层,直接将投影层与输出层相连。这种简洁的设计使得 Word2Vec 的计算非常高效,从而能够在大规模语料库上进行训练。 |
目标与手段分离
理解Word2Vec的关键在于区分其最终目标与实现手段。神经网络结构本身只是获取词向量的一种方式,并非模型的最终目的。
最终目标
获取一个高质量的 词向量查询表。这本质上是一个巨大的矩阵 W i n W_{in} Win , 矩阵的每一行就是对应单词的稠密向量。
实现手段
为了学习到这个查询表,Word2Vec设计了一个巧妙的"伪任务"------根据上下文预测中心词(或反之),并在这个过程中,将词向量查询表作为模型参数进行训练和优化。
训练结束后,用于执行预测任务的神经网络本身会被丢弃。不会使用它的输出,真正需要和保留的,只有作为其内部参数的那个 词向量查询表。
可学习的词向量矩阵
从数学上看,将一个单词的ID转换为其稠密向量的过程,在概念上可以分解为两步:
- 输入:一个代表单词的ID,例如 3 3 3 。
- 哑编码:将ID 3 3 3 转换为一个维度等于词典大小 ∣ V ∣ |V| ∣V∣ 的高维稀疏向量,例如 [ 0 , 0 , 0 , 1 , 0 , ... ] [0, 0, 0, 1, 0, \ldots] [0,0,0,1,0,...] , 其中只有第 3 个位置为 1。
- 矩阵乘法:用这个One-Hot向量去乘以一个巨大的、可学习的参数矩阵 W i n W_{in} Win(尺寸为 ∣ V ∣ × D |V|\times D ∣V∣×D)。这个矩阵 W i n W_{in} Win 就是最终想要得到的词向量查询表。
由于One-Hot向量只有一个位置是1,这个矩阵乘法的结果,等效于直接从矩阵 W i n W_{in} Win 中 "抽取"出索引为 3 的那一行。
两种经典模型
CBOW 模型详解
CBOW 模型详解
假设 B B B 是批大小, S S S 是上下文单词数量, ∣ V ∣ |V| ∣V∣ 是词典大小, D D D 是词向量维度。
-
输入层:上下文窗口内的所有词对应的ID。
数据形状: ( B , S ) (B, S) (B,S) , 例如输入为 1 , 8 , 10 , 13 , 14 , 16 ] , [ 8 , 5 , 14 , 16 , 18 , 10 1, 8, 10, 13, 14, 16], [8, 5, 14, 16, 18, 10 1,8,10,13,14,16],[8,5,14,16,18,10 。
-
词向量转换:
- 操作:将每个单词ID转换为对应的 D D D 维词向量。这通过输入矩阵 W i n W_{in} Win (大小为 ∣ V ∣ × D |V|\times D ∣V∣×D )实现,相当于公式中的 v c − k = W i n w c − k v_{c-k} = W_{in}w_{c-k} vc−k=Winwc−k 。
- 数据形状变化: ( B , S ) (B, S) (B,S) -> ( B , S , D ) (B, S, D) (B,S,D) 。
- 上下文向量聚合:
- 操作:将一个样本中 S S S 个上下文单词的 D D D 维向量进行聚合(通常是求和或平均),得到上下文向量 h h h 。原论文中使用的是平均,但在部分实现中也会采用求和。
- 数据形状变化: ( B , S , D ) (B, S, D) (B,S,D) -> ( B , D ) (B, D) (B,D) 。
- 输出得分计算:
- 操作:将 D D D 维的上下文向量与输出矩阵 W o u t W_{out} Wout (大小为 D × ∣ V ∣ D\times |V| D×∣V∣ )相乘,得到 ∣ V ∣ |V| ∣V∣ 维的得分向量,对应公式中的 z c = W o u t T , h z_c = W_{out}^T, h zc=WoutT,h (或按实现以右乘形式表示)。
- 数据形状变化: ( B , D ) (B, D) (B,D) -> ( B , ∣ V ∣ ) (B, |V|) (B,∣V∣) 。
- 损失计算:
- 操作:使用 Softmax 将得分转换为概率分布,然后计算与真实中心词之间的交叉熵损失。
- 优化:通过反向传播更新输入矩阵 W i n W_{in} Win 和输出矩阵 W o u t W_{out} Wout 。最终需要的是训练好的输入矩阵 W i n W_{in} Win 。
公式
- 词向量转换:对于上下文中的每个词 w c − k w_{c-k} wc−k ,从输入矩阵 W i n W_{in} Win 中获取对应的词向量: v c − k = W i n w c − k v_{c-k} = W_{in}w_{c-k} vc−k=Winwc−k
- 上下文向量:将上下文窗口中所有词的词向量聚合(求和或平均),得到 h = 1 S ∑ ( v c − m + ⋯ + v c + m ) h = \frac{1}{S} \sum (v_{c-m} + \cdots + v_{c+m}) h=S1∑(vc−m+⋯+vc+m) (此处以平均为例)
- 输出得分:将上下文向量与输出矩阵 W o u t W_{out} Wout 相乘: z c = W o u t T h z_c = W_{out}^T h zc=WoutTh
- 损失函数:模型的优化目标是最小化负对数似然:
Skip-gram 模型详解
Skip-gram任务是 "根据中心词预测上下文"
数据流与维度变化
- 输入层:中心词的 ID 。
数据形状: ( B , 1 ) (B, 1) (B,1) 。 - 词向量转换:
- 操作:将中心词 ID 通过查表(输入矩阵 W i n W_{in} Win )转换为其 D D D 维词向量 v w c v_{w_c} vwc 。
- 数据形状变化: ( B , 1 ) (B, 1) (B,1) -> ( B , 1 , D ) (B, 1, D) (B,1,D) 。
- 输出得分计算:
- 操作:将 D D D 维的中心词向量 v w c v_{w_c} vwc , 与输出矩阵 W o u t W_{out} Wout 相乘,得到一个 ∣ V ∣ |V| ∣V∣ 维的得分向量。
- 数据形状变化: ( B , 1 , D ) (B, 1, D) (B,1,D) -> ( B , ∣ V ∣ ) (B, |V|) (B,∣V∣) 。
- 损失计算(多标签问题):
- 操作:与 CBOW 不同,这里的目标是预测多个上下文单词(例如, S S S 个)。因此,这一个 ∣ V ∣ |V| ∣V∣ 维的得分向量将被 复用 S S S 次,分别与 S S S 个真实的上下文单词计算损失。
- 优化:将 S S S 个位置的损失全部相加,然后进行反向传播,同时更新 W i n W_{in} Win 和 W o u t W_{out} Wout 。因为一个输入对应多个输出标签,这本质上是一个多标签分类问题。在实际运用中,通常将其分解为多个独立的单标签分类任务:对每个上下文词位置,都使用 Softmax 进行一次独立的预测,然后将所有位置的损失相加。
公式
- 词向量转换:对于中心词 w c w_c wc,从输入矩阵 W i n W_{in} Win 中获取对应的词向量: v c = W i n w c v_c = W_{in}w_c vc=Winwc
- 输出得分计算:将中心词向量与输出矩阵 W o u t W_{out} Wout 相乘: z = W o u t T v c z = W_{out}^T v_c z=WoutTvc
- 损失函数:模型的优化目标是最小化负对数似然。
Word2Vec的局限性
尽管Word2Vec是里程碑式的算法,但存在一个根本性的局限性------它产生的是静态词向量。
- 上下文无关
对于词典中的任意一个词,Word2Vec 只会生成一个 固定 的向量表示。这个向量是在整个语料库上训练得到的"平均"语义,与该词出现的具体上下文无关。
这直接导致了 Word2Vec 无法解决一词多义的问题。例如,"小米"这个词,无论是在"农民伯伯正在收割小米"的语境中,还是在"小米公司发布了新手机"的语境中,Word2Vec 赋予它的词向量都是完全相同的。 - 静态的本质
Word2Vec 的输出是一个巨大的查询表。训练完成后,这个表就固定下来了。在使用时,只是根据单词 ID 去查找对应的行向量,整个过程不涉及对上下文的动态分析。
参考资料
https://github.com/datawhalechina/base-nlp/blob/main/docs/chapter2/05_Word2Vec.md