【发布时间】:2021-05-16 15:00:01
【问题描述】:
在paper引入焦点损失中,他们指出损失函数是这样制定的:
在哪里
我在另一个作者的 Github 页面上找到了它的实现,他在他们的paper 中使用了它。我在我拥有的一个分割问题数据集上尝试了这个函数,它似乎工作得很好。
下面是实现:
def binary_focal_loss(pred, truth, gamma=2., alpha=.25):
eps = 1e-8
pred = nn.Softmax(1)(pred)
truth = F.one_hot(truth, num_classes = pred.shape[1]).permute(0,3,1,2).contiguous()
pt_1 = torch.where(truth == 1, pred, torch.ones_like(pred))
pt_0 = torch.where(truth == 0, pred, torch.zeros_like(pred))
pt_1 = torch.clamp(pt_1, eps, 1. - eps)
pt_0 = torch.clamp(pt_0, eps, 1. - eps)
out1 = -torch.mean(alpha * torch.pow(1. - pt_1, gamma) * torch.log(pt_1))
out0 = -torch.mean((1 - alpha) * torch.pow(pt_0, gamma) * torch.log(1. - pt_0))
return out1 + out0
我不明白的部分是pt_0和pt_1的计算。我为自己创建了一个小例子来尝试弄清楚,但它仍然让我有点困惑。
# one hot encoded prediction tensor
pred = torch.tensor([
[
[.2, .7, .8], # probability
[.3, .5, .7], # of
[.2, .6, .5] # background class
],
[
[.8, .3, .2], # probability
[.7, .5, .3], # of
[.8, .4, .5] # class 1
]
])
# one-hot encoded ground truth labels
truth = torch.tensor([
[1, 0, 0],
[1, 1, 0],
[1, 0, 0]
])
truth = F.one_hot(truth, num_classes = 2).permute(2,0,1).contiguous()
print(truth)
# gives me:
# tensor([
# [
# [0, 1, 1],
# [0, 0, 1],
# [0, 1, 1]
# ],
# [
# [1, 0, 0],
# [1, 1, 0],
# [1, 0, 0]
# ]
# ])
pt_0 = torch.where(truth == 0, pred, torch.zeros_like(pred))
pt_1 = torch.where(truth == 1, pred, torch.ones_like(pred))
print(pt_0)
# gives me:
# tensor([[
# [0.2000, 0.0000, 0.0000],
# [0.3000, 0.5000, 0.0000],
# [0.2000, 0.0000, 0.0000]
# ],
# [
# [0.0000, 0.3000, 0.2000],
# [0.0000, 0.0000, 0.3000],
# [0.0000, 0.4000, 0.5000]
# ]
# ])
print(pt_1)
# gives me:
# tensor([[
# [1.0000, 0.7000, 0.8000],
# [1.0000, 1.0000, 0.7000],
# [1.0000, 0.6000, 0.5000]
# ],
# [
# [0.8000, 1.0000, 1.0000],
# [0.7000, 0.5000, 1.0000],
# [0.8000, 1.0000, 1.0000]
# ]
# ])
我不明白为什么在 pt_0 中我们在 torch.where 语句为假的地方放置了零,而在 pt_1 中我们放置了 1。从我对论文的理解来看,我会认为不是放置零或一,而是放置 1-p。
谁能帮我解释一下?
【问题讨论】:
标签: neural-network pytorch conv-neural-network probability loss-function