以 SparseCategoricalCrossentropy(from_logits=True) 为例,读keras源码,发现 losses.py 中定义的 SparseCategoricalCrossentropy 实际上调用的是 backend.py 中的 sparse_categorical_crossentropy 函数,代码当中有如下一段:

elif not from_logits:
    epsilon_ = _constant_to_tensor(epsilon(), output.dtype.base_dtype)
    output = tf.clip_by_value(output, epsilon_, 1 - epsilon_)
    output = tf.math.log(output)

也就是说,如果 from_logits=False (即输出层是带softmax激活函数的),那么其结果会被clip在 [epsilon_, 1 - epsilon_] 的范围之内。这是由于简单的softmax函数会有数值溢出的问题 (参见 softmax溢出问题)。因此如果是先计算softmax再计算cross-entropy,那么要通过clip防止数据溢出问题。

而如果设置 from_logits=True,那么模型会将 softmax和cross-entropy 结合在一起计算,即 softmax溢出问题 中的公式:
log ( y j ^ ) = log ( e x j − x ∗ ∑ i = 1 n e x i − x ∗ ) = ( x j − x ∗ ) − log ( ∑ i = 1 n e x i − x ∗ ) \begin{aligned} \text{log}(\hat{y_j}) &= \text{log}(\frac{e^{x_j - x^*}}{\sum_{i=1}^{n} e^{x_i - x^*}})\\ &= (x_j - x^*) - \text{log}(\sum_{i=1}^{n} e^{x_i - x^*}) \end{aligned} log(yj^)=log(i=1nexixexjx)=(xjx)log(i=1nexix)

这样可以更好的解决softmax的溢出问题。因此 设置 from_logits=True 一般会比 from_logits=False 数值稳定性更强。(如果计算过程中没用遇到过大或过小的数值,那么两者就没有什么区别)

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐