2016-07-03 35 views
0

Word2vec模型使用噪声对比估计(NCE)损失来训练模型。为什么在word2vec培训过程中使用tf.mul?

为什么在真实样本logit计算中使用tf.mul,但在负向计算中使用tf.matmul

请参阅source code

+0

仅供参考:'tf.mul'已更改为'tf.multiply'。请参阅:https://www.tensorflow.org/api_docs/python/tf/multiply –

回答

0

您可以考虑NCE损失计算的一种方法是作为一批独立的二元逻辑回归分类问题。在这两种情况下,我们都执行相同的计算,尽管它看起来并不像第一个那样。

要告诉你,我们在实际计算同样的事情,承担起真正的输入部分follwoing:

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]是从emb获得的word_id = 1的输入词的词向量,[w1,w2,w3]是word_id = 0的期望的目标词的词向量。

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

两个分类任务然后是(没有偏置,并且tensorflow具有这个方便 'sigmoid_cross_entropy_with_logits' 功能,后来施加乙状结肠):

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 

我们可以计算[[分对数(1 => 0 )],[logit(1 => 2)]]是最简单的,如果我们执行元素方面的乘法tf.mul(),然后总结每一行。

此计算的输出将是一个[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]。

直观地看,这意味着你增加6个多训练样本的批次,即:

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 

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

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

现在,在这种情况下,我们才能转置sampled_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。每个元素表示分类任务的逻辑。

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

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,稍后应用)。