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

时间:2017-11-08 06:13:12

标签: machine-learning tensorflow cross-entropy

我使用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 tensor的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时工作正常吗?

2 个答案:

答案 0 :(得分:1)

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

  
      
  • 标签:形状张力[d_0,d_1,...,d_ {r-1}](其中r是等级   标签和结果)和dtype int32或int64。标签中的每个条目都必须   是[0,num_classes)中的索引。其他值将引发异常   当此操作在CPU上运行时,返回NaN以获得相应的损失   GPU上的渐变行。
  •   
  • logits :形状的非标定日志概率   [d_0,d_1,...,d_ {r-1},num_classes]和dtype float32或float64。
  •   

tf.hinge_loss要求不同:

  
      
  • 标签:地面实况输出张量。它的形状应该匹配   logits的形状。张量的值预计为0.0或   1.0。
  •   
  • logits :logits,一个浮动张量。
  •   

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

  • 将标签重新塑造为[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

  • 通过logits使用所有已学习的tf.reduce_sum功能,这将使(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

答案 1 :(得分:0)

原因在马克西姆的答案中得到了很好的解释。我试图根据您的目标是为不同的类添加权重来提供一些替代解决方案。

您的权重似乎与批量大小相同。我猜你的目标是为不同的班级添加不同的权重,以及"权重"通过类似于下面的一些代码获得:

class_weights = [0.4, 0.6] # The weights for each class
weights = tf.reduce_sum(class_weights * tf.labels, axis = 1)

这些代码是将要添加到每个样本的类权重转换为批处理中每个样本的权重,以便我们可以通过间接加权样本来对类进行加权。 (例如,对于标签为[0,1]的样本,计算的样本权重为0 * 0.4 + 1 * 0.6 = 0.6,实际上是类权重)

但是当你使用tf.losses.hinge_loss时,不需要进行这种转换。权重参数必须是" 0或相同的标签等级,并且必须可以广播到标签(即,所有维度必须是1,或者与相应的损失维度相同)"

因此,您需要创建等级为1(2维)的类权重,而维度0为1或批量大小。以下程序可以正常工作。

weights = tf.expand_dims(class_weights, axis = 0)
hinge_loss = tf.losses.hinge_loss(labels = self.label, logits = self.prediction, 
                                  weights = weights)

由于我没有足够的声誉来评论这个问题,我无法获得有关您任务的更多信息。以上所有答案都基于您要为不同类添加权重的假设。所以,如果我错了,请通知我删除这个答案:)。