Tensorflow - 使用 tf.losses.hinge_loss 导致形状不兼容错误

Tensorflow - Using tf.losses.hinge_loss causing Shapes Incompatible error

我当前使用 sparse_softmax_cross_entropy 的代码工作正常。

loss_normal = (
    tf.reduce_mean(tf.losses
                   .sparse_softmax_cross_entropy(labels=labels,
                                                 logits=logits,
                                                 weights=class_weights))
    )

但是,当我尝试使用 hinge_loss:

loss_normal = (
    tf.reduce_mean(tf.losses
                   .hinge_loss(labels=labels,
                               logits=logits,
                               weights=class_weights))
    )

它报告了一个错误说:

ValueError: Shapes (1024, 2) and (1024,) are incompatible

错误似乎源于 losses_impl.py 文件中的这个函数:

  with ops.name_scope(scope, "hinge_loss", (logits, labels)) as scope:
    ...
    logits.get_shape().assert_is_compatible_with(labels.get_shape())
    ...

我修改了我的代码如下,只提取 logits 张量的 1 列:

loss_normal = (
    tf.reduce_mean(tf.losses
                   .hinge_loss(labels=labels,
                               logits=logits[:,1:],
                               weights=class_weights
                               ))
    )

但是还是报类似的错误:

ValueError: Shapes (1024, 1) and (1024,) are incompatible.

有人可以帮忙指出为什么我的代码可以在 sparse_softmax_cross_entropy 丢失但不能 hinge_loss 的情况下正常工作吗?

张量 labels 的形状为 [1024],张量 logits 的形状为 [1024, 2]。这适用于 tf.nn.sparse_softmax_cross_entropy_with_logits:

  • labels: Tensor of shape [d_0, d_1, ..., d_{r-1}] (where r is rank of labels and result) and dtype int32 or int64. Each entry in labels must be an index in [0, num_classes). Other values will raise an exception when this op is run on CPU, and return NaN for corresponding loss and gradient rows on GPU.
  • logits: Unscaled log probabilities of shape [d_0, d_1, ..., d_{r-1}, num_classes] and dtype float32 or float64.

但是tf.hinge_loss要求不同:

  • labels: The ground truth output tensor. Its shape should match the shape of logits. The values of the tensor are expected to be 0.0 or 1.0.
  • logits: The logits, a float tensor.

您可以通过两种方式解决此问题:

  • 将标签重塑为 [1024, 1] 并仅使用一行 logits,就像您所做的那样 - logits[:,1:]:

    labels = tf.reshape(labels, [-1, 1])
    hinge_loss = (
        tf.reduce_mean(tf.losses.hinge_loss(labels=labels,
                                            logits=logits[:,1:],
                                            weights=class_weights))
        )
    

    我认为您还需要以同样的方式重塑 class_weights

  • 使用通过 tf.reduce_sum 学习到的所有 logits 特征,这将生成平坦的 (1024,) 张量:

    logits = tf.reduce_sum(logits, axis=1)
    hinge_loss = (
        tf.reduce_mean(tf.losses.hinge_loss(labels=labels,
                                            logits=logits,
                                            weights=class_weights))
        )
    

    这样你就不需要重塑 labelsclass_weights.