PyTorch 中如何计算 BCELoss?[与数学实现相比的不同结果]

数据挖掘 Python 神经网络 损失函数 火炬
2022-02-14 14:13:09

我试图了解如何在 PyTorch 中计算二进制交叉熵。我在这里尝试了 PyTorch 文档中的相同代码,但与此函数的数学实现相比,我得到了不同的结果。

代码(与文档相比,我做了一些小改动):

import torch
import torch.nn as nn
m = nn.Sigmoid()
loss = nn.BCELoss()
input = torch.randn(1, requires_grad=True)
print(input)
print(m(input))
target = torch.empty(1).random_(2)
print(target)
output = loss(m(input), target)
print(output)
output.backward()
print(output)

上面代码的输出是: 在此处输入图像描述

BCELoss 的数学公式是:

output = -[target*log(our_value) + (1-target)*log(1-our_value)]

从上面的数学公式中,我应该得到 'output'=0.3215,'our_value'=0.4770 和 'target'=1。但是 PyTorch 显示“输出”=0.7403。

我还在这里找到了此函数的 C 代码,但公式几乎相同(只应添加非常小的 epsila,并且输出没有差异)。所以,对我来说仍然不清楚。

它是怎么来的?欢迎任何提示。

1个回答

查看BCELoss的文档

我们的解决方案是 BCELoss 将其日志函数输出钳制为大于或等于 -100。这样,我们总是可以有一个有限的损失值和一个线性后向方法。

如果您修改定义以包括它应该产生正确的结果:

def binary_cross_entropy(pred, y): 
    log_pred = torch.clamp(torch.log(pred), -100, 100)
    log_pred_rev = torch.clamp(torch.log(1-pred), -100, 100)
    return -(log_pred*y + (1-y)*log_pred_rev).sum()


a = torch.linspace(0, 1, 10)

w = np.array([F.binary_cross_entropy(x,torch.tensor(0.2)).item() for x in a])
q = np.array([binary_cross_entropy(x,torch.tensor(0.2)).item() for x in a])

print(w)
print(q)

[20.          0.53367138  0.501867    0.54409462  0.63241535  0.76630157 0.95998287  1.2535249   1.78133631 80.        ]
[20.          0.53367138  0.501867    0.54409462  0.63241535  0.76630157 0.95998287  1.2535249   1.78133631 80.        ]