为什么在word2vec培训过程中使用tf.mul?

时间:2016-07-03 08:03:35

标签: tensorflow word2vec

Word2vec模型使用噪声对比估计(NCE)损失来训练模型。

为什么它在真正的样本logit计算中使用tf.mul,但在否定计算中使用tf.matmul

请参阅source code

1 个答案:

答案 0 :(得分:0)

您可以想到NCE损失计算的一种方法是作为一批独立的二元逻辑回归分类问题。在这两种情况下,我们都在执行相同的计算,即使它在第一时间看起来不像它。

为了向您展示我们实际上正在计算同样的事情,假设真正的输入部分如下:

emb_dim    = 3 # dimensions of your embedding vector 
batch_size = 2 # number of examples in your trainings batch
vocab_size = 6 # number of total words in your text 
               # (so your word ids range from 0 - 5)

此外,假设您的批次中有以下培训示例:

1 => 0 # given word with word_id=1, I expect word with word_id=0 
1 => 2 # given word with word_id=1, I expect word with word_id=2

然后您的嵌入矩阵example_emb的尺寸为[2,3],而您的真实权重矩阵true_w的尺寸也为[2,3],应该如下所示:

example_emb = [ [e1,e2,e3], [e1,e2,e3] ] # [2,3]  input word
true_w      = [ [w1,w2,w3], [w4,w5,w5] ] # [2,3]  target word

example_emb是您尝试学习的总字嵌入(emb)的子集,而true_w是权重的一个子集(smb_w_t)。 example_emb中的每一行表示和输入向量,权重中的每一行表示目标向量。

因此[e1,e2,e3]是输入字的字向量,其中word_id = 1取自emb,而[w1,w2,w3]是预期目标字的字向量,其中word_id = 0。 / p>

现在直观地说,你要解决的分类任务是:给定我看到输入词和目标词这个观察是否正确?

然后是两个分类任务(没有偏差,张量流有这个方便的'sigmoid_cross_entropy_with_logits'函数,后来应用sigmoid):

logit( 1=>0 ) = dot( [e1,e2,e3], transpose( [w1,w2,w3] )   =>
logit( 1=>0 )  = e1*w1 + e2*w2 + e3*w3  

and

logit( 1=>2 )  = dot( [e1,e2,e3], transpose( [w4,w5,w6] )   =>
logit( 1=>2 )  = e1*w4 + e2*w5 + e3*w6 

如果我们执行逐元素乘法tf.mul()然后对每一行求和,我们可以计算[[logit(1 => 0)],[logit(1 => 2)]]最简单。

此计算的输出将是[batch_size,1]矩阵,其中包含正确单词的对数。我们知道这个例子的基本事实/标签(y'),这是1,因为这些是正确的例子。

true_logits = [ 
  [logit(1=>0)], # first input word of the batch 
  [logit(1=>2)]  # second input word of the batch
]

现在,对于你的问题的第二部分,为什么我们在负抽样中使用tf.matmul(),让我们假设我们绘制了3个负样本(num_sampled = 3)。所以sampled_ids = [3,4,5]。

直观地说,这意味着您要向批次添加六个培训示例,即:

1 => 3 # given word_id=1, do i expect word_id=3? No, because these are negative examples.
1 => 4
1 => 5
1 => 3 # second input word is also word_id=1
1 => 4
1 => 5

所以你查找你的sampled_w,结果证明是[3,3]矩阵。您的参数现在看起来像这样:

example_emb = [ [e1,e2,e3], [e1,e2,e3] ] # [2,3]  input word
sampled_w   = [ [w6,w7,w8], [w9,w10,w11], [w12,w13,w14] ] # [3,3]  sampled target words

与真实情况类似,我们想要的是所有负面训练示例的对数。例如,第一个例子:

logit(1 => 3) = dot( [e1,e2,e3], transpose( [w6,w7,w8] )   =>
logit(1 => 3) = e1*w6 + e2*w7 + e3*w8

现在在这种情况下,我们可以在转换sampling_w矩阵后使用矩阵乘法。这是使用tf.matmul()调用中的transpose_b = True参数实现的。转置的权重矩阵如下所示:

sampled_w_trans   = [ [w6,w9,w12], [w7,w10,w13], [w8,w11,w14] ] # [3,3]

所以现在tf.matmul()操作将返回一个[batch_size,3]矩阵,其中每一行都是输入批处理的一个示例的logits。每个元素代表分类任务的logit。

负抽样的整个结果矩阵包含:

sampled_logits = [ 
  [logit(1=>3), logit(1,4), logit(1,5)], # first input word of the batch 
  [logit(1=>3), logit(1,4), logit(1,5)]  # second input word of the batch
]

sampled_logits的标签/基础事实都是零,因为这些是负面的例子。

在这两种情况下,我们执行相同的计算,即二元分类逻辑回归的计算(没有sigmoid,稍后会应用)。