微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

分类交叉熵背后的直觉

如何解决分类交叉熵背后的直觉

我正在尝试制作分类交叉熵损失函数以更好地理解其背后的直觉。 到目前为止,我的实现是这样的:

# Observations
y_true = np.array([[0,1,0],[0,1]])
y_pred = np.array([[0.05,0.95,0.05],[0.1,0.8,0.1]])

# Loss calculations
def categorical_loss():
  loss1 = -(0.0 * np.log(0.05) + 1.0 * np.log(0.95) + 0 * np.log(0.05))
  loss2 = -(0.0 * np.log(0.1) + 0.0 * np.log(0.8) + 1.0 * np.log(0.1))
  loss = (loss1 + loss2) / 2 # divided by 2 because y_true and y_pred have 2 observations and 3 classes
  return loss

# Show loss
print(categorical_loss()) # 1.176939193690798

但是我不明白函数在以下情况下应该如何返回正确的值:

  • y_pred 中至少有一个数字是 01 因为然后 log 函数返回 -inf0 以及代码实现应该如何看起来像这种情况
  • y_true 中至少有一个数是 0 因为乘以 0 总是返回 0 并且 np.log(0.95) 的值将被丢弃然后代码如何实现在这种情况下也应该看起来像

解决方法

关于 y_pred 是 0 还是 1,深入研究 binary_crossentropycategorical_crossentropy 的 Keras 后端源代码,我们得到:

def binary_crossentropy(target,output,from_logits=False):
    if not from_logits:
        output = np.clip(output,1e-7,1 - 1e-7)
        output = np.log(output / (1 - output))
    return (target * -np.log(sigmoid(output)) +
            (1 - target) * -np.log(1 - sigmoid(output)))


def categorical_crossentropy(target,from_logits=False):
    if from_logits:
        output = softmax(output)
    else:
        output /= output.sum(axis=-1,keepdims=True)
    output = np.clip(output,1 - 1e-7)
    return np.sum(target * -np.log(output),axis=-1,keepdims=False)

从中可以清楚地看到,在两个函数中,output(即预测)都有一个裁剪操作,以避免对数的无穷大:>

output = np.clip(output,1 - 1e-7)

因此,这里的 y_pred 在底层计算中永远不会正好是 0 或 1。其他框架中的处理类似。

关于 y_true 为 0,不涉及任何问题 - 相应的术语设置为 0,因为它们应该根据数学定义。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。