来自Tensorflow中的sparse_softmax_cross_entropy_with_logits的NaN

时间:2016-09-19 23:58:45

标签: python tensorflow

当我尝试在tensorflow中使用sparse_softmax_cross_entropy_with_logits丢失函数时,我得到了NaN。我有一个简单的网络,如:

layer = tf.nn.relu(tf.matmul(inputs, W1) + b1)
layer = tf.nn.relu(tf.matmul(inputs, W2) + b2)
logits = tf.matmul(inputs, W3) + b3
loss = tf.sparse_softmax_cross_entropy_with_logits(logits, labels)

我有很多类(~10000),所以我想我得到了NaN,因为至少有一个示例中对应于正确类的logit被截断为零。有没有办法避免这种情况?

3 个答案:

答案 0 :(得分:8)

事实证明我的一些标签超出了范围(例如标签为14000,当我的logits矩阵只有150 x 10000时)。事实证明,这会导致NaN而不是错误。

答案 1 :(得分:4)

tf.sparse_softmax_cross_entropy_with_logits为您处理log(0)的情况,您不必担心。

通常NaN归因于优化算法的高学习率。尝试降低它,直到NaN错误消失并且损失开始减少

答案 2 :(得分:0)

如前所述,当其中一个softmaxed logit被截断为0时,可能会发生NaN错误,然后执行log(0)来计算交叉熵错误。

为了避免这种情况,正如this other answer中建议的那样,你可以剪切softmax输出的值,使它们永远不为零。

out = tf.clip_by_value(out,1e-10,100.0)

或者你可以添加一个小常量来避免零:

out = out + 1e-10

问题在于,sparse_softmax_cross_entropy_with_logits()在内部对logits应用了softmax函数,因此无法改变其行为。

要解决此问题,请自行编码交叉熵错误,并将常量1e-10添加到softmax的输出,而不是logits。

loss = -tf.reduce_sum(labels*tf.log(tf.nn.softmax(logits) + 1e-10))

请注意,使用sparse_softmax_cross_entropy_with_logits()函数时,变量labels是标签的数值,但如果您自己实现交叉熵丢失,labels必须是 - 这些数字标签的编码。

更新:由于@mdaoust的评论,我已经更正了答案。正如他所说的那样,只有在将softmax函数应用于logits后才能使用零,而不是之前。