为什么我们需要 2 个用于 word2vec 或 GloVe 的矩阵

数据挖掘 word2vec 词嵌入 矩阵分解
2021-09-16 04:11:02

Word2vec 和 GloVe 是两个最知名的词嵌入方法。许多工作指出这两个模型实际上彼此非常接近,并且在某些假设下,它们对语料库中单词共现的 pPMI 进行矩阵分解。

尽管如此,我还是不明白为什么我们实际上需要两个矩阵(而不是一个)来用于这些模型。我们不能对 U 和 V 使用同一个吗?是梯度下降的问题还是有其他原因?

有人告诉我这可能是因为一个词的嵌入 u 和 v 应该足够远来表示一个词很少出现在它自己的上下文中的事实。但我不清楚。

3个回答

可能不是您正在寻找的答案,但我仍然会尝试:

首先,快速回顾一下 word2Vec,假设我们使用的是 skip gram。

一个典型的 Word2Vec 可训练模型包括 1 个输入层(例如,10 000 长的 one-hot 向量)、一个隐藏层(例如 300 个神经元)、一个输出(10 000 长的 one-hot 向量)

  • 输入:10 000
  • 隐藏:300
  • 输出:10 000

Input-Hidden 之间有一个矩阵E,描述了使你的 one-hot 成为嵌入的权重。该矩阵很特殊,因为每一列(或行,取决于您的首选符号)代表这 300 个神经元中的预激活 - 对相应传入 1-hot 向量的响应。

您无需对这 300 个神经元执行任何激活,并且可以立即将它们的值用作任何未来任务的嵌入。


然而,简单地将 one-hot 压缩到 300 维表示中是不够的——它必须有意义。我们使用额外的第二个矩阵来确保这个含义是正确的 - 它将隐藏连接到输出

我们不想激活隐藏层,因为在运行时不需要激活函数,但是,在这种情况下,我们将需要第二个矩阵,从隐藏到输出。

第二个矩阵将与您的嵌入完全不同这样的 one-hot 将代表一个最有可能在您的原始 one-hot 附近(根据上下文)的词。换句话说,这个输出不会是你原来的 one-hot。

这就是为什么需要第二个矩阵的原因。在输出端,我们执行 softmax,就像在分类问题中一样。

这允许我们表达一个关系 "word"-->embedding-->"context-neighbor-word"

现在,可以进行反向传播,以纠正Input-Hidden权重(您的第一个矩阵 E)——这些是我们真正关心的权重。那是因为 Matrix E 可以在运行时使用(我认为),可能作为第一个全连接层插入到一些循环神经网络中。

在那种情况下,你不会使用这个:

您无需对这 300 个神经元执行任何激活,并且可以立即将它们的值用作任何未来任务的嵌入

但是,您只需在运行时从该矩阵中获取适当的列(或行,取决于您的首选符号)。这样做的好处是,通过这种方式,您可以获得一个非常便宜的预训练全连接层,旨在与 one-hots 一起使用。通常,由于梯度消失的问题,第一层的训练时间最长。


为什么在训练期间需要第二个矩阵:

再次回想一下,隐藏层没有激活。

我们可以指示网络必须创建什么“one-hot”以响应您原来的“input one-hot”,并且如果网络未能生成正确答案,我们可以惩罚它。

我们不能将 softmax 直接放在隐藏层之后,因为我们有兴趣调用一种机制来转换为嵌入。这已经是第一个矩阵 E 的责任了。因此,我们需要一个额外的步骤(一个额外的矩阵),这将为我们提供足够的空间,以便现在在输出层就不同但相似的(上下文相关的)邻词得出结论

在运行时,您丢弃第二个矩阵。但如果您需要返回并继续训练您的模型,请不要永久删除它。

为什么我们实际上需要两个矩阵(而不是一个)来用于这些模型。我们不能对 U 和 V 使用同一个吗?

原则上,你是对的,我们可以。但是我们不想这样做,因为参数数量的增加在实践中是有好处的,但是向量的含义呢?

报纸怎么说?

Word2vec:只有一次提到输入/输出向量只是为了引入变量。

GloVe:“单词和上下文单词之间的区别是任意的,我们可以自由地交换这两个角色”。

弱理由:

向量对(单词,上下文),也称为(目标,源)或(输出,输入),用于反映单个单词将扮演的两种不同角色。然而,由于一个词会在同一个句子中同时扮演“目标”和“上下文”的角色,所以理由很弱。例如,在句子“I love deep learning”中,在(deep|le一个rn一世nG), deep是一个目标,但接下来(le一个rn一世nG|deep),它是一个上下文,尽管事实上deep在整个句子中具有相同的语义。我们可以得出结论,这种分离没有数据支持。

所以在词嵌入的情况下,这种分离只是我们通过增加参数数量来提高性能的一个故事,没有任何更深层次的东西。

坚实的理由:

然而,在像节点嵌入有向网络这样的任务中,理由是可靠的,因为角色反映在数据级别例如,对于一个链接(一个,b), 一个 是在语义上不同于链接接收端的源 b. 源节点永远不会扮演“目标”角色,除非它是另一个链接中的目标。因此,您可以期望通过对目标(源)节点使用目标(源)表示来实现有意义的语义分离。对于与词嵌入相同的无向图,这种证明失败了。

在一些论文中,作者甚至根据实体在数据级别所扮演的额外角色选择四种表示,这在语义上是合理的,并进一步提高了性能。

结论:

整个前提是“如果增加参数数量有回报,那就去做。如果它在语义上是合理的,那就更好了。”

W仅使用一个形状向量空间实现 word2vec CBOW ,(V, D)其中V是词汇D的数量,是词向量中的特征数量。

简而言之,它没有很好地工作。

Let(word, context)是一对并从上下文中创建BoW(词袋)。例如,一个句子的对I love dogs that meaw(dogs, I love that meaw)当上下文长度为 4 时。

使用粗斜体表示它是(word, context)成对的字。

训练的步骤如下所示,将成对的N数量(word, context)作为一个批次进行喂养。

正分

从上下文中提取的词向量计算BoW ,并将与该词的W向量的点积作为正分数。

E-1。提取一个词向量WeWe = W[index_of_word]其中单词index_of_word的索引在哪里 E-2。提取上下文向量where并创建BoW E-3。计算作为的分数 E-4。计算损失 E-5。反向传播as E-6。反向传播as W
WcWc = W[indices_of_context] Bc = sum(Wc, axis=0)
WeBcYe = dot(Bc, We)
Le = -log(sigmoid(Ye))
dLe/dYeWedLe/dWe = dLe/dYe * dYe/dWe = dLe/dYe * Bc
dLe/dYeWcdLe/dWc = dLe/dYe * dYe/dWc = dLe/dYe * We

在实际的自差计算中,sum需要考虑 的导数来应用*运算。

负分及其损失值

取负样本词的个数,并以BoWSL为负分数,以点积计算每个负样本的负分数。结果是负分的数量。SL

S-1。SL负样本词的数量,不包括 中的那些词(word, context)
S-2。提取负样本的词向量,Ws其中Ws = W[indices_of_samples].
S-3。Ws从和计算负分数,Bc因为Ys = einsum("nd,nsd->ns",Bc, Ws)
*n代表批量大小Nd代表词向量大小Ds代表负样本大小SL
S-4。计算损失Ls = -log(1 - sigmoid(Ys))
S-5。反向传播dLs/dYsWsas dLs/dWs = dLs/dYs * dYs/dWs = dLs/dYs * Bc
S-6。反向传播dLe/dYeWcas dLe/dWc = dLs/dYs * dYs/dWs = dLs/dYs * Ws

在实际的自差分计算中,需要考虑einsum的导数来应用*运算。

问题

我认为单个不工作的原因是同时 在一批中使用多个反向传播W更新相同的结果:W

  • 正分数反向传播dLe/dWedLe/dWc
  • 负分反向传播dLs/dWs dLs/dWc.

在此处输入图像描述

在具有多(word, context)对的批次中,一对可能具有X作为正分数的但它可以用作同一批次中其他对的负样本。因此,在批次中的梯度下降期间,单词X将用于正分数和负分数。

因此,反向传播将同时更新W[X]正负两个词向量。

假设在一个批次的第 1 行,这个词dogs一个对的(word, context),并且用于一个正分数。W[index_for_dogs]由 更新dLe/dWe

然后对于批次中的第二对,dogs作为负样本进行采样。然后W[index_for_dogs]由 更新dLs/dWs可以(word, context)在一个批次中成对地排除所有单词,但这会导致负样本可用的单词集狭窄或倾斜。

此外,相同的词向量 inW将是一对context,在另一对中是 a,并且是另一对的负样本。

我相信这些混合物可能是一种混淆行为

  • 奖励(正分支持)和惩罚(负分支持)相同 W
  • 使用与word、 context 和负样本相同的词。

因此,将需要分离成不同的向量空间以给出明确的作用,例如,一个向量空间Wc用于上下文。

可能有一个单独的向量空间用于单词,一个用于负样本。对两者使用一个向量空间也会同时导致正负反向传播。我认为这可能是为什么用于负样本的向量空间不用作 word2vec 的结果模型的原因。