一、损失函数
1.交叉熵损失 Cross Entorpy Loss
逐像素交叉熵损失是图像分割中最常用的损失函数。该损失函数分别检查每个像素,将类预测(softmax 或 sigmoid)与目标向量(one hot)进行比较。
1.1交叉熵。
关于样本集的两个概率分布p和q,设p为真实的分布,例如[1, 0, 0]表示当前文本属于第一类;q为拟合的分布,例如该文本的分布为[0.7, 0.2, 0.1]。
按照真实分布p来衡量识别一个样本所需的编码长度的期望,即平均编码长度(信息熵):
如果使用拟合分布q来表示来自真实分布p的编码长度的期望,即平均编码长度(交叉熵):
根据吉斯不等式,恒成立,当q为真实分布时取等,我们将由q得到的平均编码长度比由p得到的平均编码长度多出的bit数称为相对熵,也叫KL散度:
在机器学习的分类问题中,我们希望缩小模型预测和标签之间的差距,即KL散度越小越好,在这里由于KL散度中的项不变(在其他问题中未必),故在优化过程中只需要关注交叉熵就可以了,因此一般使用交叉熵作为损失函数。
1.2 二分类交叉熵
二分类网络模型的输出最后采用Sigmoid激活函数,输出一个通道。二分类交叉熵损失:
其中,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 多分类交叉熵
多分类任务中的交叉熵损失函数定义为:
其中是一个概率分布,每个元素
表示样本属于第
类的概率;
是样本的one-hot标签,当样本属于第
类时,
,否则
。
PyTorch提供了两个类来计算交叉熵,分别是torch.nn.CrossEntropyLoss() 和torch.nn.NLLLoss()。
torch.nn.CrossEntropyLoss()接收网络非softmax输出。令表示网络的输出(非softmax),则损失函数描述如下:
如果weight被指定,则,其中,
定义与应用如下:
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输出),令表示样本的对数似然估计,则该损失函数表述如下:
,其中
定义与应用如下:
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函数: ;softmax函数:
;
log_softmax:,加速运算,保持数值稳定,防止溢出。
2.加权交叉熵损失
带有权重的交叉熵损失函数,定义为:
在交叉熵损失的基础上给每一个类别添加一个权重参数,其中
为数据集的像素总书,
为数据集第
类像素数。即给数量较少的样本添加一个较大的权重,使得网络均衡学习样本的分布。有效地解决样本不均衡时的少量样本的训练问题。
3.Focal Loss
何凯明团队在RetinaNet论文中引入了Focal Loss来解决难易样本数量不平衡。One-Stage的目标检测器通常会产生10k数量级的框,但只有极少数是正样本,正负样本数量非常不平衡。
二分类Focal Loss:
多分类Focal Loss:
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]):
Dice Loss:
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 score5. IOU Loss
6.Tversky Loss
Tversky系数是Dice系数和 Jaccard 系数的一种推广。当设置α=β=0.5,此时Tversky系数就是Dice系数。而当设置α=β=1时,此时Tversky系数就是Jaccard系数。α和β分别控制假阴性和假阳性。通过调整α和β,可以控制假阳性和假阴性之间的平衡。
二、评价指标
1.执行时间(execution time)
2.内存占用(memory footprint)
3.Pixel Accuracy 像素精度
标记(分割)正确的像素占总像素的比例。
4.Mean Pixel Accuracy 平均像素精度
每个类内被正确分类的像素数的比例,求和之后再求平均
5.Mean IOU
计算真实值和预测值两个集合的交集和并集之比。这个比例可以变形为TP(交集)比上TP、FP、FN之和(并集)。即:mIOU=TP/(FP+FN-TP)。
6. requency Weighted Intersection over Union(FWIOU 频权交并比)
根据每个类出现的频率为其设置权重。
python 代码
















