理解tensorflow中的`tf.nn.nce_loss()`

时间:2017-01-04 23:54:20

标签: python tensorflow

我试图了解Tensorflow中的NCE损失函数。 NCE丢失用于word2vec任务,例如:

# Look up embeddings for inputs.
embeddings = tf.Variable(
    tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0))
embed = tf.nn.embedding_lookup(embeddings, train_inputs)

# Construct the variables for the NCE loss
nce_weights = tf.Variable(
    tf.truncated_normal([vocabulary_size, embedding_size],
                        stddev=1.0 / math.sqrt(embedding_size)))
nce_biases = tf.Variable(tf.zeros([vocabulary_size]))

# Compute the average NCE loss for the batch.
# tf.nce_loss automatically draws a new sample of the negative labels each
# time we evaluate the loss.
loss = tf.reduce_mean(
    tf.nn.nce_loss(weights=nce_weights,
                   biases=nce_biases,
                   labels=train_labels,
                   inputs=embed,
                   num_sampled=num_sampled,
                   num_classes=vocabulary_size))

更多详情,请参阅Tensorflow word2vec_basic.py

  1. NCE功能中的输入和输出矩阵是什么?
  2. 在word2vec模型中,我们有兴趣为单词构建表示。在训练过程中,给定一个滑动窗口,每个单词将有两个嵌入:1)当单词是中心单词时; 2)当单词是上下文单词时。这两个嵌入分别称为输入和输出向量。 (more explanations of input and output matrices

    在我看来,输入矩阵是embeddings,输出矩阵是nce_weights。是不是?

    1. 什么是最终嵌入?
    2. 根据post s0urcer也与nce有关,它说最终的嵌入矩阵只是输入矩阵。同时,some others sayingfinal_embedding=input_matrix+output_matrix。哪个是对的/更常见的?

5 个答案:

答案 0 :(得分:14)

让我们看一下 word2vec 示例中的相对代码(examples/tutorials/word2vec)。

embeddings = tf.Variable(
    tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0))
embed = tf.nn.embedding_lookup(embeddings, train_inputs)

这两行创建嵌入表示。 embeddings是一个矩阵,其中每一行代表一个单词向量。 embedding_lookup是获取与train_inputs对应的向量的快捷方法。在word2vec示例中,train_inputs由一些int32个数字组成,代表目标字词的id。基本上,可以通过隐藏图层功能放置

# Construct the variables for the NCE loss
nce_weights = tf.Variable(
    tf.truncated_normal([vocabulary_size, embedding_size],
                        stddev=1.0 / math.sqrt(embedding_size)))
nce_biases = tf.Variable(tf.zeros([vocabulary_size]))

这两行创建参数。它们将在培训期间由优化器更新。我们可以使用tf.matmul(embed, tf.transpose(nce_weights)) + nce_biases来获得最终输出分数。换句话说,分类中的最后一个内积层可以替换为

loss = tf.reduce_mean(
      tf.nn.nce_loss(weights=nce_weights,     # [vocab_size, embed_size]
                   biases=nce_biases,         # [embed_size]
                   labels=train_labels,       # [bs, 1]
                   inputs=embed,              # [bs, embed_size]
                   num_sampled=num_sampled, 
                   num_classes=vocabulary_size))

这些行创建nce loss @garej 给出了非常好的解释。 num_sampled是指nce算法中的负抽样数。

为了说明nce的用法,我们可以将其应用于 mnist 示例(examples/tutorials/mnist/mnist_deep.py),并执行以下两个步骤:

<强> 1。将嵌入替换为隐藏图层输出。隐藏图层的维度为1024,num_output为10num_sampled的最小值为1.请记住删除deepnn()中的最后一个内积层。

y_conv, keep_prob = deepnn(x)                                            

num_sampled = 1                                                          
vocabulary_size = 10                                                     
embedding_size = 1024                                                    
with tf.device('/cpu:0'):                                                
  embed = y_conv                                                         
  # Construct the variables for the NCE loss                             
  nce_weights = tf.Variable(                                             
      tf.truncated_normal([vocabulary_size, embedding_size],             
                          stddev=1.0 / math.sqrt(embedding_size)))       
  nce_biases = tf.Variable(tf.zeros([vocabulary_size])) 

<强> 2。创建损失和计算输出。计算输出后,我们可以用它来计算精度。请注意,此处的标签不是softmax中使用的单热矢量。标签是培训样本的原始标签。

loss = tf.reduce_mean(                                   
    tf.nn.nce_loss(weights=nce_weights,                           
                   biases=nce_biases,                             
                   labels=y_idx,                                  
                   inputs=embed,                                  
                   num_sampled=num_sampled,                       
                   num_classes=vocabulary_size))                  

output = tf.matmul(y_conv, tf.transpose(nce_weights)) + nce_biases
correct_prediction = tf.equal(tf.argmax(output, 1), tf.argmax(y_, 1))

当我们设置num_sampled=1时,val准确度将以98.8%左右结束。如果我们设置num_sampled=9,我们可以获得与softmax训练的val精度几乎相同的val精度。但请注意,ncesoftmax不同。

可以找到mnist的完整培训代码nce here。希望它有所帮助。

答案 1 :(得分:2)

embeddings Tensor是您的最终输出矩阵。它将单词映射到向量。在单词预测图中使用它。

输入矩阵是从训练文本生成的一批centre-word : context-word对(train_inputtrain_label)。

虽然nce_loss op的确切工作原理尚不清楚,但基本思路是它使用单层网络(参数nce_weightsnce_biases)来映射输入向量(使用embeddings op从embed中选择)到输出词,然后将输出与训练标签(训练文本中的相邻单词)以及随机子样本进行比较(num_sampled)词汇表中的所有其他单词,然后修改输入向量(存储在embeddings中)和网络参数以最小化错误。

答案 2 :(得分:1)

  

NCE功能中的输入和输出矩阵是什么?

以跳过的克模型为例:

the quick brown fox jumped over the lazy dog

输入和输出对是:

(quick, the), (quick, brown), (brown, quick), (brown, fox), ...

有关详细信息,请参阅the tutorial

  

最终的嵌入是什么?

您应该提取的最终嵌入通常是输入和隐藏图层之间的{w}

enter image description here

为了更直观地说明,请看下面的图片: enter image description here

一个热矢量[0,0,0,1,0]是上图中的输入层,输出是字嵌入[10,12,19],W(在上图中)是中间的矩阵。

有关详细说明,请阅读this tutorial

答案 3 :(得分:1)

1)简而言之,它一般是正确的,但对于所讨论的功能只是部分正确。见tutorial

  

噪声对比估计损失定义为a   逻辑回归模型。为此,我们需要定义权重和   词汇表中每个单词的偏见(也称为output weights   而不是input embeddings)。

因此,nce_loss函数的输入为output weightsinput embeddings部分为<{1}}。

2)&#39;决赛&#39;嵌入(又名Word向量,又名单词的向量表示)就是你所说的input matrix。嵌入是该矩阵的字符串(向量),对应于每个单词。

警告事实上,由于NN环境中的输入和输出概念用法,这个术语令人困惑。嵌入矩阵不是NN的输入,因为NN的输入在技术上是输入层。您可以在培训过程中获得此矩阵的最终状态。尽管如此,这个矩阵应该在编程中初始化,因为算法必须从该矩阵的某个随机状态开始,以便在训练期间逐步更新它。

权重也是如此 - 它们也要初始化。它发生在以下行:

nce_weights = tf.Variable(
        tf.truncated_normal([50000, 128], stddev=1.0 / math.sqrt(128)))

每个嵌入向量可以乘以权重矩阵的向量(以字符串到列的方式)。所以我们将在NN output layer中得到标量。此标量的范数被解释为目标词(来自输入层)将伴随与output layer中的标量位置对应的标签[或上下文]字的概率。

所以,如果我们说的是函数的输入(参数),那么两个矩阵都是这样的:权重和嵌入式的批量大小提取:

tf.nn.nce_loss(weights=nce_weights,            # Tensor of shape(50000, 128)
               biases=nce_biases,              # vector of zeros; len(128)
               labels=train_labels,            # labels == context words enums
               inputs=embed,                   # Tensor of shape(128, 128)
               num_sampled=num_sampled,        # 64: randomly chosen negative (rare) words
               num_classes=vocabulary_size))   # 50000: by construction

nce_loss函数输出batch_size的向量 - 在TensorFlow示例中为shape(128,)张量。 然后reduce_mean()将此结果减少为采用这128个值的平均值的标量,这实际上是进一步最小化的目标。

希望这有帮助。

答案 4 :(得分:0)

从论文 有效地学习单词嵌入与噪声对比估计

  

NCE基于将密度估计减少到概率二元分类。基本思想是训练逻辑回归分类器   区分来自数据分布的样本和来自某些“噪声”分布的样本

我们可以发现,在字嵌入中,NCE实际上是负抽样。 (关于这两者之间的区别,请参阅论文: 关于噪声对比度估计和负采样的注意事项

因此,您无需输入噪音分布。而且从引用中,你会发现它实际上是一个逻辑回归:权重和偏见是逻辑回归所需要的。如果您熟悉word2vec,那只是添加偏见。