Python 理解tensorflow中的'tf.nn.nce_loss()

Python 理解tensorflow中的'tf.nn.nce_loss(),python,tensorflow,Python,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 variable

我试图理解张量流中的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

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

    在我看来,输入矩阵是
    嵌入
    ,输出矩阵是
    nce\u权重
    。是这样吗

  • 什么是最终嵌入

  • 根据同样与
    nce
    相关的一位学者的说法,最终的嵌入矩阵就是输入矩阵。而
    最终嵌入=输入矩阵+输出矩阵
    。哪个是正确的/更常见的?

    嵌入张量是最终的输出矩阵。它将单词映射到向量。在单词预测图中使用此选项

    输入矩阵是从培训文本生成的一批
    中心词:上下文词对(
    train\u input
    train\u label

    虽然我还不知道
    nce\u loss
    op的确切工作原理,但其基本思想是,它使用单层网络(参数
    nce\u权重
    nce\u偏差
    )将输入向量(使用
    嵌入
    op从
    嵌入中选择)映射到输出字,然后将输出与训练标签(训练文本中的相邻单词)以及vocab中所有其他单词的随机子样本(
    num_sampled
    )进行比较,然后修改输入向量(存储在
    embeddings
    )和网络参数,以将错误降至最低

    NCE函数中的输入和输出矩阵是什么

    以skip gram模型为例,对于这句话:

    敏捷的棕色狐狸跳过了懒狗

    输入和输出对为:

    (快,那个),(快,棕色),(棕色,快),(棕色,狐狸),…

    有关更多信息,请参阅

    什么是最终嵌入

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

    # 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]))
    
    loss = tf.reduce_mean(
          tf.nn.nce_loss(weights=nce_weights,     # [vocab_size, embed_size]
                       biases=nce_biases,         # [vocab_size]
                       labels=train_labels,       # [bs, 1]
                       inputs=embed,              # [bs, embed_size]
                       num_sampled=num_sampled, 
                       num_classes=vocabulary_size))
    

    为了更直观地说明,请看下图:

    一个热向量[0,0,0,1,0]是上图中的输入层,输出是单词嵌入[10,12,19],W(上图中)是介于两者之间的矩阵

    有关详细说明,请阅读。

    1)简而言之,它在总体上是正确的,但对于所讨论的函数来说只是部分正确。见:

    噪声对比估计损失定义为 logistic回归模型。为此,我们需要定义权重和 词汇表中每个单词的偏差(也称为
    输出权重
    输入嵌入相反

    因此,函数
    nce\u loss
    的输入是
    输出权重
    和一小部分
    输入嵌入

    2) “最终”嵌入(又名单词向量,又名单词向量表示)就是您所说的输入矩阵。嵌入是该矩阵的字符串(向量),对应于每个单词

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

    重量也是如此——它们也需要初始化。它发生在以下行中:

    nce_weights = tf.Variable(
            tf.truncated_normal([50000, 128], stddev=1.0 / math.sqrt(128)))
    
    每个嵌入向量可以与权重矩阵中的向量相乘(以字符串到列的方式)。因此,我们将在NN
    输出层
    中获得标量。该标量的范数被解释为目标词(来自输入层)将伴随与
    输出层中标量位置对应的标签[或上下文]词的概率


    因此,如果我们说的是函数的输入(参数),那么这两个矩阵都是这样的:权重和从嵌入中批量提取:

    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\u loss
    函数输出批量大小的向量-在TensorFlow示例中是一个
    shape(128,)
    tensor。 然后
    reduce_mean()
    将此结果减少到一个标量,取这128个值的平均值,这实际上是进一步最小化的目标


    希望这有帮助。

    让我们看看word2vec示例()中的相关代码

    这两条线创建嵌入表示<代码>嵌入
    是一个矩阵,其中每行表示一个单词向量<代码>嵌入查找
    是一种快速获取与
    训练输入
    对应的向量的方法。在word2vec示例中,
    train_输入由一些
    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]))
    
    loss = tf.reduce_mean(
          tf.nn.nce_loss(weights=nce_weights,     # [vocab_size, embed_size]
                       biases=nce_biases,         # [vocab_size]
                       labels=train_labels,       # [bs, 1]
                       inputs=embed,              # [bs, embed_size]
                       num_sampled=num_sampled, 
                       num_classes=vocabulary_size))
    
    这两行创建参数。它们将在培训期间由optimizer更新。我们可以使用
    tf.matmul(嵌入,tf.transpose(nce_权重))+nce_偏差
    来获得最终的输出分数。换句话说,分类中的最后一个内积层可以被它所取代

    # 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]))
    
    loss = tf.reduce_mean(
          tf.nn.nce_loss(weights=nce_weights,     # [vocab_size, embed_size]
                       biases=nce_biases,         # [vocab_size]
                       labels=train_labels,       # [bs, 1]
                       inputs=embed,              # [bs, embed_size]
                       num_sampled=num_sampled, 
                       num_classes=vocabulary_size))
    
    这些行创建了nce损耗,
    @garej给出了很好的解释
    num_sampled
    是指
    nce中的负采样数<