【word2vec】为什么要维护两套词向量矩阵?

代码与定义

python 复制代码
def negSamplingLossAndGradient(
    centerWordVec,
    outsideWordIdx,
    outsideVectors,
    dataset,
    K=10
):
    """负采样损失函数用于word2vec模型

    实现中心词向量和外部词索引对应的负采样损失和梯度
    作为word2vec模型的构建模块。K是负样本的数量。

    注意:同一个词可能被多次负采样。例如如果一个外部词
    被采样了两次,你需要针对该词的梯度进行双倍累加。
    三次采样则累加三次,依此类推。

    """

    negSampleWordIndices = getNegativeSamples(outsideWordIdx, dataset, K)
    indices = [outsideWordIdx] + negSampleWordIndices

    loss = 0.0
    gradCenterVec = np.zeros_like(centerWordVec)
    gradOutsideVecs = np.zeros_like(outsideVectors)
    
    # 正样本词
    u_o = outsideVectors[outsideWordIdx]  # 获取正样本词向量
    z_o = np.dot(u_o, centerWordVec)     # 计算点积
    p_o = sigmoid(z_o)                   # 计算概率
    loss -= np.log(p_o)                  # 累加正样本损失
    gradCenterVec += (p_o - 1.0) * u_o   # 更新中心词梯度
    gradOutsideVecs[outsideWordIdx] += (p_o - 1.0) * centerWordVec  # 更新正样本词梯度
    
    # 负样本词
    u_k = outsideVectors[negSampleWordIndices]  # 获取负样本词向量
    z_k = np.dot(u_k, centerWordVec)           # 计算点积
    p_k = sigmoid(-z_k)                        # 计算负样本概率
    loss -= np.sum(np.log(p_k))                # 累加负样本损失
    gradCenterVec += np.dot(1.0 - p_k, u_k)    # 更新中心词梯度
    
    # 对每个负样本单独更新词向量梯度
    for i, k in enumerate(negSampleWordIndices):
        gradOutsideVecs[k] += (1.0 - p_k[i]) * centerWordVec

    return loss, gradCenterVec, gradOutsideVecs
代码变量名 数学符号 详细含义
centerWordVec v_c 中心词向量。当前窗口正中间那个词的词向量,它是我们要更新的"输入"。
outsideWordIdx o 真实上下文词的索引。即在语料库中,实际出现在中心词身边的那个词的编号。
outsideVectors U 外部词向量矩阵。形状为 (V, N),每一行 u_w 代表词汇表中第 w 个词作为"上下文"时的特征。
dataset - 用于负采样的工具。它包含了词频信息,确保高频词更有可能被选为负样本。

分析

用两个矩阵(中心词向量 centerWordVec 和外部词向量矩阵 outsideVectors)是为了分别表示词作为中心词词作为上下文词时的不同向量表征

如果不分开两个矩阵,而让每个词只有一个向量,那么当这个词作为中心词时和作为上下文词时,梯度更新会相互干扰(比如更新中心词时也会影响它作为上下文词时的表示)。实验证明分开训练效果更好。

复制代码
gradCenterVec = np.zeros_like(centerWordVec)          # 与中心词向量同形状(一维)
gradOutsideVecs = np.zeros_like(outsideVectors)       # 与上下文矩阵同形状(词汇表大小 × 维度)
  • gradCenterVec:只对应当前这一个中心词的梯度。因为损失函数中只有当前中心词向量出现,其他中心词向量不参与本次更新。

  • gradOutsideVecs :对应所有可能被更新到的上下文词向量。正样本词 outsideWordIdx 和每个负样本词 negSampleWordIndices 都需要更新其对应的行。这些词可能重复(同一个词被多次负采样),所以梯度要累加。

代码中为什么只传一个 centerWordVec 而不是整个中心词矩阵?

因为负采样损失函数是 每次处理一个中心词 (以及它的一个正样本和 K 个负样本)。在训练循环中,会遍历所有中心词,每次取出当前中心词的向量 centerWordVec(从中心词矩阵中取一行),并传入整个上下文矩阵 outsideVectors,因为需要根据索引从中取出正负样本的向量。

损失函数与梯度

相关推荐
沪漂阿龙14 小时前
面试题:逻辑回归是什么?为什么用 Sigmoid、对数损失、最大似然、Softmax、多分类、类别不平衡一文讲透
人工智能·算法·机器学习·分类·逻辑回归
147API14 小时前
GPT 试用流程复盘:日志、成本和失败样本怎么设计
人工智能·gpt·机器学习
Liangwei Lin15 小时前
LeetCode 74. 搜索二维矩阵
算法·leetcode·矩阵
萑澈1 天前
编程能力强和多模态模型的模型后训练
人工智能·深度学习·机器学习
哥布林学者1 天前
深度学习进阶(二十)Transformer-XL
机器学习·ai
多年小白1 天前
【周末消息面汇总】2026年5月10日(周日)
人工智能·科技·机器学习·ai·金融
MediaTea1 天前
Scikit-learn:从数据到结构——无监督学习的最小闭环
人工智能·学习·算法·机器学习·scikit-learn
o_insist1 天前
多层感知机判断氨基酸亲疏水性(PyTorch版)
人工智能·深度学习·机器学习