1 BCELoss简介
BCELoss:Binary Cross Entropy Loss,二值交叉熵损失,适用于0/1二分类。
计算公式是 “ -ylog(y^hat) - (1-y)log(1-y^hat) ”,其中y为gt,y_hat为预测值。这样,当gt为0的时候,公式前半部分为0,y^hat 需要尽可能为0才能使后半部分数值更小;当gt为1时,后半部分为0,y^hat 需要尽可能为1才能使前半部分的值更小,这样就达到了让y^hat尽量靠近gt的预期效果。
这要求输出必须在0-1之间,所以为了让网络的输出确保在0-1之间,一般都会加一个Sigmoid。更具体一点来说,使用BCELoss的话只需要网络输出一个节点即可,不像CE Loss(Cross Entropy Loss)那样,往往是有n_class个类就需要网络最终输出n_class个节点。
2 与Cross Entropy Loss的区别
分类任务中
CE因为需要用在多分类上,所以计算公式就变成了sum(-ylog(y^hat))。这个函数实际上只是在对相应gt=1的那个节点的值做约束,希望这一点的输出能尽量为1;而其他原本gt为0的节点因为y=0,在计算到sum中的时候无论其相应输出节点是多少都没有关系。
那这是不是意味着CE的公式还有漏洞呢?话虽这么说,但其实是因为我们忘记了CE之前还有Softmax这个函数,这个函数会让输入的n_class个节点中大的更大,小的更小,并且可以确保最终所有节点的输出的总和为1,这样一来只要对应gt=1的那个节点输出足够靠近1,其他的节点自然输出就会趋近于0了。
分割任务中
BCE和CE的另一个区别是,BCE只需要输出一个通道,而CE需要输出n_class个通道。
3 解释BCE并不是只能学习0或1的label
BCE虽然总是用来学习0/1分布,即二分类问题,但不是0/1两个数,只要在0~1之间的数也都能学习。原因从BCE的公式聊起:
4 pytorch中的BCELoss
torch.nn.BCELoss(input: Tensor, target: Tensor) -> Tensor
实例:
import torch
import torch.nn as nn
m = nn.Sigmoid()
loss = nn.BCELoss()
input = torch.randn((3, 3), requires_grad=True)
target = torch.empty(3, 3).random_(2)
output = loss(m(input), target)
output.backward()
print('input', input)
print('-----------------------------')
print('target', target)
print('-----------------------------')
print('m(input)', m(input))
print('-----------------------------')
print('output', output)
输出:
input tensor([[-0.5255, -0.9176, 0.1117],
[ 0.8469, -0.3685, -1.2900],
[ 1.1795, -2.0813, 1.8317]], requires_grad=True)
-----------------------------
target tensor([[1., 0., 0.],
[0., 1., 1.],
[0., 0., 1.]])
-----------------------------
m(input) tensor([[0.3716, 0.2855, 0.5279],
[0.6999, 0.4089, 0.2159],
[0.7649, 0.1109, 0.8620]], grad_fn=<SigmoidBackward0>)
-----------------------------
output tensor(0.8246, grad_fn=<BinaryCrossEntropyBackward0>)
把输入的数据先进行sigmod,然后再计算loss,应用时,通常还有个backward()
5 参考链接:
https://blog.csdn.net/weixin_37724529/article/details/107084970
https://www.cnblogs.com/dotman/p/13857843.html
https://zhuanlan.zhihu.com/p/108961272