TL;DR 版本:在计算损失函数时,由于数值稳定性,概率值(即 sigmoid 函数的输出)被剪裁。
如果你检查源代码,你会发现使用binary_crossentropy
因为损失将导致致电binary_crossentropy
函数于损失.py file:
def binary_crossentropy(y_true, y_pred):
return K.mean(K.binary_crossentropy(y_true, y_pred), axis=-1)
正如您所看到的,它反过来调用等效的后端函数。如果使用 Tensorflow 作为后端,这将导致调用binary_crossentropy
函数于张量流后端.py file:
def binary_crossentropy(target, output, from_logits=False):
""" Docstring ..."""
# Note: tf.nn.sigmoid_cross_entropy_with_logits
# expects logits, Keras expects probabilities.
if not from_logits:
# transform back to logits
_epsilon = _to_tensor(epsilon(), output.dtype.base_dtype)
output = tf.clip_by_value(output, _epsilon, 1 - _epsilon)
output = tf.log(output / (1 - output))
return tf.nn.sigmoid_cross_entropy_with_logits(labels=target,
logits=output)
如你看到的from_logits
参数设置为False
默认情况下。因此,if 条件的计算结果为 true,因此输出中的值被剪裁到范围内[epsilon, 1-epislon]
。这就是为什么无论概率多小或多大,它都不可能小于epsilon
并且大于1-epsilon
。这解释了为什么输出binary_crossentropy
损失也是有限度的。
现在,这里的 epsilon 是什么?它是一个非常小的常数,用于数值稳定性(例如防止被零除或未定义的行为等)。要找出它的值,您可以进一步检查源代码,您可以在通用.py file:
_EPSILON = 1e-7
def epsilon():
"""Returns the value of the fuzz factor used in numeric expressions.
# Returns
A float.
# Example
```python
>>> keras.backend.epsilon()
1e-07
```
"""
return _EPSILON
如果出于任何原因,您想要更高的精度,您也可以使用以下方法将 epsilon 值设置为较小的常数set_epsilon
来自后端的功能:
def set_epsilon(e):
"""Sets the value of the fuzz factor used in numeric expressions.
# Arguments
e: float. New value of epsilon.
# Example
```python
>>> from keras import backend as K
>>> K.epsilon()
1e-07
>>> K.set_epsilon(1e-05)
>>> K.epsilon()
1e-05
```
"""
global _EPSILON
_EPSILON = e
但是,请注意,将 epsilon 设置为极低的正值或零,可能会破坏整个 Keras 计算的稳定性。