Way2AI · PyTorch的CrossEntropyLoss实现的不对?
TL;DR
Way2AI系列,确保出发去"改变世界"之前,我们已经打下了一个坚实的基础。
作者在学习机器学习之逻辑回归任务时,遇到的交叉熵计算不符合预期,才发现了PyTorch的别有洞天。
于是,本文便是结合实验交代了PyTorch中交叉熵损失的真实计算过程。
数据准备
1 | import numpy as np |
正文
大部分博客给出的公式如下:
$$
H = - \sum_i{y_i log(\hat{y}_i)}
$$
其中 $\hat{y}_i$ 为预测值,$y_i$ 为真实值。
我们在低维空间复现此公式,注意到PyTorch可以采用class indices直接取下标进行计算,这里采用同样的方式模拟。
1 |
|
我们看一下PyTorch的计算结果。
1 | import torch |
可以看到,结果并不相同。所以PyTorch应该是采用了另外的实现方式,而这也是大部分教程没有交代的。
$$
H(x, class) = - log{\frac{e^{x_{class}}}{\sum_i{e^{x_i}}}} = - x_{class} + log{\sum_i{e^{x_i}}}
$$
代码如下:
1 | def cross_entropy(X, Y): |
如此,可以看到PyTorch的CrossEntropyLoss的真正计算过程。
More
事实上,我们还可以发现,nn.CrossEntropyLoss() 其实是 nn.logSoftmax() 和 nn.NLLLoss() 的整合版本。
$$
logSoftmax = log{\frac{e^x}{\sum_i{e^{x_i}}}}
$$
$$
NLLLoss(x, class) = -x[class]
$$
验证代码如下:
1 | import numpy as np |
结论
-
nn.CrossEntropyLoss() 的计算公式如下:
$$
H(x, class) = - log{\frac{e^{x_{class}}}{\sum_i{e^{x_i}}}} = - x_{class} + log{\sum_i{e^{x_i}}}
$$ -
nn.CrossEntropyLoss() 是 nn.logSoftmax() 和 nn.NLLLoss() 的整合。
- Blog Link: https://neo1989.net/Way2AI/Way2AI-CrossEntropyLoss/
- Copyright Declaration: 转载请声明出处。