import torch
import torch.nn as nn
a = torch.tensor([0.1,0.3,0.6])
b = torch.tensor([0,0,1])
loss = nn.BCELoss(reduction='sum')
nn.BCELoss(a,b.float())
得到输出结果为tensor(0.9729)
,其中BCELoss的计算过程为:
- 首先这里的预测结果有3个,分别为(p1=0.1,p2=0.2,p3=0.6),对应的真实标签为(y1=0,y2=0,y3=1)而二值交叉熵的计算公式为:
−
y
∗
l
o
g
p
−
(
1
−
y
)
∗
l
o
g
(
1
−
p
)
-{y*logp-(1-y)*log(1-p)}
−y∗logp−(1−y)∗log(1−p),这里有3个预测值,我们将3个预测值分别代入二值交叉熵函数中,然后求和:
− { 1 ∗ l o g ( 0.9 ) + 1 ∗ l o g ( 0.7 ) + 1 ∗ l o g ( 0.6 ) } -\left\{1*log(0.9)+1*log(0.7)+1*log(0.6)\right\} −{1∗log(0.9)+1∗log(0.7)+1∗log(0.6)}
得到最终的结果为0.9728610833625495-math.log(0.6)-math.log(0.9)-math.log(0.7)
关于BCELoss中的weight参数,是对不同的样本使用不同的权重参数,而不是对于不同类别,我从网上得到了一个二类的FocalLoss函数,如下:
class FocalLossV1(nn.Module):
def __init__(self,
alpha=0.25,
gamma=2,
reduction='sum',):
super(FocalLossV1, self).__init__()
self.alpha = alpha
self.gamma = gamma
self.reduction = reduction
self.crit = nn.BCEWithLogitsLoss(reduction='none')
self.celoss = torch.nn.CrossEntropyLoss(reduction='none')
def forward(self, logits, label):
'''
args:
logits: tensor of shape (N, ...)
label: tensor of shape(N, ...)
'''
# compute loss
logits = logits.float() # use fp32 if logits is fp16
with torch.no_grad():
alpha = torch.empty_like(logits).fill_(1 - self.alpha)
alpha[label == 1] = self.alpha
ce_loss=(-(label * torch.log(logits)) - (
(1 - label) * torch.log(1 - logits)))
# ce_loss=(-(label * torch.log(torch.softmax(logits, dim=1))) - (
# (1 - label) * torch.log(1 - torch.softmax(logits, dim=1))))
pt = torch.where(label == 1, logits, 1 - logits)
# ce_loss = self.crit(logits, label)
loss = (alpha * torch.pow(1 - pt, self.gamma) * ce_loss)
if self.reduction == 'mean':
loss = loss.mean()
if self.reduction == 'sum':
loss = loss.sum()
return loss