【天池赛事】零基础入门语义分割-地表建筑物识别

  • Task1:赛题理解与 baseline(3 天)
    – 学习主题:理解赛题内容解题流程
    – 学习内容:赛题理解、数据读取、比赛 baseline 构建
    – 学习成果:比赛 baseline 提交

  • Task2:数据扩增方法(3 天)
    – 学习主题:语义分割任务中数据扩增方法
    – 学习内容:掌握语义分割任务中数据扩增方法的细节和使用
    – 学习成果:数据扩增方法的实践

  • Task3:网络模型结构发展(3 天)
    – 学习主题:掌握语义分割模型的发展脉络
    – 学习内容: FCN、 Unet、 DeepLab、 SegNet、 PSPNet
    – 学习成果:多种网络模型的搭建

  • Task4:评价函数与损失函数(3 天)
    – 学习主题:语义分割模型各种评价函数与损失函数
    – 学习内容: Dice、 IoU、 BCE、 Focal Loss、 Lovász-Softmax
    – 学习成果:评价/损失函数的实践

  • Task5:模型训练与验证(3 天)
    – 学习主题:数据划分方法
    – 学习内容:三种数据划分方法、模型调参过程
    – 学习成果:数据划分具体操作

  • Task6:分割模型模型集成(3 天)
    – 学习主题:语义分割模型集成方法
    – 学习内容: LookaHead、 SnapShot、 SWA、 TTA
    – 学习成果:模型集成思路

Task4:评价函数与损失函数

  • 1 学习目标
  • 2 TP TN FP FN
  • 3 Dice评价指标
    • Dice系数
    • Dice Loss
  • 4 IoU评价指标
  • 5 BCE损失函数
  • 6 Focal Loss
  • 7 Lovász-Softmax
  • 8 参考链接
  • 9 小结

本章主要介绍语义分割的评价函数和各类损失函数。

1 学习目标

• 掌握常见的评价函数和损失函数 Dice、IoU、BCE、Focal Loss、Lovász-Softmax;
• 掌握评价/损失函数的实践;

2 TP TN FP FN

在讲解语义分割中常用的评价函数和损失函数之前,先补充一 TP(真正例 true positive) ,TN(真反例 true negative) ,FP(假正例 false positive) ,FN(假反例 false negative) 的知识。在分类问题中,我们经常看到上述的表述方式,以二分类为例,我们可以将所有的样本预测结果分成 TP、TN、FP、FN 四类,并且每一类含有的样本数量之和为总样本数量,即 TP+FP+FN+TN= 总样本数量。其混淆矩阵如下:


上述的概念都是通过以预测结果的视角定义的,可以依据下面方式理解:
• 预测结果中的正例 在实际中是正例 的所有样本被称为真正例(TP)< 预测正确 >
• 预测结果中的正例 在实际中是反例 的所有样本被称为假正例(FP)< 预测错误 >
• 预测结果中的反例 在实际中是正例 的所有样本被称为假反例(FN)< 预测错误 >
• 预测结果中的反例 在实际中是反例 的所有样本被称为真反例(TN)< 预测正确 >

这里就不得不提及精确率(precision)和召回率(recall):

precision=TPTP+FPprecision={{TP}\over{TP+FP}}precision=TP+FPTP​

recall=TPTP+FNrecall={{TP}\over{TP+FN}}recall=TP+FNTP​

precision代表了预测的正例中真正的正例所占的比例,recall代表了真正的正例中被正确预测出来的比例。

转移到语义分割任务中,可以将语义分割看作是对每一个图像像素的分类问题。根据混淆矩阵中的定义,我们亦可以将特定像素所属的集合或区域划分为TP、TN、FP、FN四类。


以上面的图片为例,图中左子图中的人物区域(黄色像素集合)是我们真实标注的前景信息(target),其他区域(紫色像素集合)为背景信息。当经过预测之后,我们会得到的一张预测结果,图中右子图中的黄色像素为预测的前景(prediction),紫色像素为预测的背景区域。此时,我们便能够将预测结果分成4 个部分:

• 预测结果中的黄色无线区域 真实的前景 的所有像素集合被称为真正例(TP)< 预测正确 >
• 预测结果中的蓝色斜线区域 真实的背景 的所有像素集合被称为假正例(FP)< 预测错误 >
• 预测结果中的红色斜线区域 真实的前景 的所有像素集合被称为假反例(FN)< 预测错误 >
• 预测结果中的白色斜线区域 真实的背景 的所有像素集合被称为真反例(TN)< 预测正确 >

3 Dice评价指标

Dice系数

Dice 系数(Dice coefficient)是常见的评价分割效果的方法之一,同样也可以改写成损失函数用来度量 prediction 和 target 之间的距离。Dice 系数定义如下:

Dice(T,P)=2∣T∩P∣∣T∣∪∣P∣=2TPFP+2TP+FNDice(T,P)={{2|T\cap P|}\over{|T|\cup|P|}}={{2TP}\over{FP+2TP+FN}}Dice(T,P)=∣T∣∪∣P∣2∣T∩P∣​=FP+2TP+FN2TP​

式中:T 表示真实前景(target),P 表示预测前景(prediction)。Dice 系数取值范围为 [0, 1],其中值为1 时代表预测与真实完全一致。仔细观察,Dice 系数与分类评价指标中的 F1 score 很相似:

F1=2∗precision∗recallprecision+recall=2TPFP+2TP+FNF1={{2*precision*recall}\over{precision+recall}}={{2TP}\over{FP+2TP+FN}}F1=precision+recall2∗precision∗recall​=FP+2TP+FN2TP​

所以,Dice 系数不仅在直观上体现了 target 与 prediction 的相似程度,同时其本质上还隐含了精确率和召回率两个重要指标。

计算 Dice 时,将 |T ∩ P| 近似为 prediction 与 target 对应元素相乘再相加的结果。|T| 和 |P| 的计算直接进行简单的元素求和(也有一些做法是取平方求和),如下示例:

∣T∩P∣=[0.010.030.020.020.050.120.090.070.890.850.880.910.990.970.950.97]∗[0000000011111111]→[000000000.890.850.880.910.990.970.950.97]→sum7.41|T \cap P| = \begin{bmatrix} 0.01 & 0.03 & 0.02 & 0.02 \\ 0.05 & 0.12 & 0.09 & 0.07 \\ 0.89 & 0.85 & 0.88 & 0.91 \\ 0.99 & 0.97 & 0.95 & 0.97 \\ \end{bmatrix} * \begin{bmatrix} 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 \\ \end{bmatrix} \stackrel{}{\rightarrow} \begin{bmatrix} 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0.89 & 0.85 & 0.88 & 0.91 \\ 0.99 & 0.97 & 0.95 & 0.97 \\ \end{bmatrix} \stackrel{sum}{\rightarrow} 7.41 ∣T∩P∣=⎣⎢⎢⎡​0.010.050.890.99​0.030.120.850.97​0.020.090.880.95​0.020.070.910.97​⎦⎥⎥⎤​∗⎣⎢⎢⎡​0011​0011​0011​0011​⎦⎥⎥⎤​→⎣⎢⎢⎡​000.890.99​000.850.97​000.880.95​000.910.97​⎦⎥⎥⎤​→sum7.41

∣T∣=[0.010.030.020.020.050.120.090.070.890.850.880.910.990.970.950.97]→sum7.82|T| = \begin{bmatrix} 0.01 & 0.03 & 0.02 & 0.02 \\ 0.05 & 0.12 & 0.09 & 0.07 \\ 0.89 & 0.85 & 0.88 & 0.91 \\ 0.99 & 0.97 & 0.95 & 0.97 \\ \end{bmatrix} \stackrel{sum}{\rightarrow} 7.82 ∣T∣=⎣⎢⎢⎡​0.010.050.890.99​0.030.120.850.97​0.020.090.880.95​0.020.070.910.97​⎦⎥⎥⎤​→sum7.82

∣P∣=[0000000011111111]→sum8|P| = \begin{bmatrix} 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 \\ \end{bmatrix} \stackrel{sum}{\rightarrow} 8 ∣P∣=⎣⎢⎢⎡​0011​0011​0011​0011​⎦⎥⎥⎤​→sum8

Dice Loss

Dice Loss 是在 V-net 模型中被提出应用的,是通过 Dice 系数转变而来,其实为了能够实现最小化的损失函数,以方便模型训练,以 1 − Dice 的形式作为损失函数:

Loss=1−2∣T∩P∣∣T∣∪∣P∣Loss=1-{{2|T\cap P|}\over{|T|\cup|P|}}Loss=1−∣T∣∪∣P∣2∣T∩P∣​

在一些场合还可以添加上 Laplace smoothing 减少过拟合:

Loss=1−2∣T∩P∣+1∣T∣∪∣P∣+1Loss=1-{{2|T\cap P|+1}\over{|T|\cup|P|+1}}Loss=1−∣T∣∪∣P∣+12∣T∩P∣+1​

import numpy as npdef dice(output, target):'''计算Dice系数'''smooth=1e-6 # 避免0为除数intersection = (output*target).sum()return (2.*intersection+smooth)/(output.sum()+target.sum()+smooth)# 生成随机两个矩阵测试
output=np.random.randint(0,2,(3,3))
target=np.random.randint(0,2,(3,3))d=dice(output,target)
print(output)
print(target)
print(d)

4 IoU评价指标

IoU(intersection over union)指标就是常说的交并比,不仅在语义分割评价中经常被使用,在目标检测中也是常用的评价指标。顾名思义,交并比就是指 target 与 prediction 两者之间交集与并集的比值:

IoU=T∩UT∪U=TPFP+TP+FNIoU={{T\cap U}\over{T\cup U}}={{TP}\over{FP+TP+FN}}IoU=T∪UT∩U​=FP+TP+FNTP​

仍然以人物前景分割为例,如下图,其IoU的计算就是使用intersection/unionintersection / unionintersection/union。

targettargettarget

predictionpredictionprediction

Intersection(T∩P)Intersection(T\cap P)Intersection(T∩P)

Union(T∪P)Union(T\cup P)Union(T∪P)

import numpy as npdef iou_score(output, target):'''计算IoU指标'''intersetion=np.logical_and(target, output)union=np.logical_or(target,output)return np.sum(intersetion)/np.sum(union)# 生成随机两个矩阵测试
output=np.random.randint(0,2,(3,3))
target=np.random.randint(0,2,(3,3))d=iou_score(output,target)
print(output)
print(target)
print(d)

5 BCE损失函数

BCE损失函数(Binary Cross-Entropy Loss)是交叉熵损失函数(Cross-Entropy Loss)的一种特例,BCE Loss只应用在二分类任务中。针对分类问题,单样本的交叉熵损失为:
l(y,y^)=−∑i=1cyi⋅logy^il(\pmb y, \pmb{\hat y})=- \sum_{i=1}^{c}y_i \cdot log\hat y_i l(y​y​​y,y^​​y^​​​y^​)=−i=1∑c​yi​⋅logy^​i​
式中,y={y1,y2,...,yc,}\pmb{y}=\{y_1,y_2,...,y_c,\}y​y​​y={y1​,y2​,...,yc​,},其中yiy_iyi​是非0即1的数字,代表了是否属于第iii类,为真实值;y^i\hat y_iy^​i​代表属于第i类的概率,为预测值。可以看出,交叉熵损失考虑了多类别情况,针对每一种类别都求了损失。针对二分类问题,上述公式可以改写为:
l(y,y^)=−[y⋅logy^+(1−y)⋅log(1−y^)]l(y,\hat y)=-[y \cdot log\hat y +(1-y)\cdot log (1-\hat y)] l(y,y^​)=−[y⋅logy^​+(1−y)⋅log(1−y^​)]
式中,yyy为真实值,非1即0;y^\hat yy^​为所属此类的概率值,为预测值。这个公式也就是BCE损失函数,即二分类任务时的交叉熵损失。值得强调的是,公式中的y^\hat yy^​为概率分布形式,因此在使用BCE损失前,都应该将预测出来的结果转变成概率值,一般为sigmoid激活之后的输出。

在pytorch中,官方已经给出了BCE损失函数的API,免去了自己编写函数的痛苦:

在pytorch中,官方已经给出了BCE损失函数的API,免去了自己编写函数的痛苦:

torch.nn.BCELoss(weight: Optional[torch.Tensor] = None, size_average=None, reduce=None, reduction: str = 'mean')
ℓ(y,y^)=L={l1,…,lN}⊤,ln=−wn[yn⋅logy^n+(1−yn)⋅log(1−y^n)]ℓ(y,\hat y)=L=\{l_1,…,l_N \}^⊤,\ \ \ l_n=-w_n[y_n \cdot log\hat y_n +(1-y_n)\cdot log (1-\hat y_n)] ℓ(y,y^​)=L={l1​,…,lN​}⊤,   ln​=−wn​[yn​⋅logy^​n​+(1−yn​)⋅log(1−y^​n​)]
参数:
weight(Tensor)- 为每一批量下的loss添加一个权重,很少使用
size_average(bool)- 弃用中
reduce(bool)- 弃用中
reduction(str) - ‘none’ | ‘mean’ | ‘sum’:为代替上面的size_average和reduce而生。——为mean时返回的该批量样本loss的平均值;为sum时,返回的该批量样本loss之和

同时,pytorch还提供了已经结合了Sigmoid函数的BCE损失:torch.nn.BCEWithLogitsLoss(),相当于免去了实现进行Sigmoid激活的操作。

import torch
import torch.nn as nnbce=nn.BCELoss()
bce_sig=nn.BCEWithLogitsLoss()input=torch.randn(5,1,requires_grad=True)
target=torch.empty(5,1).random_(2)
pre=nn.Sigmoid()(input)loss_bce=bce(pre,target)
loss_bce_sig=bce_sig(input,target)print(loss_bce) # tensor(0.7031, grad_fn=<BinaryCrossEntropyBackward>)
print(loss_bce_sig) # tensor(0.7031, grad_fn=<BinaryCrossEntropyWithLogitsBackward>)

6 Focal Loss

Focal loss最初是出现在目标检测领域,主要是为了解决正负样本比例失调的问题。那么对于分割任务来说,如果存在数据不均衡的情况,也可以借用focal loss来进行缓解。Focal loss函数公式如下所示:

loss=−1N∑i=1N(αyi(1−pi)γlog⁡pi+(1−α)(1−yi)piγlog⁡(1−pi))loss = -\frac{1}{N} \sum_{i=1}^{N}\left(\alpha y_{i}\left(1-p_{i}\right)^{\gamma} \log p_{i}+(1-\alpha)\left(1-y_{i}\right) p_{i}^{\gamma} \log \left(1-p_{i}\right)\right) loss=−N1​i=1∑N​(αyi​(1−pi​)γlogpi​+(1−α)(1−yi​)piγ​log(1−pi​))

仔细观察就不难发现,它其实是BCE扩展而来,对比BCE其实就多了个
α(1−pi)γ和(1−α)piγ\alpha(1-p_{i})^{\gamma}和(1-\alpha)p_{i}^{\gamma} α(1−pi​)γ和(1−α)piγ​
为什么多了这个就能缓解正负样本不均衡的问题呢?见下图:


简单来说:ααα解决样本不平衡问题,γγγ解决样本难易问题。

也就是说,当数据不均衡时,可以根据比例设置合适的ααα,这个很好理解,为了能够使得正负样本得到的损失能够均衡,因此对loss前面加上一定的权重,其中负样本数量多,因此占用的权重可以设置的小一点;正样本数量少,就对正样本产生的损失的权重设的高一点。

那γ具体怎么起作用呢?以图中γ=5γ=5γ=5曲线为例,假设gtgtgt类别为1,当模型预测结果为1的概率ptp_tpt​比较大时,我们认为模型预测的比较准确,也就是说这个样本比较简单。而对于比较简单的样本,我们希望提供的loss小一些而让模型主要学习难一些的样本,也就是pt→1p_t→ 1pt​→1则loss接近于0,即不用再特别学习;当分类错误时,pt→0p_t → 0pt​→0则loss正常产生,继续学习。对比图中蓝色和绿色曲线,可以看到,γ值越大,当模型预测结果比较准确的时候能提供更小的loss,符合我们为简单样本降低loss的预期。

代码实现:

import torch
import torch.nn as nn
import torch.nn.functional as Fclass FocalLoss(nn.Module):def __init__(self,alpha=1,gamma=2,logits=False,reduce=True):super(FocalLoss,self).__init__()self.alpha=alphaself.gamma=gammaself.logits=logits # 如果BCE带logits,则损失函数在计算BCEloss之前,自动计算softmax/sigmoid将其映射到[0,1]self.reduce=reducedef forward(self,inputs,targets):if self.logits:BCE_loss=F.binary_cross_entropy_with_logits(inputs,targets,reduce=True)else:BCE_loss=F.binary_cross_entropy(inputs,targets,reduce=True)pt=torch.exp(-BCE_loss)F_loss=self.alpha*(1-pt)**self.gamma*BCE_lossif(self.reduce):return torch.mean(F_loss)else:return F_lossFL1 = FocalLoss(logits=False)
FL2 = FocalLoss(logits=True)inputs = torch.randn(5, 1, requires_grad=True)
targets = torch.empty(5, 1).random_(2)
pre = nn.Sigmoid()(inputs)f_loss_1 = FL1(pre, targets)
f_loss_2 = FL2(inputs, targets)print(f_loss_1) # tensor(0.1179, grad_fn=<MeanBackward0>)
print(f_loss_2) # tensor(0.1179, grad_fn=<MeanBackward0>)

7 Lovász-Softmax

IoU是评价分割模型分割结果质量的重要指标,因此很自然想到能否用1−IoU1-IoU1−IoU(即Jaccard loss)来做损失函数,但是它是一个离散的loss,不能直接求导,所以无法直接用来作为损失函数。为了克服这个离散的问题,可以采用lLovász extension将离散的Jaccard loss 变得连续,从而可以直接求导,使得其作为分割网络的loss function。Lovász-Softmax相比于交叉熵函数具有更好的效果。

论文地址:

paper on CVF open access

arxiv paper

首先明确定义,在语义分割任务中,给定真实像素标签向量y∗\pmb{y^*}y∗​y∗​​y∗和预测像素标签y^\pmb{\hat{y}}y^​​y^​​​y^​,则所属类别ccc的IoU(也称为Jaccard index)如下,其取值范围为[0,1][0,1][0,1],并规定0/0=10/0=10/0=1:
Jc(y∗,y^)=∣{y∗=c}∩{y^=c}∣∣{y∗=c}∪{y^=c}∣J_c(\pmb{y^*},\pmb{\hat{y}})=\frac{|\{\pmb{y^*}=c\} \cap \{\pmb{\hat{y}}=c\}|}{|\{\pmb{y^*}=c\} \cup \{\pmb{\hat{y}}=c\}|} Jc​(y∗​y∗​​y∗,y^​​y^​​​y^​)=∣{y∗​y∗​​y∗=c}∪{y^​​y^​​​y^​=c}∣∣{y∗​y∗​​y∗=c}∩{y^​​y^​​​y^​=c}∣​
则Jaccard loss为:
ΔJc(y∗,y^)=1−Jc(y∗,y^)\Delta_{J_c}(\pmb{y^*},\pmb{\hat{y}}) =1-J_c(\pmb{y^*},\pmb{\hat{y}}) ΔJc​​(y∗​y∗​​y∗,y^​​y^​​​y^​)=1−Jc​(y∗​y∗​​y∗,y^​​y^​​​y^​)
针对类别ccc,所有未被正确预测的像素集合定义为:
Mc(y∗,y^)={y∗=c,y^≠c}∪{{y∗≠c,y^=c}}M_c(\pmb{y^*},\pmb{\hat{y}})=\{\pmb{y^*}=c, \pmb{\hat{y}} \neq c\}\cup \{\{\pmb{y^*}\neq c, \pmb{\hat{y}} = c\}\} Mc​(y∗​y∗​​y∗,y^​​y^​​​y^​)={y∗​y∗​​y∗=c,y^​​y^​​​y^​​=c}∪{{y∗​y∗​​y∗​=c,y^​​y^​​​y^​=c}}
则可将Jaccard loss改写为关于McM_cMc​的子模集合函数(submodular set functions):
ΔJc:Mc∈{0,1}p↦∣Mc∣∣{y∗=c}∪Mc∣\Delta_{J_c}:M_c \in \{0,1\}^{p} \mapsto \frac{|M_c|}{|\{\pmb{y^*}=c\}\cup M_c|} ΔJc​​:Mc​∈{0,1}p↦∣{y∗​y∗​​y∗=c}∪Mc​∣∣Mc​∣​
方便理解,此处可以把{0,1}p\{0,1\}^p{0,1}p理解成如图像mask展开成离散一维向量的形式。

Lovász extension可以求解子模最小化问题,并且子模的Lovász extension是凸函数,可以高效实现最小化。在论文中作者对Δ\DeltaΔ(集合函数)和Δ‾\overline{\Delta}Δ(集合函数的Lovász extension)进行了定义,为不涉及过多概念以方便理解,此处不再过多讨论。我们可以将Δ‾\overline{\Delta}Δ理解为一个线性插值函数,可以将{0,1}p\{0,1\}^p{0,1}p这种离散向量连续化,主要是为了方便后续反向传播、求梯度等等。因此我们可以通过这个线性插值函数得到ΔJc\Delta_{J_c}ΔJc​​的Lovász extensionΔJc‾\overline{\Delta_{J_c}}ΔJc​​​。

在具有c(c>2)c(c>2)c(c>2)个类别的语义分割任务中,我们使用Softmax函数将模型的输出映射到概率分布形式,类似传统交叉熵损失函数所进行的操作:
pi(c)=eFi(c)∑c′∈CeFi(c′)∀i∈[1,p],∀c∈Cp_i(c)=\frac{e^{F_i(c)}}{\sum_{c^{'}\in C}e^{F_i(c^{'})}}  \forall i \in [1,p],\forall c \in C pi​(c)=∑c′∈C​eFi​(c′)eFi​(c)​  ∀i∈[1,p],∀c∈C
式中,pi(c)p_i(c)pi​(c)表示了像素iii所属类别ccc的概率。通过上式可以构建每个像素产生的误差m(c)m(c)m(c):
mi(c)={1−pi(c),ifc=yi∗pi(c),otherwisem_i(c)=\left \{ \begin{array}{c} 1-p_i(c),\ \ if \ \ c=y^{*}_{i} \\ p_i(c),\ \ \ \ \ \ \ otherwise \end{array} \right. mi​(c)={1−pi​(c),  if  c=yi∗​pi​(c),       otherwise​
可知,对于一张图像中所有像素则误差向量为m(c)∈{0,1}pm(c)\in \{0, 1\}^pm(c)∈{0,1}p,则可以建立关于ΔJc\Delta_{J_c}ΔJc​​的代理损失函数:
loss(p(c))=ΔJc‾(m(c))loss(p(c))=\overline{\Delta_{J_c}}(m(c)) loss(p(c))=ΔJc​​​(m(c))
当我们考虑整个数据集是,一般会使用mIoU进行度量,因此我们对上述损失也进行平均化处理,则定义的Lovász-Softmax损失函数为:
loss(p)=1∣C∣∑c∈CΔJc‾(m(c))loss(\pmb{p})=\frac{1}{|C|}\sum_{c\in C}\overline{\Delta_{J_c}}(m(c)) loss(p​p​​p)=∣C∣1​c∈C∑​ΔJc​​​(m(c))

代码实现

论文作者已经给出了Lovász-Softmax实现代码,并且有pytorch和tensorflow两种版本,并提供了使用demo。此处将针对多分类任务的Lovász-Softmax源码进行展示。

Lovász-Softmax实现链接:https://github.com/bermanmaxim/LovaszSoftmax

import torch
from torch.autograd import Variable
import torch.nn.functional as F
import numpy as np
try:from itertools import  ifilterfalse
except ImportError: # py3kfrom itertools import  filterfalse as ifilterfalse# --------------------------- MULTICLASS LOSSES ---------------------------
def lovasz_softmax(probas, labels, classes='present', per_image=False, ignore=None):"""Multi-class Lovasz-Softmax lossprobas: [B, C, H, W] Variable, class probabilities at each prediction (between 0 and 1).Interpreted as binary (sigmoid) output with outputs of size [B, H, W].labels: [B, H, W] Tensor, ground truth labels (between 0 and C - 1)classes: 'all' for all, 'present' for classes present in labels, or a list of classes to average.per_image: compute the loss per image instead of per batchignore: void class labels"""if per_image:loss = mean(lovasz_softmax_flat(*flatten_probas(prob.unsqueeze(0), lab.unsqueeze(0), ignore), classes=classes)for prob, lab in zip(probas, labels))else:loss = lovasz_softmax_flat(*flatten_probas(probas, labels, ignore), classes=classes)return lossdef lovasz_softmax_flat(probas, labels, classes='present'):"""Multi-class Lovasz-Softmax lossprobas: [P, C] Variable, class probabilities at each prediction (between 0 and 1)labels: [P] Tensor, ground truth labels (between 0 and C - 1)classes: 'all' for all, 'present' for classes present in labels, or a list of classes to average."""if probas.numel() == 0:# only void pixels, the gradients should be 0return probas * 0.C = probas.size(1)losses = []class_to_sum = list(range(C)) if classes in ['all', 'present'] else classesfor c in class_to_sum:fg = (labels == c).float() # foreground for class cif (classes is 'present' and fg.sum() == 0):continueif C == 1:if len(classes) > 1:raise ValueError('Sigmoid output possible only with 1 class')class_pred = probas[:, 0]else:class_pred = probas[:, c]errors = (Variable(fg) - class_pred).abs()errors_sorted, perm = torch.sort(errors, 0, descending=True)perm = perm.datafg_sorted = fg[perm]losses.append(torch.dot(errors_sorted, Variable(lovasz_grad(fg_sorted))))return mean(losses)def flatten_probas(probas, labels, ignore=None):"""Flattens predictions in the batch"""if probas.dim() == 3:# assumes output of a sigmoid layerB, H, W = probas.size()probas = probas.view(B, 1, H, W)B, C, H, W = probas.size()probas = probas.permute(0, 2, 3, 1).contiguous().view(-1, C)  # B * H * W, C = P, Clabels = labels.view(-1)if ignore is None:return probas, labelsvalid = (labels != ignore)vprobas = probas[valid.nonzero().squeeze()]vlabels = labels[valid]return vprobas, vlabelsdef xloss(logits, labels, ignore=None):"""Cross entropy loss"""return F.cross_entropy(logits, Variable(labels), ignore_index=255)# --------------------------- HELPER FUNCTIONS ---------------------------
def isnan(x):return x != xdef mean(l, ignore_nan=False, empty=0):"""nanmean compatible with generators."""l = iter(l)if ignore_nan:l = ifilterfalse(isnan, l)try:n = 1acc = next(l)except StopIteration:if empty == 'raise':raise ValueError('Empty mean')return emptyfor n, v in enumerate(l, 2):acc += vif n == 1:return accreturn acc / n

8 参考链接

语义分割的评价指标IoU

医学图像分割常用的损失函数

What is “Dice loss” for image segmentation?

pytorch loss-functions

Submodularity and the Lovász extension

9 小结

本章对各类评价指标进行介绍,并进行具体代码实践。

  • 理解各类评价函数的原理;
  • 对比各类损失函数原理,并进行具体实践;

【天池赛事】零基础入门语义分割-地表建筑物识别 Task4:评价函数与损失函数相关推荐

  1. 【天池赛事】零基础入门语义分割-地表建筑物识别 Task6:分割模型模型集成

    [天池赛事]零基础入门语义分割-地表建筑物识别 Task1:赛题理解与 baseline(3 天) – 学习主题:理解赛题内容解题流程 – 学习内容:赛题理解.数据读取.比赛 baseline 构建 ...

  2. 【天池赛事】零基础入门语义分割-地表建筑物识别 Task5:模型训练与验证

    [天池赛事]零基础入门语义分割-地表建筑物识别 Task1:赛题理解与 baseline(3 天) – 学习主题:理解赛题内容解题流程 – 学习内容:赛题理解.数据读取.比赛 baseline 构建 ...

  3. 【天池赛事】零基础入门语义分割-地表建筑物识别 Task3:网络模型结构发展

    [天池赛事]零基础入门语义分割-地表建筑物识别 Task1:赛题理解与 baseline(3 天) – 学习主题:理解赛题内容解题流程 – 学习内容:赛题理解.数据读取.比赛 baseline 构建 ...

  4. 【天池赛事】零基础入门语义分割-地表建筑物识别 Task2:数据扩增方法

    [天池赛事]零基础入门语义分割-地表建筑物识别 Task1:赛题理解与 baseline(3 天) – 学习主题:理解赛题内容解题流程 – 学习内容:赛题理解.数据读取.比赛 baseline 构建 ...

  5. 【天池赛事】零基础入门语义分割-地表建筑物识别 Task1:赛题理解与 baseline

    [天池赛事]零基础入门语义分割-地表建筑物识别 Task1:赛题理解与 baseline(3 天) – 学习主题:理解赛题内容解题流程 – 学习内容:赛题理解.数据读取.比赛 baseline 构建 ...

  6. 【天池赛事】零基础入门语义分割-地表建筑物识别

    https://tianchi.aliyun.com/competition/entrance/531872/introduction [天池赛事]零基础入门语义分割-地表建筑物识别:第一章 赛题及b ...

  7. 天池赛题解析:零基础入门语义分割-地表建筑物识别-CV语义分割实战(附部分代码)

    赛题内容 赛题背景 赛题以计算机视觉为背景,要求选手使用给定的航拍图像训练模型并完成地表建筑物识别任务.为更好的引导大家入门,我们为本赛题定制了学习方案和学习任务,具体包括语义分割的模型和具体的应用案 ...

  8. 零基础入门语义分割-地表建筑物识别 Task2 数据扩增 -学习笔记

    先给出task1的链接:task1-赛题理解 这一节进行数据扩增的试验 读取图片: train_mask = pd.read_csv('./data/train_mask.csv', sep='\t' ...

  9. 零基础入门语义分割——Task1 赛题理解

    文章目录 一.赛题数据 二.数据标签 三.评价指标 四.读取数据 比赛地址:零基础入门语义分割-地表建筑物识别 一.赛题数据 遥感技术已成为获取地表覆盖信息最为行之有效的手段,遥感技术已经成功应用于地 ...

最新文章

  1. dnslog在mysql在linux_DNSlog实现Mysql注入
  2. 把别人的Tcl/Tk代码加入到Go语言里12 游戏5 画图案?
  3. 关于apache kylin 安装32位linux办法
  4. 洛谷 U3357 C2-走楼梯
  5. java国王毒酒答案,换换脑子500桶酒国王用囚犯找毒酒答案-500桶酒其中1桶是毒酒找毒酒答案最新版【附公式详解】-东坡下载...
  6. 以太坊2.0客户端Prysm缺陷导致信标链节点共损失15ETH,即将发布更新
  7. www请求用到的Unescape
  8. java email 的格式_使用Java将电子邮件转换为原始格式
  9. 一代霸主的没落——诺基亚
  10. 【OpenGL】实例渲染示例——草地渲染
  11. ps cc 2014 智能切图
  12. 单片机c语言中断程序实验报告,单片机实验之外部中断应用实验
  13. 【Python百日基础系列】Day73 - dash实例:系统发育树
  14. 庆祝北大“如何制作MOOC”课程取得优秀成绩
  15. Nooi 一个Onedrive管理器
  16. 百丽时尚赴港IPO,持续释放品牌年轻化活力
  17. chrome浏览器91版本,Chrome中跨域请求无法携带Cookie的解决方案
  18. 移动医疗APP的渠道策略
  19. 企业官网中的“农家老宅”和“精品房”区别在哪?
  20. 岂无远道思亲泪,不及高堂念子心,堂上二老既活佛,何用灵山朝世尊。

热门文章

  1. 基于IPV6数据包分析(GNS3)
  2. 【BCFTOOLS】按样本拆分VCF文件
  3. 【LeetCode】002 Add Two Numbers
  4. Autofac - 属性注入
  5. MSSQLSERVER数据库- 递归查询例子
  6. python字典高级用法_Python 字典的高级用法
  7. python3库下载_下载安装Python第三方库的方法,最全方式,值得收藏
  8. rar 文件头crc版本_php实现rar文件的读取和解压
  9. 四川大学计算机网络_四川大学20考研情况
  10. PHP调用tushare,python调用tushare获取沪股通、深股通成份股数据