【问题标题】:tensorflow cross entropy loss for sequence with different lengths不同长度序列的张量流交叉熵损失
【发布时间】:2018-06-10 00:52:08
【问题描述】:

我正在使用 tensorflow 使用 LSTM 构建 seq2seq 模型。我使用的损失函数是 softmax 交叉熵损失。问题是我的输入序列有不同的长度,所以我填充了它。模型的输出形状为[max_length, batch_size, vocab_size]。如何计算 0 填充值不影响损失的损失? tf.nn.softmax_cross_entropy_with_logits 提供了轴参数,因此我们可以使用 3 维计算损失,但它不提供权重。 tf.losses.softmax_cross_entropy 提供权重参数,但它接收形状为[batch_size, nclass(vocab_size)] 的输入。请帮忙!

【问题讨论】:

    标签: tensorflow


    【解决方案1】:

    下面的函数接受两个形状的张量(batch_size,time_steps,vocab_len)。计算掩码以将与填充相关的时间步归零。掩码将消除分类交叉熵中的填充损失。

    # the labels that has 1 as the first element
    def mask_loss(y_true, y_pred):
        mask_value = np.zeros((vocab_len))
        mask_value[0] = 1
        # find out which timesteps in `y_true` are not the padding character 
        mask = K.equal(y_true, mask_value)
        mask = 1 - K.cast(mask, K.floatx())
        mask = K.sum(mask,axis=2)/2
        # multplying the loss by the mask. the loss for padding will be zero
        loss = tf.keras.layers.multiply([K.categorical_crossentropy(y_true, y_pred), mask])
        return K.sum(loss) / K.sum(mask)
    

    【讨论】:

      【解决方案2】:

      在这种情况下,您需要填充两个 logits 和标签,以使它们具有相同的长度。所以,如果你有张量logits 的大小为(batch_size, length, vocab_size)labels 的大小为(batch_size, length) 其中length 是你的序列的大小。首先,您必须将它们填充到相同的长度:

      def _pad_tensors_to_same_length(logits, labels):
          """Pad x and y so that the results have the same length (second dimension)."""
          with tf.name_scope("pad_to_same_length"):
              logits_length = tf.shape(logits)[1]
              labels_length = tf.shape(labels)[1]
      
              max_length = tf.maximum(logits_length, labels_length)
      
              logits = tf.pad(logits, [[0, 0], [0, max_length - logits_length], [0, 0]])
              labels = tf.pad(labels, [[0, 0], [0, max_length - labels_length]])
              return logits, labels
      

      然后你可以做填充交叉熵:

      def padded_cross_entropy_loss(logits, labels, vocab_size):
        """Calculate cross entropy loss while ignoring padding.
      
        Args:
          logits: Tensor of size [batch_size, length_logits, vocab_size]
          labels: Tensor of size [batch_size, length_labels]
          vocab_size: int size of the vocabulary
        Returns:
          Returns the cross entropy loss 
        """
        with tf.name_scope("loss", values=[logits, labels]):
          logits, labels = _pad_tensors_to_same_length(logits, labels)
      
          # Calculate cross entropy
          with tf.name_scope("cross_entropy", values=[logits, labels]):
            xentropy = tf.nn.softmax_cross_entropy_with_logits_v2(
                logits=logits, labels=targets)
      
          weights = tf.to_float(tf.not_equal(labels, 0))
          return xentropy * weights
      

      【讨论】:

        【解决方案3】:

        我认为您必须编写自己的损失函数。查看https://danijar.com/variable-sequence-lengths-in-tensorflow/

        【讨论】:

        • 非常感谢,但我在博客中读到:“'实际上,我们不必对成本和误差函数进行屏蔽,因为预测和目标都是零向量填充帧,因此它们是完美的预测。”真的吗?因为当 X 为 0 但偏差 > 0 时,我认为损失会受到影响!
        • 我同意,偏差甚至简单的 sigmoid 都会产生非零输出。
        • 但是我对网站上的这个声明有疑问。填充时预测不是零向量,因为您正在通过 softmax 层获取未缩放的 logits,这意味着现在它们是非零的。只有目标为零,因此将非零标度 logits(即预测)与零目标相乘将为零,对吗?
        猜你喜欢
        • 1970-01-01
        • 2018-06-06
        • 2021-08-25
        • 2018-02-05
        • 2021-05-17
        • 2017-03-05
        • 2018-08-07
        • 2018-09-03
        • 2016-08-01
        相关资源
        最近更新 更多