【问题标题】:Pytorch BCELoss function different outputs for same inputsPytorch BCELoss 为相同的输入提供不同的输出
【发布时间】:2021-05-28 01:46:19
【问题描述】:

我正在尝试使用 pytorch 的 BCELoss 函数来计算交叉熵损失,以解决二进制分类问题。在修补时,我发现了这种奇怪的行为。

from torch import nn
sigmoid = nn.Sigmoid()
loss = nn.BCELoss(reduction="sum")
target = torch.tensor([0., 1.])

input1 = torch.tensor([1., 1.], requires_grad=True)
input2 = sigmoid(torch.tensor([10., 10.], requires_grad=True))
print(input2) #tensor([1.0000, 1.0000], grad_fn=<SigmoidBackward>)

print(loss(input1, target)) #tensor(100., grad_fn=<BinaryCrossEntropyBackward>)
print(loss(input2, target)) #tensor(9.9996, grad_fn=<BinaryCrossEntropyBackward>)

既然 input1 和 input2 有相同的值,它不应该返回相同的损失值而不是 100 和 9.9996。正确的损失值应该是 100,因为我将 log(0) ~-infinity 相乘,它在 pytorch 中的上限为 -100。 https://pytorch.org/docs/stable/generated/torch.nn.BCELoss.html

这里发生了什么,我哪里出错了?

【问题讨论】:

    标签: python python-3.x deep-learning pytorch


    【解决方案1】:

    sigmoid(10) 不完全等于 1:

    >>> 1 / (1 + torch.exp(-torch.tensor(10.))).item()
    0.9999545833234493
    

    在你的情况下:

    >>> sigmoid(torch.tensor([10., 10.], requires_grad=True)).tolist()
    [0.9999545812606812, 0.9999545812606812]
    

    因此input1input2 不同:[1.0, 1.0] vs [0.9999545812606812, 0.9999545812606812]

    让我们手动计算 BCE:

    def bce(x, y):
        return - (y * torch.log(x) + (1 - y) * torch.log(1 - x)).item()
    
    
    # input1
    
    x1 = torch.tensor(1.)
    x2 = torch.tensor(1.)
    
    y1 = torch.tensor(0.)
    y2 = torch.tensor(1.)
    
    
    print("input1:", sum([bce(x1, y1), bce(x2, y2)]))
    
    
    # input2
    
    x1 = torch.tensor(0.9999545812606812)
    x2 = torch.tensor(0.9999545812606812)
    
    y1 = torch.tensor(0.)
    y2 = torch.tensor(1.)
    
    
    print("input2:", sum([bce(x1, y1), bce(x2, y2)]))
    
    
    input1: nan
    input2: 9.999631525119185
    

    对于input1,我们得到nan,但根据文档:

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

    这就是为什么我们在最终的pytorchBCE 输出中有100

    【讨论】:

    • 谢谢。但是这个 `input3 = torch.tensor([0.9999545812606812, 0.9999545812606812], requires_grad=True) print(loss(input, target))' 返回 100,我理解这个结果,但我如何得到问题中所问的 9.9996。跨度>
    • 你确定吗?在提供的代码中,您使用了inputprint(loss(input, target) 而不是input3
    • 我刚刚创建了一个带有 sigmoid 输出的新变量 input3 来测试您的答案中提到的损失函数并得到了可靠的结果。但是我在问题中的代码 sn-p 在尝试使用 input2 时仍然给出 9.9996。我是不是错过了什么。谢谢。
    猜你喜欢
    • 2021-09-09
    • 1970-01-01
    • 1970-01-01
    • 2020-12-28
    • 1970-01-01
    • 1970-01-01
    • 2020-11-15
    • 2017-03-15
    • 1970-01-01
    相关资源
    最近更新 更多