当我尝试在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被截断为零。有没有办法避免这种情况?
答案 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后才能使用零,而不是之前。