语义分割中IOU损失(PyTorch实现)

1,273 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

语义分割中IOU损失(PyTorch实现)

语义分割常用loss介绍及pytorch实现_CaiDaoqing的博客-程序员秘密_pytorch 语义分割loss - 程序员秘密 (cxymm.net)

语义分割之dice loss深度分析(梯度可视化) - 知乎 (zhihu.com)

语义分割常用loss介绍及pytorch实现_CaiDaoqing的博客-CSDN博客_pytorch 语义分割loss

语义分割损失函数系列(2):IoU损失_spectrelwf的博客-CSDN博客_iou损失

IOU是

预测与真值的交集/预测与真值的并集预测与真值的交集/预测与真值的并集

语义分割中的IOU是:

预测与真值的交集上每个像素点之和/预测与真值的并集每个像素点之和预测与真值的交集上每个像素点之和/预测与真值的并集每个像素点之和

损失函数就是1IOU1-IOU或者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就是用来对部分像素加权的,上一种方法不好加权