【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,因为需要根据索引从中取出正负样本的向量。

损失函数与梯度

相关推荐
哥布林学者3 小时前
深度学习进阶(十) RoI Align
机器学习·ai
爱凤的小光4 小时前
OpenCV4机器学习算法原理与代码---个人学习篇
opencv·机器学习
刘 大 望4 小时前
RAG相关技术介绍及Spring AI中使用--第三期
java·人工智能·后端·spring·机器学习·ai·aigc
Mr数据杨4 小时前
成人收入预测建模与信用评估应用
大数据·人工智能·机器学习·数据分析·kaggle
大江东去浪淘尽千古风流人物4 小时前
【cuVSLAM】项目解析:一套偏工程实战的 GPU 紧耦合视觉惯性 SLAM
数据库·人工智能·python·机器学习·oracle
代码改善世界5 小时前
【MATLAB初阶】矩阵操作(二):矩阵的运算
android·matlab·矩阵
今日说"法"5 小时前
线性代数与矩阵运算:AI世界的数学基石——从SVD到特征值分解的实战解析
人工智能·线性代数·矩阵
Mr数据杨5 小时前
结构化表格分类建模与业务预测落地路径
人工智能·机器学习·分类·数据挖掘·数据分析·kaggle
猴哥聊项目管理5 小时前
从职能型组织到矩阵型组织的IPD转型路径
线性代数·矩阵·项目管理·项目经理·ipd流程·ipd项目管理流程·ipd流程管理
生信研究猿5 小时前
#P4475.第2题-终端款型聚类识别
机器学习·数据挖掘·聚类