本文已参与「新人创作礼」活动,一起开启掘金创作之路。
语义分割中IOU损失(PyTorch实现)
语义分割常用loss介绍及pytorch实现_CaiDaoqing的博客-程序员秘密_pytorch 语义分割loss - 程序员秘密 (cxymm.net)
语义分割之dice loss深度分析(梯度可视化) - 知乎 (zhihu.com)
语义分割常用loss介绍及pytorch实现_CaiDaoqing的博客-CSDN博客_pytorch 语义分割loss
IOU是
语义分割中的IOU是:
损失函数就是或者
首先是我在论文代码中遇到的一种实现方式:
class IoU_loss(torch.nn.Module):
def __init__(self):
super(IoU_loss, self).__init__()
def forward(self, pred, target):
b = pred.shape[0]
IoU = 0.0
for i in range(0, b):
#compute the IoU of the foreground
Iand1 = torch.sum(target[i, :, :, :]*pred[i, :, :, :])
Ior1 = torch.sum(target[i, :, :, :]) + torch.sum(pred[i, :, :, :])-Iand1
IoU1 = Iand1/(Ior1 + 1e-5)
#IoU loss is (1-IoU1)
IoU = IoU + (1-IoU1)
return IoU/b
这种方式是每张预测图像分别计算,在每张预测图中(注意输入的预测图要提前手动sigmoid进行激活):
第一步:预测值与真值相乘得到交集,然后求和得到交集的像素点之和
第二步:预测值像素点之和+真值像素点之和-交集像素点之和
第三步:交集/并集,不过分母加上1e-5,防止为0
第四步:1-IOU
最后,求所有预测图IOU损失的均值
第二篇论文代码看到的
def iou(pred, mask, epoch, epsilon=1)
pred = torch.sigmoid(pred)
inter = ((pred * mask) * weit).sum(dim=(2, 3))
union = ((pred + mask) * weit).sum(dim=(2, 3))
wiou = 1 - (inter + epsilon) / (union - inter + epsilon)
return wiou.mean()
这种方法是一次性计算所有预测图像的:
第一步:计算交集,预测图和真值相乘,然后乘weit权重,再对第二三维度求和,也就是图像高宽
第二步:计算并集(其实不是并集,多了一块交集),预测图+真值,再乘weit权重,再对第二三维度求和
第三步:计算iou损失,其中epsilon是1,是一个小的数,防止为0,不过我感觉这个不小了,所以我都是把epsilon替换成在分母加1e-5
weit就是用来对部分像素加权的,上一种方法不好加权