一、损失函数

1.交叉熵损失 Cross Entorpy Loss

逐像素交叉熵损失是图像分割中最常用的损失函数。该损失函数分别检查每个像素,将类预测(softmax 或 sigmoid)与目标向量(one hot)进行比较。

1.1交叉熵。

关于样本集的两个概率分布p和q,设p为真实的分布,例如[1, 0, 0]表示当前文本属于第一类;q为拟合的分布,例如该文本的分布为[0.7, 0.2, 0.1]。

按照真实分布p来衡量识别一个样本所需的编码长度的期望,即平均编码长度(信息熵):
cyclegan pytorch 损失函数 deeplabv3+损失函数_二分类

如果使用拟合分布q来表示来自真实分布p的编码长度的期望,即平均编码长度(交叉熵):
cyclegan pytorch 损失函数 deeplabv3+损失函数_计算机视觉_02

根据吉斯不等式,cyclegan pytorch 损失函数 deeplabv3+损失函数_计算机视觉_03恒成立,当q为真实分布时取等,我们将由q得到的平均编码长度比由p得到的平均编码长度多出的bit数称为相对熵,也叫KL散度:
cyclegan pytorch 损失函数 deeplabv3+损失函数_深度学习_04

在机器学习的分类问题中,我们希望缩小模型预测和标签之间的差距,即KL散度越小越好,在这里由于KL散度中的cyclegan pytorch 损失函数 deeplabv3+损失函数_计算机视觉_05项不变(在其他问题中未必),故在优化过程中只需要关注交叉熵就可以了,因此一般使用交叉熵作为损失函数。

1.2 二分类交叉熵

二分类网络模型的输出最后采用Sigmoid激活函数,输出一个通道。二分类交叉熵损失:

cyclegan pytorch 损失函数 deeplabv3+损失函数_python_06

其中,y为标签,1表示正样本,0表示负样本。p表示样本预测为正样本的概率。

pytorch用于计算二分类交叉熵的类为torch.nn.BCELoss()。定义与应用如下:

torch.nn.BCELoss(
      weight=None,
      size_average=None,
      reduce=None,
      reduction='mean'
)

# 实际应用
import torch
import torch.nn as nn

model = nn.Conv2d(1, 1, 3, padding=1)
criterion = nn.BCELoss(reduction='mean')
x = torch.randn(1, 1, 16, 16)
y = torch.randint(0, 2, size=(1, 1, 16, 16)).type(torch.FloatTensor)
preds = nn.Sigmoid()(model(x))
loss = criterion(preds, y)
1.2 多分类交叉熵

多分类任务中的交叉熵损失函数定义为:

cyclegan pytorch 损失函数 deeplabv3+损失函数_二分类_07

其中cyclegan pytorch 损失函数 deeplabv3+损失函数_深度学习_08是一个概率分布,每个元素cyclegan pytorch 损失函数 deeplabv3+损失函数_python_09表示样本属于第cyclegan pytorch 损失函数 deeplabv3+损失函数_深度学习_10类的概率;cyclegan pytorch 损失函数 deeplabv3+损失函数_二分类_11是样本的one-hot标签,当样本属于第cyclegan pytorch 损失函数 deeplabv3+损失函数_深度学习_10类时,cyclegan pytorch 损失函数 deeplabv3+损失函数_二分类_13,否则cyclegan pytorch 损失函数 deeplabv3+损失函数_python_14

PyTorch提供了两个类来计算交叉熵,分别是torch.nn.CrossEntropyLoss() 和torch.nn.NLLLoss()。

torch.nn.CrossEntropyLoss()接收网络非softmax输出。令cyclegan pytorch 损失函数 deeplabv3+损失函数_python_15表示网络的输出(非softmax),则损失函数描述如下:
cyclegan pytorch 损失函数 deeplabv3+损失函数_损失函数_16
如果weight被指定,则
cyclegan pytorch 损失函数 deeplabv3+损失函数_深度学习_17,其中,cyclegan pytorch 损失函数 deeplabv3+损失函数_深度学习_18
定义与应用如下:

torch.nn.CrossEntropyLoss(
    weight=None,
    ignore_index=-100,
    reduction="mean",
)

#  实际应用
import torch
import torch.nn as nn
model = nn.Conv2d(1, 3, 3, padding=1)
criterion = nn.CrossEntropyLoss(weight=None,
                                ignore_index=-100,
                                reduction='mean')
x = torch.randn(1, 1, 16, 16)
y = torch.randint(0, 3, size=(1, 16, 16)) # pytorch的label是像素所在位置的值,故y.shape = [B, H, W]
logits = model(x) 
loss = criterion(logits, y)

torch.nn.NLLLoss()接收网络softmax输出,即每个样本类别的对数似然估计(softmax输出),令cyclegan pytorch 损失函数 deeplabv3+损失函数_计算机视觉_19表示样本的对数似然估计,则该损失函数表述如下:
cyclegan pytorch 损失函数 deeplabv3+损失函数_二分类_20,其中cyclegan pytorch 损失函数 deeplabv3+损失函数_深度学习_18

定义与应用如下:

torch.nn.NLLLoss(
    weight=None,
    ignore_index=-100,
    reduction="mean",
)
#实际应用
import torch
import torch.nn as nn
model = nn.Sequential(
    nn.Conv2d(1, 3, 3, padding=1),
    nn.LogSoftmax(dim=1)
)
criterion = nn.NLLLoss(weight=None,
    ignore_index=-100,
    reduction='mean')

x = torch.randn(1, 1, 16, 16)
y = torch.randint(0, 3, size=(1, 16, 16))

preds = model(x)  # (16, 3)
loss = criterion(preds, y)

另外,sigmoid函数: cyclegan pytorch 损失函数 deeplabv3+损失函数_python_22;softmax函数:cyclegan pytorch 损失函数 deeplabv3+损失函数_二分类_23

log_softmax:cyclegan pytorch 损失函数 deeplabv3+损失函数_计算机视觉_24加速运算,保持数值稳定,防止溢出

2.加权交叉熵损失

带有权重的交叉熵损失函数,定义为:
cyclegan pytorch 损失函数 deeplabv3+损失函数_python_25
在交叉熵损失的基础上给每一个类别添加一个权重参数cyclegan pytorch 损失函数 deeplabv3+损失函数_二分类_26,其中cyclegan pytorch 损失函数 deeplabv3+损失函数_计算机视觉_27为数据集的像素总书,cyclegan pytorch 损失函数 deeplabv3+损失函数_二分类_28为数据集第cyclegan pytorch 损失函数 deeplabv3+损失函数_深度学习_10类像素数。即给数量较少的样本添加一个较大的权重,使得网络均衡学习样本的分布。有效地解决样本不均衡时的少量样本的训练问题。

3.Focal Loss

何凯明团队在RetinaNet论文中引入了Focal Loss来解决难易样本数量不平衡。One-Stage的目标检测器通常会产生10k数量级的框,但只有极少数是正样本,正负样本数量非常不平衡。
二分类Focal Loss:
cyclegan pytorch 损失函数 deeplabv3+损失函数_计算机视觉_30

多分类Focal Loss:
cyclegan pytorch 损失函数 deeplabv3+损失函数_深度学习_31

pytorch代码:

import torch
import torch.nn as nn
import torch.nn.functional as F

class FocalLoss(nn.Module):
    def __init__(self, gamma=0, alpha=None, reduction=True):
        super(FocalLoss, self).__init__()
        self.gamma = gamma
        self.alpha = alpha
        if isinstance(alpha,(float,int)): self.alpha = torch.Tensor([alpha,1-alpha])
        if isinstance(alpha,list): self.alpha = torch.Tensor(alpha)
        self.reduction = reduction

    def forward(self, input, target):
        if input.dim()>2:
            input = input.view(input.size(0),input.size(1),-1)  # N,C,H,W => N,C,H*W
            input = input.transpose(1,2)    # N,C,H*W => N,H*W,C
            input = input.contiguous().view(-1,input.size(2))   # N,H*W,C => N*H*W,C
        target = target.view(-1,1)

        logpt = F.log_softmax(input, dim=1)
        logpt = logpt.gather(1,target)
        logpt = logpt.view(-1)
        pt = torch.Tensor(logpt.data.exp())

        if self.alpha is not None:
            if self.alpha.type()!=input.data.type():
                self.alpha = self.alpha.type_as(input.data)
            at = self.alpha.gather(0,target.data.view(-1))
            logpt = logpt * torch.Tensor(at)

        loss = -1 * (1-pt)**self.gamma * logpt
        if self.reduction: return loss.mean()
        else: return loss.sum()

if __name__ == '__main__':
    model = nn.Sequential(
        nn.Conv2d(1, 3, 3, padding=1),
    )
    criterion = FocalLoss(gamma=2, alpha=[0.2, 0.3, 0.5], reduction=True)
    x = torch.randn(1, 1, 16, 16)
    y = torch.randint(0, 3, size=(1, 16, 16))
    preds = model(x)
    loss1 = criterion(preds, y)

4.Dice Loss

Dice系数,是一种集合相似度度量函数,通常用于计算两个样本的相似度值(范围为[0,1]):
cyclegan pytorch 损失函数 deeplabv3+损失函数_损失函数_32

Dice Loss: cyclegan pytorch 损失函数 deeplabv3+损失函数_计算机视觉_33
import torch
import torch.nn as nn
import torch.nn.functional as F

class DiceLoss(nn.Module):
    def __init__(self):
        super(DiceLoss, self).__init__()
        self.epsilon = 1e-5
    
    def forward(self, predict, target):
        assert predict.size() == target.size(), "the size of predict and target must be equal."
        num = predict.size(0)
        
        pre = torch.sigmoid(predict).view(num, -1)
        tar = target.view(num, -1)
        
        intersection = (pre * tar).sum(-1).sum()  #利用预测值与标签相乘当作交集
        union = (pre + tar).sum(-1).sum()
        
        score = 1 - 2 * (intersection + self.epsilon) / (union + self.epsilon)
        
        return score

5. IOU Loss

cyclegan pytorch 损失函数 deeplabv3+损失函数_python_34

6.Tversky Loss

Tversky系数是Dice系数和 Jaccard 系数的一种推广。当设置α=β=0.5,此时Tversky系数就是Dice系数。而当设置α=β=1时,此时Tversky系数就是Jaccard系数。α和β分别控制假阴性和假阳性。通过调整α和β,可以控制假阳性和假阴性之间的平衡。

cyclegan pytorch 损失函数 deeplabv3+损失函数_计算机视觉_35

cyclegan pytorch 损失函数 deeplabv3+损失函数_python_36

二、评价指标

1.执行时间(execution time)

2.内存占用(memory footprint)

3.Pixel Accuracy 像素精度

标记(分割)正确的像素占总像素的比例。

cyclegan pytorch 损失函数 deeplabv3+损失函数_损失函数_37

4.Mean Pixel Accuracy 平均像素精度

每个类内被正确分类的像素数的比例,求和之后再求平均
cyclegan pytorch 损失函数 deeplabv3+损失函数_损失函数_38

5.Mean IOU

计算真实值和预测值两个集合的交集和并集之比。这个比例可以变形为TP(交集)比上TP、FP、FN之和(并集)。即:mIOU=TP/(FP+FN-TP)。

cyclegan pytorch 损失函数 deeplabv3+损失函数_二分类_39

6. requency Weighted Intersection over Union(FWIOU 频权交并比)

根据每个类出现的频率为其设置权重。
cyclegan pytorch 损失函数 deeplabv3+损失函数_深度学习_40

python 代码