python - 为什么我的对数损失(或交叉熵)的实现没有产生相同的结果?

标签 python machine-learning scikit-learn metrics cross-entropy

我正在阅读 log-loss和交叉熵,似乎有 2 种计算方法,基于以下等式。

enter image description here

第一个是the following .

import numpy as np
from sklearn.metrics import log_loss


def cross_entropy(predictions, targets):
    N = predictions.shape[0]
    ce = -np.sum(targets * np.log(predictions)) / N
    return ce


predictions = np.array([[0.25,0.25,0.25,0.25],
                        [0.01,0.01,0.01,0.97]])
targets = np.array([[1,0,0,0],
                   [0,0,0,1]])

x = cross_entropy(predictions, targets)
print(log_loss(targets, predictions), 'our_answer:', ans)

前面程序的输出是0.7083767843022996 our_answer: 0.71355817782,几乎是一样的。所以这不是问题。

上面的实现是上面等式的中间部分。

第二种方法基于上述等式的 RHS 部分。

res = 0
for act_row, pred_row in zip(targets, np.array(predictions)):
    for class_act, class_pred in zip(act_row, pred_row):
        res += - class_act * np.log(class_pred) - (1-class_act) * np.log(1-class_pred)

print(res/len(targets))

而输出是1.1549753967602232,这不太一样。

我已经用 NumPy 尝试过相同的实现,但它也没有用。我做错了什么?

PS: 我也很好奇 -y log (y_hat) 在我看来和 - sigma(p_i * log( q_i)) 是一样的 那怎么会有一个 -(1-y) log(1-y_hat) 部分。显然我误解了 -y log (y_hat) 是如何计算的。

最佳答案

我无法重现你在第一部分报告的结果的差异(你还引用了一个 ans 变量,你似乎没有定义它,我猜它是 x):

import numpy as np
from sklearn.metrics import log_loss


def cross_entropy(predictions, targets):
    N = predictions.shape[0]
    ce = -np.sum(targets * np.log(predictions)) / N
    return ce

predictions = np.array([[0.25,0.25,0.25,0.25],
                        [0.01,0.01,0.01,0.97]])
targets = np.array([[1,0,0,0],
                   [0,0,0,1]])

结果:

cross_entropy(predictions, targets)
# 0.7083767843022996

log_loss(targets, predictions)
# 0.7083767843022996

log_loss(targets, predictions) == cross_entropy(predictions, targets)
# True

您的cross_entropy 函数似乎工作正常。

关于第二部分:

Clearly I am misunderstanding how -y log (y_hat) is to be calculated.

确实,更仔细地阅读您链接到的 fast.ai wiki,您会发现方程的 RHS 仅适用于二进制分类(其中始终是 y 1-y 将为零),这里不是这种情况 - 您有一个 4 类多项式分类。所以,正确的表述是

res = 0
for act_row, pred_row in zip(targets, np.array(predictions)):
    for class_act, class_pred in zip(act_row, pred_row):
        res += - class_act * np.log(class_pred)

即丢弃 (1-class_act) * np.log(1-class_pred) 的减法。

结果:

res/len(targets)
# 0.7083767843022996

res/len(targets) == log_loss(targets, predictions)
# True

在更一般的层面上(对数损失机制和二进制分类的准确性),您可能会发现 this answer有用。

关于python - 为什么我的对数损失(或交叉熵)的实现没有产生相同的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49473587/

相关文章:

python - 将UTF-8 python列表解码为数组列表python

python - 取消缩短 Flic.kr 网址

python - 如何在python中检查域是否有ssl证书?

python - 如何使用 redis-py 在 python 脚本中模拟 redis MONITOR 命令?

python - 为什么我收到 AttributeError : 'LinearRegressionGD' object has no attribute 'n_iter'

machine-learning - 交叉验证和网格搜索有什么区别?

用于机器学习算法的 Python csv 流

machine-learning - 为什么验证准确率达到1.00,而训练准确率却达到99%。我的数据由 49 个特征和 700K 个样本组成

python - 导入 scikit-learn 模块时出错

python - 垃圾邮件过滤器 - Python 新手