前言

前两天介绍了一下Contrastive Loss,Triplet Loss以及Center Loss。今天正好是周六,时间充分一点我就来大概盘点一下语义分割的常见Loss,希望能为大家训练语义分割网络的时候提供一些关于Loss方面的知识。此文只为抛转引玉,一些Loss笔者暂时也没有进行试验,之后做了实验有了实验结果会继续更新。

交叉熵Loss

L = − ∑ c = 1 M y c l o g ( p c ) L=-\sum_{c=1}^My_clog(p_c) L=−∑c=1M​yc​log(pc​)

其中, M M M表示类别数, y c y_c yc​是一个one-hot向量,元素只有 0 0 0和 1 1 1两种取值,如果该类别和样本的类别相同就取 1 1 1,否则取 0 0 0,至于 P c P_c Pc​表示预测样本属于 c c c的概率。

当类别数 M M M等于 2 2 2的时候,这个损失就是二元交叉熵 L o s s Loss Loss,在Pytorch中提供了一个单独的实现。

交叉熵Loss可以用在大多数语义分割场景中,但它有一个明显的缺点,那就是对于只用分割前景和背景的时候,当前景像素的数量远远小于背景像素的数量时,即 y = 0 y=0 y=0的数量远大于 y = 1 y=1 y=1的数量,损失函数中 y = 0 y=0 y=0的成分就会占据主导,使得模型严重偏向背景,导致效果不好。

代码实现如下:

#二值交叉熵,这里输入要经过sigmoid处理
import torch
import torch.nn as nn
import torch.nn.functional as F
nn.BCELoss(F.sigmoid(input), target)
#多分类交叉熵, 用这个 loss 前面不需要加 Softmax 层
nn.CrossEntropyLoss(input, target)

带权交叉熵 Loss

带权重的交叉熵Loss,公式为:

L = − ∑ c = 1 M w c y c l o g ( p c ) L=-\sum_{c=1}^Mw_cy_clog(p_c) L=−∑c=1M​wc​yc​log(pc​)

可以看到只是在交叉熵Loss的基础上为每一个类别添加了一个权重参数,其中 w c w_c wc​的计算公式为:
w c = N − N c N w_c=\frac{N-N_c}{N} wc​=NN−Nc​​
其中 N N N表示总的像素个数,而 N c N_c Nc​表示GT类别为 c c c的像素个数。这样相比于原始的交叉熵Loss,在样本数量不均衡的情况下可以获得更好的效果。

Focal Loss

何凯明团队在RetinaNet论文中引入了Focal Loss来解决难易样本数量不平衡,我们来回顾一下。
我们知道,One-Stage的目标检测器通常会产生10k数量级的框,但只有极少数是正样本,正负样本数量非常不平衡。我们在计算分类的时候常用的损失——交叉熵的公式如下:


为了解决正负样本数量不平衡的问题,我们经常在二元交叉熵损失前面加一个参数 α \alpha α,即:

虽然 α \alpha α平衡了正负样本的数量,但实际上,目标检测中大量的候选目标都是易分样本。这些样本的损失很低,但是由于数量极不平衡,易分样本的数量相对来讲太多,最终主导了总的损失。

因此,这篇论文认为易分样本(即,置信度高的样本)对模型的提升效果非常小,模型应该主要关注与那些难分样本 。所以Focal Loss横空出世了。一个简单的想法就是只要我们将高置信度样本的损失降低一些就好了吧?
也即是下面的公式:
我们取 γ \gamma γ等于2来感受一下,如果 p = 0.9 p=0.9 p=0.9,那么, ( 1 − 0.9 ) 2 = 0.001 (1-0.9)^2=0.001 (1−0.9)2=0.001,损失降低了1000倍。最终Focal Loss还结合了公式(2),这很好理解,公式(3)解决了难易样本的不平衡,公式(2)解决了正负样本的不平衡,将公式(2)与(3)结合使用,同时解决正负难易2个问题!所以最终Focal Loss的形式如下:

下面这张图展示了Focal Loss取不同的 λ \lambda λ时的损失函数下降。

实验结果展示,当 γ = 2 \gamma=2 γ=2, α = 0.75 \alpha=0.75 α=0.75时,效果最好,这样损失函数训练的过程中关注的样本优先级就是正难>负难>正易>负易了。

虽然在RetinaNet中 λ \lambda λ取 2 2 2是最好的,但是不代表这个参数在我们的分割任务和其他样本上是最好的,我们需要手动调整这个参数,另外Focal Loss在分割任务上似乎是只适合于二分类的情况

Focal Loss的Pytorch代码实现如下:

class FocalLoss(nn.Module):def __init__(self, gamma=0, alpha=None, size_average=True):super(FocalLoss, self).__init__()self.gamma = gammaself.alpha = alphaif isinstance(alpha,(float,int,long)): self.alpha = torch.Tensor([alpha,1-alpha])if isinstance(alpha,list): self.alpha = torch.Tensor(alpha)self.size_average = size_averagedef 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*Winput = input.transpose(1,2)    # N,C,H*W => N,H*W,Cinput = input.contiguous().view(-1,input.size(2))   # N,H*W,C => N*H*W,Ctarget = target.view(-1,1)logpt = F.log_softmax(input)logpt = logpt.gather(1,target)logpt = logpt.view(-1)pt = Variable(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 * Variable(at)loss = -1 * (1-pt)**self.gamma * logptif self.size_average: return loss.mean()else: return loss.sum()

Dice Loss

  • Dice系数:根据 Lee Raymond Dice[1]命令,是用来度量集合相似度的度量函数,通常用于计算两个样本之间的像素,公式如下:
    s = 2 ∣ X ⋂ Y ∣ ∣ X ∣ + ∣ Y ∣ s=\frac{2|X\bigcap Y|}{|X|+|Y|} s=∣X∣+∣Y∣2∣X⋂Y∣​
    分子中之所以有一个系数2是因为分母中有重复计算 X X X和 Y Y Y的原因,最后 s s s的取值范围是 [ 0 , 1 ] [0,1] [0,1]。而针对我们的分割任务来说, X X X表示的就是Ground Truth分割图像,而Y代表的就是预测的分割图像。这里可能需要再讲一下,其实 s s s除了上面那种形式还可以写成:
    s = 2 T P 2 T P + F N + F P s=\frac{2TP}{2TP+FN+FP} s=2TP+FN+FP2TP​
    其中 T P , F P , F N TP,FP,FN TP,FP,FN分别代表真阳性,假阳性,假阴性的像素个数。
  • Dice Loss:公式定义为 :
    l o s s = 1 − 2 ∣ X ⋂ Y ∣ ∣ X ∣ + ∣ Y ∣ loss = 1 - \frac{2|X\bigcap Y|}{|X|+|Y|} loss=1−∣X∣+∣Y∣2∣X⋂Y∣​
    Dice Loss使用与样本极度不均衡的情况,如果一般情况下使用Dice Loss会回反向传播有不利的影响,使得训练不稳定。
  • 训练分割网络,例如FCN,UNet是选择交叉熵Loss还是选择Dice Loss?
    • 假设我们用 p p p来表示预测值,而 t t t来表示真实标签值,那么交叉熵损失关于 p p p的梯度形式类似于 p − t p-t p−t(我会在文后给出推导),而Dice Loss的值是 1 − 2 p t p 2 + t 2 1- \frac{2pt}{p^2+t^2} 1−p2+t22pt​或 1 − 2 p t p + t 1 - \frac{2pt}{p+t} 1−p+t2pt​,其关于 p p p的梯度形式为 2 t 2 ( p + t ) 2 \frac{2t^2}{(p+t)^2} (p+t)22t2​或 2 t ( t 2 − p 2 ) ( p 2 + t 2 ) 2 \frac{2t(t^2-p^2)}{(p^2+t^2)^2} (p2+t2)22t(t2−p2)​,可以看到在极端情况下即 p p p和 t t t都很小的时候,计算得到的梯度值可能会非常大,即会导致训练十分不稳定。
    • 另外一种解决类别不平衡的方法是简单的对每一个类别根据赋予不同的权重因子(如对数量少的类别赋予较大的权重因子),使得样本数量不均衡问题得到缓解(上面已经介绍过了,就是带权重的交叉熵Loss)。
    • 这两种处理方式,哪种更好,还是建议自己针对自己的数据做一个实验。
  • 代码实现:
import torch.nn as nn
import torch.nn.functional as Fclass SoftDiceLoss(nn.Module):def __init__(self, weight=None, size_average=True):super(SoftDiceLoss, self).__init__()def forward(self, logits, targets):num = targets.size(0)// 为了防止除0的发生smooth = 1probs = F.sigmoid(logits)m1 = probs.view(num, -1)m2 = targets.view(num, -1)intersection = (m1 * m2)score = 2. * (intersection.sum(1) + smooth) / (m1.sum(1) + m2.sum(1) + smooth)score = 1 - score.sum() / numreturn score

IOU Loss

IOU Loss和Dice Loss一样属于metric learning的衡量方式,公式定义如下:

L = 1 − A ⋂ B A ⋃ B L = 1 - \frac{A\bigcap B}{A \bigcup B} L=1−A⋃BA⋂B​
它和Dice Loss一样仍然存在训练过程不稳定的问题,IOU Loss在分割任务中应该是不怎么用的,如果你要试试的话代码实现非常简单,在上面Dice Loss的基础上改一下分母部分即可,不再赘述了。我们可以看一下将IOU loss应用到FCN上在VOC 2010上的实验结果:


可以看到IOU Loss是对大多数类别的分割结果有一定改善的,但是对Person类却性能反而下降了。

Tversky Loss

论文地址为:https://arxiv.org/pdf/1706.05721.pdf。实际上Dice Loss只是Tversky loss的一种特殊形式而已,我们先来看一下Tversky系数的定义,它是Dice系数和Jaccard系数(就是IOU系数,即 A ⋂ B A ⋃ B \frac{A\bigcap B}{A \bigcup B} A⋃BA⋂B​)的广义系数,公式为:
T ( A , B ) = A ⋂ B A ⋂ B + α ∣ A − B ∣ + β ∣ B − A ∣ T(A,B)=\frac{A\bigcap B}{A\bigcap B+\alpha |A-B|+\beta |B-A|} T(A,B)=A⋂B+α∣A−B∣+β∣B−A∣A⋂B​
这里A表示预测值而B表示真实值。当 α \alpha α和 β \beta β均为 0.5 0.5 0.5的时候,这个公式就是Dice系数,当 α \alpha α和 β \beta β均为 1 1 1的时候,这个公式就是Jaccard系数。其中 ∣ A − B ∣ |A-B| ∣A−B∣代表FP(假阳性), ∣ B − A ∣ |B-A| ∣B−A∣代表FN(假阴性),通过调整 α \alpha α和 β \beta β这两个超参数可以控制这两者之间的权衡,进而影响召回率等指标。下表展示了对FCN使用Tversky Loss进行病灶分割,并且取不同的 α \alpha α和 β \beta β参数获得的结果,其中Sensitivity代表召回率Recall,而Specificity表示准确率Precision:

在极小的病灶下的分割效果图如下:


而在较大的病灶下的分割效果图如下:

Keras代码实现如下:


def tversky(y_true, y_pred):y_true_pos = K.flatten(y_true)y_pred_pos = K.flatten(y_pred)true_pos = K.sum(y_true_pos * y_pred_pos)false_neg = K.sum(y_true_pos * (1-y_pred_pos))false_pos = K.sum((1-y_true_pos)*y_pred_pos)alpha = 0.7return (true_pos + smooth)/(true_pos + alpha*false_neg + (1-alpha)*false_pos + smooth)def tversky_loss(y_true, y_pred):return 1 - tversky(y_true,y_pred)

Generalized Dice loss

论文原文全程为:Generalized Overlap Measures for Evaluation and Validation in Medical Image Analysis
刚才分析过Dice Loss对小目标的预测是十分不利的,因为一旦小目标有部分像素预测错误,就可能会引起Dice系数大幅度波动,导致梯度变化大训练不稳定。另外从上面的代码实现可以发现,Dice Loss针对的是某一个特定类别的分割的损失。当类似于病灶分割有多个场景的时候一般都会使用多个Dice Loss,所以Generalized Dice loss就是将多个类别的Dice Loss进行整合,使用一个指标作为分割结果的量化指标。GDL Loss在类别数为2时公式如下:
G D L = 1 − 2 ∑ l = 1 2 w l ∑ n r l n p l n ∑ l = 1 2 w l ∑ n r l n + p l n GDL=1-2\frac{\sum_{l=1}^2w_l\sum_nr_{ln}p_{ln}}{\sum_{l=1}^2w_l\sum_nr_{ln}+p_{ln}} GDL=1−2∑l=12​wl​∑n​rln​+pln​∑l=12​wl​∑n​rln​pln​​
其中 r l n r_{ln} rln​表示类别 l l l在第 n n n个位置的真实像素类别,而 p l n p_{ln} pln​表示相应的预测概率值, w l w_l wl​表示每个类别的权重。 w l w_l wl​的公式为:
w l = 1 ∑ i = 1 n r l n 2 w_l=\frac{1}{{\sum_{i=1}^nr_{ln}}^2} wl​=∑i=1n​rln​21​。

Keras代码实现:

def generalized_dice_coeff(y_true, y_pred):Ncl = y_pred.shape[-1]w = K.zeros(shape=(Ncl,))w = K.sum(y_true, axis=(0,1,2))w = 1/(w**2+0.000001)# Compute gen dice coef:numerator = y_true*y_prednumerator = w*K.sum(numerator,(0,1,2,3))numerator = K.sum(numerator)denominator = y_true+y_preddenominator = w*K.sum(denominator,(0,1,2,3))denominator = K.sum(denominator)gen_dice_coef = 2*numerator/denominatorreturn gen_dice_coef
def generalized_dice_loss(y_true, y_pred):return 1 - generalized_dice_coeff(y_true, y_pred)

BCE + Dice Loss

即将BCE Loss和Dice Loss进行组合,在数据较为均衡的情况下有所改善,但是在数据极度不均衡的情况下交叉熵Loss会在迭代几个Epoch之后远远小于Dice Loss,这个组合Loss会退化为Dice Loss。

Focal Loss + Dice Loss

这个Loss的组合应该最早见于腾讯医疗AI实验室2018年在《Medical Physics》上发表的这篇论文:https://arxiv.org/pdf/1808.05238.pdf。论文提出了使用Focal Loss和Dice Loss来处理小器官的分割问题。公式如下:


其中 T P p ( c ) TP_p(c) TPp​(c), F N p ( c ) FN_p(c) FNp​(c), F P p ( c ) FP_p(c) FPp​(c)分别表示对于类别c的真阳性,假阴性,假阳性。可以看到这里使用Focal Loss的时候,里面的两个参数 γ \gamma γ直接用对于类别c的正样本像素个数来代替。具体实验细节和效果可以去看看原论文。

Exponential Logarithmic loss

这个Loss是MICCAI 2018的论文3D Segmentation with Exponential LogarithmicLoss for Highly Unbalanced Object Sizes提出来的,论文地址为:https://arxiv.org/abs/1809.00076。这个Loss结合了Focal Loss以及Dice loss。公式如下:

这里增加了两个参数权重分别为 w D i c e w_{Dice} wDice​和 w C r o s s w_{Cross} wCross​,而 L D i c e L_{Dice} LDice​为指数log Dice损失, L C r o s s L_{Cross} LCross​为指数交叉熵损失。公式如下:


其中, x x x表示像素位置, i i i表示类别标签, l l l表示位置 x x x处的ground truth类别, p i ( x ) p_i(x) pi​(x)表示经过softmax操作之后的概率值。其中:
w l = ( ∑ k f k f l ) 0.5 w_l=(\frac{\sum_kf_k}{f_l})^{0.5} wl​=(fl​∑k​fk​​)0.5
其中 f k f_k fk​表示标签 k k k出现的频率,这个参数可以减小出现频率较高的类别权重。 γ D i c e \gamma Dice γDice和 γ C r o s s \gamma Cross γCross可以提升函数的非线性,如Figure2所示:

Lovasz-Softmax Loss

这是今天要介绍的最后一个Loss,Kaggle神器。这篇论文是CVPR 2018的,原地址为:https://arxiv.org/pdf/1705.08790.pdf。对原理感兴趣可以去看一下论文,这个损失是对Jaccard(IOU) Loss进行Lovaze扩展,表现更好。因为这篇文章的目的只是简单盘点一下,就不再仔细介绍这个Loss了。之后可能会单独介绍一下这个Loss,论文的官方源码见附录,使用其实不是太难。

补充(Softmax梯度计算)

在介绍Dice Loss的时候留了一个问题,交叉熵的梯度形式推导,这里给一下推导。

(1)softmax函数
\quad 首先再来明确一下softmax函数,一般softmax函数是用来做分类任务的输出层。softmax的形式为:
S i = e z i ∑ k e z k S_i = \frac{e^{z_i}}{\sum_ke^{z_k}} Si​=∑k​ezk​ezi​​
其中 S i S_i Si​表示的是第i个神经元的输出,接下来我们定义一个有多个输入,一个输出的神经元。神经元的输出为
z i = ∑ i j x i j + b z_i = \sum_{ij}x_{ij}+b zi​=∑ij​xij​+b
其中 w i j w_{ij} wij​是第 i i i个神经元的第 j j j个权重,b是偏移值. z i z_i zi​表示网络的第 i i i个输出。给这个输出加上一个softmax函数,可以写成:
a i = e z i ∑ k e z k a_i = \frac{e^{z_i}}{\sum_ke^{z_k}} ai​=∑k​ezk​ezi​​,
其中 a i a_i ai​表示softmax函数的第i个输出值。这个过程可以用下图表示:

(2)损失函数
softmax的损失函数一般是选择交叉熵损失函数,交叉熵函数形式为:
C = − ∑ i y i l n a i C=-\sum_i{y_i lna_i} C=−∑i​yi​lnai​
其中y_i表示真实的标签值
(3)需要用到的高数的求导公式

c'=0(c为常数)
(x^a)'=ax^(a-1),a为常数且a≠0
(a^x)'=a^xlna
(e^x)'=e^x
(logax)'=1/(xlna),a>0且 a≠1
(lnx)'=1/x
(sinx)'=cosx
(cosx)'=-sinx
(tanx)'=(secx)^2
(secx)'=secxtanx
(cotx)'=-(cscx)^2
(cscx)'=-csxcotx
(arcsinx)'=1/√(1-x^2)
(arccosx)'=-1/√(1-x^2)
(arctanx)'=1/(1+x^2)
(arccotx)'=-1/(1+x^2)
(shx)'=chx
(chx)'=shx
(uv)'=uv'+u'v
(u+v)'=u'+v'
(u/)'=(u'v-uv')/^2

(3)进行推导
我们需要求的是loss对于神经元输出 z i z_i zi​的梯度,求出梯度后才可以反向传播,即是求:
∂ C ∂ z i \frac{\partial C}{\partial z_i} ∂zi​∂C​, 根据链式法则(也就是复合函数求导法则) ∂ C ∂ a j ∂ a j ∂ z i \frac{\partial C}{\partial a_j}\frac{\partial a_j}{\partial z_i} ∂aj​∂C​∂zi​∂aj​​,初学的时候这个公式理解了很久,为什么这里是 a j a_j aj​而不是 a i a_i ai​呢?这里我们回忆一下softmax的公示,分母部分包含了所有神经元的输出,所以对于所有输出非i的输出中也包含了 z i z_i zi​,所以所有的a都要参与计算,之后我们会看到计算需要分为 i = j i=j i=j和 i ≠ j i \neq j i​=j两种情况分别求导数。
首先来求前半部分:
∂ C ∂ a j = − ∑ j y i l n a j ∂ a j = − ∑ j y j 1 a j \frac{\partial C}{ \partial a_j} = \frac{-\sum_jy_ilna_j}{\partial a_j} = -\sum_jy_j\frac{1}{a_j} ∂aj​∂C​=∂aj​−∑j​yi​lnaj​​=−∑j​yj​aj​1​
接下来求第二部分的导数:

  • 如果 i = j i=j i=j, ∂ a i ∂ z i = ∂ ( e z i ∑ k e z k ) ∂ z i = ∑ k e z k e z i − ( e z i ) 2 ( ∑ k e z k ) 2 = ( e i z ∑ k e z k ) ( 1 − e z i ∑ k e z k ) = a i ( 1 − a i ) \frac{\partial a_i}{\partial z_i} = \frac{\partial(\frac{e^{z_i}}{\sum_ke^{z_k}})}{\partial z_i}=\frac{\sum_ke^{z_k}e^{z_i}-(e^{z_i})^2}{(\sum_ke^{z_k})^2}=(\frac{e^z_i}{\sum_ke^{z_k}})(1 - \frac{e^{z_i}}{\sum_ke^{z_k}})=a_i(1-a_i) ∂zi​∂ai​​=∂zi​∂(∑k​ezk​ezi​​)​=(∑k​ezk​)2∑k​ezk​ezi​−(ezi​)2​=(∑k​ezk​eiz​​)(1−∑k​ezk​ezi​​)=ai​(1−ai​)
  • 如果 i ≠ j i \neq j i​=j, ∂ a i ∂ z i = ∂ e z j ∑ k e z k ∂ z i = − e z j ( 1 ∑ k e k z ) 2 e z i = − a i a j \frac{\partial a_i}{\partial z_i}=\frac{\partial\frac{e^{z_j}}{\sum_ke^{z_k}}}{\partial z_i} = -e^{z_j}(\frac{1}{\sum_ke^z_k})^2e^{z_i}=-a_ia_j ∂zi​∂ai​​=∂zi​∂∑k​ezk​ezj​​​=−ezj​(∑k​ekz​1​)2ezi​=−ai​aj​。

接下来把上面的组合之后得到:
∂ C ∂ z i \frac{\partial C}{\partial z_i} ∂zi​∂C​
= ( − ∑ j y j 1 a j ) ∂ a j ∂ z i =(-\sum_{j}y_j\frac{1}{a_j})\frac{\partial a_j}{\partial z_i} =(−∑j​yj​aj​1​)∂zi​∂aj​​
= − y i a i a i ( 1 − a i ) + ∑ j ≠ i y j a j a i a j =-\frac{y_i}{a_i}a_i(1-a_i)+\sum_{j \neq i}\frac{y_j}{a_j}a_ia_j =−ai​yi​​ai​(1−ai​)+∑j​=i​aj​yj​​ai​aj​
= − y i + y i a i + ∑ j ≠ i y j a i =-y_i+y_ia_i+\sum_{j \neq i}\frac{y_j}a_i =−yi​+yi​ai​+∑j​=i​ayj​​i​
= − y i + a i ∑ j y j =-y_i+a_i\sum_{j}y_j =−yi​+ai​∑j​yj​。
推导完成!
(4)对于分类问题来说,我们给定的结果 y i y_i yi​最终只有一个类别是1,其他是0,因此对于分类问题,梯度等于:
∂ C ∂ z i = a i − y i \frac{\partial C}{\partial z_i}=a_i - y_i ∂zi​∂C​=ai​−yi​

最后放一份CS231N的代码实现,帮助进一步理解:

#coding=utf-8
import numpy as npdef softmax_loss_native(W, X, y, reg):'''Softmax_loss的暴力实现,利用了for循环输入的维度是D,有C个分类类别,并且我们在有N个例子的batch上进行操作输入:- W: 一个numpy array,形状是(D, C),代表权重- X: 一个形状为(N, D)为numpy array,代表输入数据- y: 一个形状为(N,)的numpy array,代表类别标签- reg: (float)正则化参数f返回:- 一个浮点数代表Loss- 和W形状一样的梯度'''loss = 0.0dW = np.zeros_like(W) #dW代表W反向传播的梯度num_classes = W.shape[1]num_train = X.shape[0]for i in xrange(num_train):scores = X[i].dot(W)shift_scores = scores - max(scores) #防止数值不稳定loss_i = -shift_scores[y[i]] + np.log(sum(np.exp(shift_scores)))loss += loss_ifor j in xrange(num_classes):softmax_output = np.exp(shift_scores[j]) / sum(np.exp(shift_scores))if j == y[i]:dW[:, j] += (-1 + softmax_output) * X[i]else:dW[:, j] += softmax_output * X[i]loss /= num_trainloss += 0.5 * reg * np.sum(W * W)dW = dW / num_train + reg * Wreturn loss, dWdef softmax_loss_vectorized(W, X, y, reg):loss = 0.0dW = np.zeros_like(W)num_class = W.shape[1]num_train = X.shape[0]scores = X.dot(W)shift_scores = scores - np.max(scores, axis=1).reshape(-1, 1)softmax_output  = np.exp(shift_scores) / np.sum(np.exp(shift_scores), axis=1).reshape(-1, 1)loss = -np.sum(np.log(softmax_output[range(num_train), list(y)]))loss /= num_trainloss += 0.5 * reg * np.sum(W * W)dS = softmax_output.copy()dS[range(num_train), list(y)] += -1dW = (x.T).dot(dS)dW = dW/num_train + reg*Wreturn loss, dW

总结

这篇文章介绍了近些年来算是非常常用的一些语义分割方面的损失函数,希望可以起到一个抛砖引玉的作用,引发大家对分割中的损失函数进一步思考。当然对于工程派和比赛派来讲,掌握一种新Loss并且应用于自己的项目或者比赛也是不错的。

附录

  • 参考资料1:https://www.aiuai.cn/aifarm1159.html
  • 参考资料2:https://blog.csdn.net/m0_37477175/article/details/83004746
  • 参考资料3:https://blog.csdn.net/m0_37477175/article/details/85335415
  • Generalized Dice loss代码实现:https://github.com/keras-team/keras/issues/9395
  • 参考资料4:https://blog.csdn.net/CaiDaoqing/article/details/90457197
  • Lovasz-Softmax Loss代码:https://github.com/bermanmaxim/LovaszSoftmax

推荐阅读

  • 【损失函数合集】Yann Lecun的Contrastive Loss 和 Google的Triplet Loss
  • 【损失函数合集】ECCV2016 Center Loss
  • 目标检测算法之RetinaNet(引入Focal Loss)
  • 目标检测算法之AAAI2019 Oral论文GHM Loss
  • 目标检测算法之CVPR2019 GIoU Loss
  • 目标检测算法之AAAI 2020 DIoU Loss 已开源(YOLOV3涨近3个点)

欢迎关注GiantPandaCV, 在这里你将看到独家的深度学习分享,坚持原创,每天分享我们学习到的新鲜知识。( • ̀ω•́ )✧

有对文章相关的问题,或者想要加入交流群,欢迎添加BBuf微信:

【损失函数合集】超详细的语义分割中的Loss大盘点相关推荐

  1. 【语义分割】类别不平衡损失函数合集

    在语义分割领域,我们会常常遇到类别不平衡的问题.比如要分割的目标(前景)可能只占图像的一小部分,因此负样本的比重很大,导致网络倾向于将所有样本判断为负样本.本文介绍了在数据不平衡时常用的一些损失函数. ...

  2. CVPR2020 | 即插即用!将双边超分辨率用于语义分割网络,提升图像分辨率的有效策略...

    点击上方"AI算法修炼营",选择"星标"公众号 精选作品,第一时间送达 本文是收录于CVPR2020的工作,文章利用低分辨率的输入图像通过超分辨率网络生成高分辨 ...

  3. dice系数 交叉熵_语义分割中的损失函数

    1 交叉熵 信息量:当一个事件发生的概率为 ,那么该事件对应的概率的信息量是 . 信息量的熵:信息量的期望,假设 事件 共有n种可能,发生 的概率为 ,那么该事件的熵 为: 相对熵,又称KL散度,如果 ...

  4. 最详细的语义分割---01如何读取数据集?

    数据集组成 网络训练的第一步就是读取数据,关于输入图片如何读取,如何进行预处理,将会在本篇文章中进行演示. 首先需要了解的是,语义分割中图片和标签是分别保存的.以voc数据集为例,它有20个类别,加上 ...

  5. 语义分割-Unsupervised Domain Adaptation in Semantic Segmentation:a Review语义分割中的无监督领域自适应:综述

    Unsupervised Domain Adaptation in Semantic Segmentation:a Review语义分割中的无监督领域自适应:综述 0.摘要 1.介绍 1.1.语义分割 ...

  6. 语义分割中的深度学习方法全解:从FCN、SegNet到各版本DeepLab

    语义分割中的深度学习方法全解:从FCN.SegNet到各版本DeepLab 原文:https://www.sohu.com/a/155907339_610300 图像语义分割就是机器自动从图像中分割出 ...

  7. 来自CCNet的一种创新:语义分割中的十字交叉视觉注意力

    来自CCNet的一种创新:语义分割中的十字交叉视觉注意力 写在文章开头 看个大概 引入 CCNet之道 整体架构 十字交叉注意力 循环--RCCA 优化类别一致性损失 CCNet效果一览 写在文章末尾 ...

  8. 语义分割中的一些模型的分类汇总

    语义分割是深度学习中的一个重要应用领域.自Unet提出到现在已经过去了8年,期间有很多创新式的语义分割模型.简单的总结了Unet++.Unet3+.HRNet.LinkNet.PSPNet.DeepL ...

  9. ”语义分割”中的“语义”

    感谢这篇论文,让我知道了"语义分割"中"语义"这一个词到底是个什么鬼.所谓的语义分割,就是之前的分割,在加上分类啦! 论文:基于内容的图像分割方法综述 姜峰 顾 ...

最新文章

  1. 【C语言】模拟实现库函数 strcpy(复制字符串内容) 与 strlen(求字符串长度)
  2. 华为北大等打造的Transformer竟在CV上超过CNN
  3. 中控考勤机的二次开发之数据秒上传至服务器功能
  4. android用openGl ES绘制任意方程的三维空间图形
  5. 搭建YUM服务器,配置yum客户端
  6. python appium自动化测试平台开发,Python+Appium实现自动化测试
  7. 软考计算机基础:存储系统
  8. JVM001_类文件结构
  9. 通过mysql实现leader election
  10. C++---容器适配器(stack、queue、priority_queue)
  11. android微信第三方登录怎么通过code获取openid?
  12. json文件编辑器android版,json editor手机版下载
  13. 英特尔傲腾内存linux,英特尔傲腾技术挺简单 三分钟了解这项黑科技
  14. DICOM世界观·第二章:[2]像素操作
  15. FILecoin 将重大战略升级,FIL 或将引导商业数据
  16. python应用——简单的跟随北上资金策略
  17. 湄洲岛风光-鹅尾神石园
  18. 一个90后程序员,需要养活几个过重阳节的老人?
  19. linux下的orre命令,鳥哥的 Linux 私房菜
  20. 带着问题学 Kubernetes 抽象对象 Service 服务间调用

热门文章

  1. GEE数据集:TerraClimate爱达荷大学全球陆地表面的每月气候和气候水平衡数据集
  2. 我的2017年读书计划
  3. 近期开通《Python编程快速上手-让繁琐工作自动化》视频教学
  4. #PPT进阶——效果聚焦
  5. 直销现状:从奖金分配政策看直销
  6. ATSHA204A加密芯片的使用
  7. SANGFOR SCSA——虚拟专用网与IPSec解决方案
  8. 网管培训教程之DOS篇
  9. linux怎么u盘挂载到根目录,Linux系统挂载U盘方法
  10. 2023美团商家数据