我当前使用 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 张量的一列:
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:形状为 [d_0, d_1, …, d_{r-1}](其中 r 是 labels 和结果的秩)的张量,数据类型为 int32 或 int64。labels 中的每个条目必须是 [0, num_classes) 范围内的索引。在 CPU 上运行此操作时,其他值将引发异常,在 GPU 上将返回 NaN 对应的损失和梯度行。
- logits:形状为 [d_0, d_1, …, d_{r-1}, num_classes] 且数据类型为 float32 或 float64 的未缩放的对数概率。
但 tf.hinge_loss
的要求不同:
- labels:真实输出张量。其形状应与 logits 的形状匹配。张量的值应为 0.0 或 1.0。
- logits:logits,一个浮点张量。
你可以通过以下两种方式解决这个问题:
-
将 labels 重塑为
[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)) )
这样你就不需要重塑
labels
或class_weights
。