常用的损失函数合集

目录

一、什么是损失函数?

二、为什么需要损失函数?

三、损失函数通常使用的位置

四、损失函数的分类

五、常用的损失函数

1、回归损失(针对连续型变量)

1.L1 Loss也称为Mean Absolute Error,即平均绝对误差(MAE)

2.L2 Loss 也称为Mean Squred Error,即均方差(MSE)

3. Smooth L1 Loss 即平滑的L1损失(SLL)

锚框损失(参考讲解会更详细)

4.IoU Loss 即交并比损失

5.GIoU Loss 即泛化的IoU损失(考虑重叠面积)

6.DIoU Loss 即距离IoU损失(考虑重叠面积,中心点距离)

7.CIoU Loss 即完整IoU损失(考虑重叠面积,中心点距离,宽高比)

8.F-EIoU Loss

9.CDIoU Loss

2、分类损失(针对离散型变量)

1.1 Entropy即“熵”

1.2 Cross Entropy 交叉熵

2.K-L Divergence 即KL散度(相对熵)

3. Hinge 损失函数(SVM)

4.Dice Loss 即骰子损失

5.Focal Loss即 焦点损失

6.Tversky loss

六、如何选择损失函数

七、总结

八、参考链接 


一、什么是损失函数?

        简单的理解就是每一个样本经过模型后会得到一个预测值,然后得到的预测值和真实值的差值就成为损失(当然损失值越小证明模型越是成功),我们知道有许多不同种类的损失函数,这些函数本质上就是计算预测值和真实值的差距的一类型函数,然后经过库(如pytorch,tensorflow等)的封装形成了有具体名字的函数。

        机器学习中,损失函数是代价函数的一部分,而代价函数则是目标函数的一种类型。

损失函数(Loss Function) 用于定义单个训练样本与真实值之间的误差;

代价函数(Cost Function) 用于定义单个批次/整个训练集样本与真实值之间的误差;

目标函数(Objective Function) 泛指任意可以被优化的函数。

        损失函数用来评估模型预测值与真实值的偏离程度。通常情况下,损失函数选取的越好,模型的性能越好。不同模型间采用的损失函数一般也不一样。最常用的最小化损失函数的算法便是“梯度下降”(Gradient Descent)。

二、为什么需要损失函数?

        我们上文说到损失函数是计算预测值和真实值的一类函数,而在机器学习中,我们想让预测值无限接近于真实值,所以需要将差值降到最低(在这个过程中就需要引入损失函数)。而在此过程中损失函数的选择是十分关键的,在具体的项目中,有些损失函数计算的差值梯度下降的快,而有些下降的慢,所以选择合适的损失函数也是十分关键的。

三、损失函数通常使用的位置

        在机器学习中,我们知道输入的feature(或称为x)需要通过模型(model)预测出y,此过程称为向前传播(forward pass),而要将预测与真实值的差值减小需要更新模型中的参数,这个过程称为向后传播(backward pass),其中我们损失函数(lossfunction)就基于这两种传播之间,起到一种有点像承上启下的作用,承上指:接収模型的预测值,启下指:计算预测值和真实值的差值,为下面反向传播提供输入数据。

四、损失函数的分类

        损失函数的分类方式有多种,按照是否添加正则项可分为经验风险损失函数结构风险损失函数。按照任务类型分类,可分为两种:回归损失(针对连续型变量)和分类损失(针对离散型变量)。


五、常用的损失函数

1、回归损失(针对连续型变量

1.L1 Loss也称为Mean Absolute Error,即平均绝对误差(MAE)

常用的损失函数合集_第1张图片

        平均绝对误差(MAE)是另一种常用的回归损失函数,它是目标值与预测值之差绝对值和的均值,表示了预测值的平均误差幅度,而不需要考虑误差的方向(平均偏差误差MBE则是考虑的方向的误差,是残差的和),范围是0∞。

(1)图像:

常用的损失函数合集_第2张图片

(2)性能:

MAE损失优点:

1L1损失函数对离群点Outliers)或者异常值更具有鲁棒性。(受离群点的影响较小)。

2相比于MSEMAE有个优点就是,对于离群点不那么敏感。因为MAE计算的是误差(y-f(x))的绝对值,对于任意大小的差值,其惩罚都是固定的。无论对于什么样的输入值,都有着稳定的梯度,不会导致梯度爆炸问题,具有较为稳健性的解。

MAE损失不足:

1在零处不可导,求解效率低,收敛速度慢;

2MAE曲线连续,但是在(y-f(x)=0)处不可导。而且 MAE 大部分情况下梯度都是相等的,这意味着即使对于小的损失值,其梯度也是大的。这不利于函数的收敛和模型的学习。针对它的收敛问题,一般的解决办法是在优化算法中使用变化的学习率,在损失接近最小值时降低学习率。

(3)代码实现

Pytorch

        计算 output target 之差的绝对值。

torch.nn.L1Loss(reduction='mean')

参数:

reduction-三个值,none: 不使用约简;mean:返回loss和的平均值;sum:返回loss的和。默认:mean

tensorflow2keras

        计算预测值与标签值之间的绝对误差的平均值:

tf.keras.losses.MAE(y_true, y_pred)
参数:

y_true

标签值

y_pred

预测值

该函数的别名:

TensorFlow2损失函数大全_bigcindy的博客-CSDN博客_tensorflow二分类损失函数

2.L2 Loss 也称为Mean Squred Error,即均方差(MSE)

常用的损失函数合集_第3张图片

        即平滑的L1损失(SLL),出自Fast RCNN SLL通过综合L1L2损失的优点,在0点处附近采用了L2损失中的平方函数,解决了L1损失在0点处梯度不可导的问题,使其更加平滑易于收敛。此外,在|x|>1的区间上,它又采用了L1损失中的线性函数,使得梯度能够快速下降。

(1)图像:

常用的损失函数合集_第4张图片

(2)性能:

MSE损失优点:

(1)MSE的函数曲线光滑、连续,处处可导,便于使用梯度下降算法,是一种常用的损失函数。 而且,随着误差的减小,梯度也在减小,这有利于收敛,即使使用固定的学习速率,也能较快的收敛到最小值。

(2)收敛速度快,能够对梯度给予合适的惩罚权重,而不是“一视同仁”,使梯度更新的方向可以更加精确。

MSE损失不足:

(1)当真实值y和预测值f(x)的差值大于1时,会放大误差;而当差值小于1时,则会缩小误差,这是平方运算决定的。MSE对于较大的误差(>1)给予较大的惩罚,较小的误差(<1)给予较小的惩罚。也就是说,对离群点比较敏感,受其影响较大,不具备鲁棒性。。

(3)代码实现

Pytorch

        计算 output target 之差的均方差。

torch.nn.MSELoss(reduction='mean')

参数:

reduction-三个值,none: 不使用约简;mean:返回loss和的平均值;sum:返回loss的和。默认:mean

tensorflow2keras

        计算预测值与标签值之间的均方误差:

tf.keras.losses.MSE(y_true, y_pred)
参数:

y_true

标签值

y_pred

预测值

该函数的别名:

TensorFlow2损失函数大全_bigcindy的博客-CSDN博客_tensorflow二分类损失函数

3. Smooth L1 Loss 即平滑的L1损失(SLL

        均方误差(Mean Square Error,MSE)是回归损失函数中最常用的误差,它是预测值f(x)与目标值y之间差值平方和的均值。出自Fast RCNN 

(1)图像:

常用的损失函数合集_第5张图片

(2)性能:

Smooth L1损失改进:

        通过对这三个损失函数进行求导可以发现,L1损失的导数为常数,如果不及时调整学习率,那么当值过小时,会导致模型很难收敛到一个较高的精度,而是趋向于一个固定值附近波动。反过来,对于L2损失来说,由于在训练初期值较大时,其导数值也会相应较大,导致训练不稳定。最后,可以发现Smooth L1在训练初期输入数值较大时能够较为稳定在某一个数值,而在后期趋向于收敛时也能够加速梯度的回传,很好的解决了前面两者所存在的问题。

Smooth L1损失不足:

(1)上面的三种Loss用于计算目标检测的Bounding Box Loss时,独立的求出4个点的Loss,然后进行相加得到最终的Bounding Box Loss这种做法的假设是4个点是相互独立的,实际是有一定相关性的

(2)实际评价框检测的指标是使用IOU,这两者是不等价的,多个检测框可能有相同大小的Smooth L1 LossIOU可能差异很大,为了解决这个问题就引入了IOU LOSS

(3)应用的案例:

      Faster RCNN目标检测。

(4)代码实现

Pytorch

        计算 output target 之差的均方差。

torch.nn.SmoothL1Loss(reduction='mean')

参数:

reduction-三个值,none: 不使用约简;mean:返回loss和的平均值;sum:返回loss的和。默认:mean

tensorflow2keras

        计算预测值与标签值之间的均方误差:(delta1.0时为SmoothL1)

tf.keras.losses.Huber(y_true, y_pred, delta=delta)
参数:

y_true

标签值

y_pred

预测值

delta

1.0

转换链接:

tensorflow2.x实现人脸关键点检测_Haohao+++的博客-CSDN博客_tensorflow 关键点检测

锚框损失(参考讲解会更详细)

理论参考:

【YOLO v4 相关理论】Bounding Box regression loss: IoU Loss、GIoU Loss、DIoU Loss、CIoU Loss_满船清梦压星河HK的博客-CSDN博客

极市开发者平台-计算机视觉算法开发落地平台

代码参考:

【深度学习】锚框损失 IoU Loss、GIoU Loss、 DIoU Loss 、CIoU Loss、 CDIoU Loss、 F-EIoU Loss_XD742971636的博客-CSDN博客_ciou loss论文

IoU、GIoU、DIoU、CIoU损失函数的那点事儿 - 知乎

深度学习笔记(十三):IOU、GIOU、DIOU、CIOU、EIOU、Focal EIOU、alpha IOU损失函数分析及Pytorch实现_ZZY_dl的博客-CSDN博客_eiou

各锚框损失对比:

边界框回归的三大几何因素:重叠面积、中心点距离、纵横比

IOU Loss:考虑了重叠面积,归一化坐标尺度;

GIOU Loss:考虑了重叠面积,基于IOU解决边界框不相交时loss等于0的问题;

DIOU Loss:考虑了重叠面积和中心点距离,基于IOU解决GIOU收敛慢的问题;

CIOU Loss:考虑了重叠面积、中心点距离、纵横比,基于DIOU提升回归精确度;

EIOU Loss:考虑了重叠面积,中心点距离、长宽边长真实差,基于CIOU解决了纵横比的模糊定义,并添加Focal Loss解决BBox回归中的样本不平衡问题。

IOU Loss

GIOU Loss

DIOU Loss

CIOU Loss

EIOU Loss

优点

IOU算法是目标检测中最常用的指标,具有尺寸不变性,满足非负性、同一性、对称性、三角不等性等特点

GIOU在基于IOU特性的基础上引入最小外界框解决检测框和真实框没有重叠时loss等于0的问题

DIOU在基于IOU特性的基础上考虑到GIOU的缺点,直接回归两个框中心点的欧式距离,加速收敛。

CIOU就是在DIOU的基础上增加了检测框尺度的loss,增加了长和宽的loss,这样预测框就会更加的符合真实框。

EIOU在CIOU的基础上分别计算宽高的差异值取代了横纵比,同时引入Focal Loss解决难以样本不平衡的问题。

缺点

1、如果两个框不相交,不能反映两个框距离远近。

2、无法精确的反映两个框的重合度大小

1、当检测框和真实框出现包含现象的时候GIOU退化成IOU

2、两个框相交时,在水平和垂直方向上收敛慢

回归过程中未考虑Bounding box的横纵比,精确度上尚有进一步提升的空间

1、横纵比描述的是相对值,存在一定的模糊。

2、未考虑难易样本的平衡问题。

待定

4.IoU Loss 即交并比损失

论文:https://arxiv.org/pdf/1608.01471.pdf

        即交并比损失,出自UnitBox,由旷视科技于ACM2016首次提出。常规的Lx损失中,都是基于目标边界中的4个坐标点信息之间分别进行回归损失计算的。因此,这些边框信息之间是相互独立的。然而,直观上来看,这些边框信息之间必然是存在某种相关性的。如下图(a)-(b)分别所示,绿色框代表Ground Truth,黑色框代表Prediction,可以看出,同一个Lx分数,预测框与真实框之间的拟合/重叠程度并不相同,显然重叠度越高的预测框是越合理的。IoU损失将候选框的四个边界信息作为一个整体进行回归,从而实现准确、高效的定位,具有很好的尺度不变性。为了解决IoU度量不可导的现象,引入了负Ln范数来间接计算IoU损失。

常用的损失函数合集_第6张图片

常用的损失函数合集_第7张图片

 (1) 性能

IoU Loss存在优点:

(1)相比与L2损失而言,可以更好的反映检测框与真实检测框的检测效果

(2)具有尺度不变性,也就是对尺度不敏感 (无论两个框是大是小,它们的从重合程度是和尺度大小无关的)

IoU Loss存在缺点:
1)当预测框与真实框之间没有任何重叠时,IoU损失为0,梯度无法有效地反向传播和更新;
2IoU对重叠情况不敏感,预测框与真实框不同的重叠情况的时候,有可能计算出来的IoU是一样的;

(2)应用场景:

除了作为目标检测的评价指标IOU还有其他应用场景:

(1)在anchor-based方法的目标检测中,根据IOU的值来区分正样本和负样本。

(2)可以直接作为边界框回归的loss函数进行优化。

(3)在NMS(非极大值抑制)对预测框筛选。

(3)代码实现:

import numpy as np
def Iou(box1, box2, wh=False):
    if wh == False:
        xmin1, ymin1, xmax1, ymax1 = box1
        xmin2, ymin2, xmax2, ymax2 = box2
    else:
        xmin1, ymin1 = int(box1[0]-box1[2]/2.0), int(box1[1]-box1[3]/2.0)
        xmax1, ymax1 = int(box1[0]+box1[2]/2.0), int(box1[1]+box1[3]/2.0)
        xmin2, ymin2 = int(box2[0]-box2[2]/2.0), int(box2[1]-box2[3]/2.0)
        xmax2, ymax2 = int(box2[0]+box2[2]/2.0), int(box2[1]+box2[3]/2.0)
    # 获取矩形框交集对应的左上角和右下角的坐标(intersection)
    xx1 = np.max([xmin1, xmin2])
    yy1 = np.max([ymin1, ymin2])
    xx2 = np.min([xmax1, xmax2])
    yy2 = np.min([ymax1, ymax2])	
    # 计算两个矩形框面积
    area1 = (xmax1-xmin1) * (ymax1-ymin1) 
    area2 = (xmax2-xmin2) * (ymax2-ymin2)
    inter_area = (np.max([0, xx2-xx1])) * (np.max([0, yy2-yy1])) # 计算交集面积
    iou = inter_area / (area1+area2-inter_area+1e-6)  # 计算交并比
    return iou

5.GIoU Loss 即泛化的IoU损失(考虑重叠面积)

论文:https://arxiv.org/pdf/1902.09630.pdf

        

        即泛化的IoU损失,全称为Generalized Intersection over Union,由斯坦福学者于CVPR2019年发表的这篇论文 中首次提出。上面我们提到了IoU损失可以解决边界框坐标之间相互独立的问题,考虑这样一种情况,当预测框与真实框之间没有任何重叠时,两个边框的交集(分子)为0,此时IoU损失为0,因此IoU无法算出两者之间的距离(重叠度)。另一方面,由于IoU损失为零,意味着梯度无法有效地反向传播和更新,即出现梯度消失的现象,致使网络无法给出一个优化的方向。此外,如下图所示,IoU不同方向的边框对齐也是一脸懵逼的,所计算出来的值都一样。

常用的损失函数合集_第8张图片

        为了解决以上的问题,如下图公式所示,GIoU通过计算任意两个形状(这里以矩形框为例)AB的一个最小闭合凸面C,然后再计算C中排除掉AB后的面积占C原始面积的比值,最后再用原始的IoU减去这个比值得到泛化后的IoU值。

常用的损失函数合集_第9张图片

        GIoU具有IoU所拥有的一切特性,如对称性,三角不等式等。GIoU ≤ IoU,特别地,0 ≤ IoU(A, B) ≤ -1, 0 ≤ GIoU(A, B) ≤ -1;当两个边框的完全重叠时,此时GIoU = IoU = 1. 而当 |AUB| 最小闭合凸面C 的比值趋近为0时,即两个边框不相交的情况下,此时GIoU将渐渐收敛至 -1. 同样地,我们也可以通过一定的方式去计算出两个矩形框之间的GIoU损失,具体计算步骤也非常简单,详情参考原

(1)性能

GIoU 性质:

(1) 与IoU相似,GIoU也是一种距离度量,作为损失函数的话,满足损失函数的基本要求

(2)GIoU对scale不敏感

(3)GIoU是IoU的下界,在两个框无限重合的情况下,IoU=GIoU=1

(4)IoU取值[0,1],但GIoU有对称区间,取值范围[-1,1]。在两者重合的时候取最大值1,在两者无交集且无限远的时候取最小值-1,因此GIoU是一个非常好的距离度量指标。

(5)与IoU只关注重叠区域不同,GIoU不仅关注重叠区域,还关注其他的非重合区域,能更好的反映两者的重合度。

GIoU缺点:

(1)边框回归还不够精确

(2)收敛速度缓慢

(3)只考虑到重叠面积关系,效果不佳

(2)代码实现:

def Giou(rec1,rec2):
    #分别是第一个矩形左右上下的坐标
    x1,x2,y1,y2 = rec1
    x3,x4,y3,y4 = rec2
    iou = Iou(rec1,rec2)
    area_C = (max(x1,x2,x3,x4)-min(x1,x2,x3,x4))*(max(y1,y2,y3,y4)-min(y1,y2,y3,y4))
    area_1 = (x2-x1)*(y1-y2)
    area_2 = (x4-x3)*(y3-y4)
    sum_area = area_1 + area_2

    w1 = x2 - x1   #第一个矩形的宽
    w2 = x4 - x3   #第二个矩形的宽
    h1 = y1 - y2
    h2 = y3 - y4
    W = min(x1,x2,x3,x4)+w1+w2-max(x1,x2,x3,x4)    #交叉部分的宽
    H = min(y1,y2,y3,y4)+h1+h2-max(y1,y2,y3,y4)    #交叉部分的高
    Area = W*H    #交叉的面积
    add_area = sum_area - Area    #两矩形并集的面积

    end_area = (area_C - add_area)/area_C    #闭包区域中不属于两个框的区域占闭包区域的比重
    giou = iou - end_area
    return giou

6.DIoU Loss 即距离IoU损失(考虑重叠面积,中心点距离)

论文:https://arxiv.org/pdf/1911.08287.pdf

        即距离IoU损失,全称为Distance-IoU loss,由天津大学数学学院研究人员于AAAI2020所发表的这篇论文中首次提出。上面我们谈到GIoU通过引入最小闭合凸面来解决IoU无法对不重叠边框的优化问题。但是,其仍然存在两大局限性:边框回归还不够精确 & 收敛速度缓慢 。考虑下图这种情况,当目标框完全包含预测框时,此时GIoU退化IoU。显然,我们希望的预测是最右边这种情况。因此,作者通过计算两个边框之间的中心点归一化距离,从而更好的优化这种情况。 

常用的损失函数合集_第10张图片

        下图表示的是GIoU损失(第一行)和DIoU损失(第二行)的一个训练过程收敛情况。其中绿色框为目标边框,黑色框为锚框,蓝色框和红色框则分别表示使用GIoU损失和DIoU损失所得到的预测框。可以发现,GIoU损失一般会增加预测框的大小使其能和目标框重叠,而DIoU损失则直接使目标框和预测框之间的中心点归一化距离最小,即让预测框的中心快速的向目标中心收敛。

常用的损失函数合集_第11张图片

        左图给出这三个IoU损失所对应的计算公式。对于DIoU来说,如图右所示,其惩罚项由两部分构成:分子为目标框和预测框中心点之间的欧式距离;分母为两个框最小外接矩形框的两个对角线距离。因此, 直接优化两个点之间的距离会使得模型收敛得更快,同时又能够在两个边框不重叠的情况下给出一个优化的方向。

常用的损失函数合集_第12张图片

 (1)性能

DIoU性质:

(1)与GIoU loss类似,DIoU loss在与目标框不重叠时,仍然可以为边界框提供移动方向。

(2)DIoU loss可以直接最小化两个目标框的距离,因此比GIoU loss收敛快得多。

(3)对于包含两个框在水平方向和垂直方向上这种情况,DIoU损失可以使回归非常快,而GIoU损失几乎退化为IoU损失。

(4)DIoU还可以替换普通的IoU评价策略,应用于NMS中,使得NMS得到的结果更加合理和有效。

Diou不足:

还要有个重要指标预测框与真实框的长宽比没考虑到。

(2)代码实现:

def Diou(bboxes1, bboxes2):
    rows = bboxes1.shape[0]
    cols = bboxes2.shape[0]
    dious = torch.zeros((rows, cols))
    if rows * cols == 0:
        return dious
    exchange = False
    if bboxes1.shape[0] > bboxes2.shape[0]:
        bboxes1, bboxes2 = bboxes2, bboxes1
        dious = torch.zeros((cols, rows))
        exchange = True
    # #xmin,ymin,xmax,ymax->[:,0],[:,1],[:,2],[:,3]
    w1 = bboxes1[:, 2] - bboxes1[:, 0]
    h1 = bboxes1[:, 3] - bboxes1[:, 1] 
    w2 = bboxes2[:, 2] - bboxes2[:, 0]
    h2 = bboxes2[:, 3] - bboxes2[:, 1]
    
    area1 = w1 * h1
    area2 = w2 * h2

    center_x1 = (bboxes1[:, 2] + bboxes1[:, 0]) / 2 
    center_y1 = (bboxes1[:, 3] + bboxes1[:, 1]) / 2 
    center_x2 = (bboxes2[:, 2] + bboxes2[:, 0]) / 2
    center_y2 = (bboxes2[:, 3] + bboxes2[:, 1]) / 2

    inter_max_xy = torch.min(bboxes1[:, 2:],bboxes2[:, 2:]) 
    inter_min_xy = torch.max(bboxes1[:, :2],bboxes2[:, :2]) 
    out_max_xy = torch.max(bboxes1[:, 2:],bboxes2[:, 2:]) 
    out_min_xy = torch.min(bboxes1[:, :2],bboxes2[:, :2])

    inter = torch.clamp((inter_max_xy - inter_min_xy), min=0)
    inter_area = inter[:, 0] * inter[:, 1]
    inter_diag = (center_x2 - center_x1)**2 + (center_y2 - center_y1)**2
    outer = torch.clamp((out_max_xy - out_min_xy), min=0)
    outer_diag = (outer[:, 0] ** 2) + (outer[:, 1] ** 2)
    union = area1+area2-inter_area
    dious = inter_area / union - (inter_diag) / outer_diag
    dious = torch.clamp(dious,min=-1.0,max = 1.0)
    if exchange:
        dious = dious.T
    return dious

7.CIoU Loss 即完整IoU损失(考虑重叠面积,中心点距离,宽高比)

被与DIoU同一篇的论文提出:https://arxiv.org/pdf/1911.08287.pdf

        即完整IoU损失,全称为Complete IoU loss,与DIoU出自同一篇论文。上面我们提到GIoU存在两个缺陷,DIoU的提出解决了其实一个缺陷,即收敛速度的问题。而一个好的边框回归损失应该同时考虑三个重要的几何因素,即重叠面积(Overlap area)、中心点距离(Central point distance)和高宽比(Aspect ratio)。GIoU考虑到了重叠面积的问题,DIoU考虑到了重叠面积和中心点距离的问题,CIoU则在此基础上进一步的考虑到了高宽比的问题。

常用的损失函数合集_第13张图片

         CIoU的计算公式如下所示,可以看出,其在DIoU的基础上加多了一个惩罚项αv。其中α为权重为正数的重叠面积平衡因子,在回归中被赋与更高的优先级,特别是在两个边框不重叠的情况下;v则用于测量宽高比的一致性。

常用的损失函数合集_第14张图片

 (1)性能

优点:

        同时考虑到了预测框与真实框的重叠面积、中心点距离、长宽比。收敛更快,效果更好。

(2)代码实现:

def bbox_overlaps_ciou(bboxes1, bboxes2):
    rows = bboxes1.shape[0]
    cols = bboxes2.shape[0]
    cious = torch.zeros((rows, cols))
    if rows * cols == 0:
        return cious
    exchange = False
    if bboxes1.shape[0] > bboxes2.shape[0]:
        bboxes1, bboxes2 = bboxes2, bboxes1
        cious = torch.zeros((cols, rows))
        exchange = True

    w1 = bboxes1[:, 2] - bboxes1[:, 0]
    h1 = bboxes1[:, 3] - bboxes1[:, 1]
    w2 = bboxes2[:, 2] - bboxes2[:, 0]
    h2 = bboxes2[:, 3] - bboxes2[:, 1]

    area1 = w1 * h1
    area2 = w2 * h2

    center_x1 = (bboxes1[:, 2] + bboxes1[:, 0]) / 2
    center_y1 = (bboxes1[:, 3] + bboxes1[:, 1]) / 2
    center_x2 = (bboxes2[:, 2] + bboxes2[:, 0]) / 2
    center_y2 = (bboxes2[:, 3] + bboxes2[:, 1]) / 2

    inter_max_xy = torch.min(bboxes1[:, 2:],bboxes2[:, 2:])
    inter_min_xy = torch.max(bboxes1[:, :2],bboxes2[:, :2])
    out_max_xy = torch.max(bboxes1[:, 2:],bboxes2[:, 2:])
    out_min_xy = torch.min(bboxes1[:, :2],bboxes2[:, :2])

    inter = torch.clamp((inter_max_xy - inter_min_xy), min=0)
    inter_area = inter[:, 0] * inter[:, 1]
    inter_diag = (center_x2 - center_x1)**2 + (center_y2 - center_y1)**2
    outer = torch.clamp((out_max_xy - out_min_xy), min=0)
    outer_diag = (outer[:, 0] ** 2) + (outer[:, 1] ** 2)
    union = area1+area2-inter_area
    u = (inter_diag) / outer_diag
    iou = inter_area / union
    with torch.no_grad():
        arctan = torch.atan(w2 / h2) - torch.atan(w1 / h1)
        v = (4 / (math.pi ** 2)) * torch.pow((torch.atan(w2 / h2) - torch.atan(w1 / h1)), 2)
        S = 1 - iou
        alpha = v / (S + v)
        w_temp = 2 * w1
    ar = (8 / (math.pi ** 2)) * arctan * ((w1 - w_temp) * h1)
    cious = iou - (u + alpha * ar)
    cious = torch.clamp(cious,min=-1.0,max = 1.0)
    if exchange:
        cious = cious.T
    return cious

8.F-EIoU Loss

论文:https://yfzhang114.github.io/files/cvpr_final.pdf

        Focal and Efficient IoU Loss是由华南理工大学学者最近提出的一篇关于目标检测损失函数的论文,文章主要的贡献是提升网络收敛速度和目标定位精度。目前检测任务的损失函数主要有两个缺点:(1)无法有效地描述边界框回归的目标,导致收敛速度慢以及回归结果不准确(2)忽略了边界框回归中不平衡的问题。

F-EIou loss首先提出了一种有效的交并集(IOU)损失,它可以准确地测量边界框回归中的重叠面积中心点边长三个几何因素的差异:

常用的损失函数合集_第15张图片

        其次,基于对有效样本挖掘问题(EEM)的探讨,提出了Focal loss的回归版本,以使回归过程中专注于高质量的锚框:

常用的损失函数合集_第16张图片

        最后,将以上两个部分结合起来得到Focal-EIou Loss

常用的损失函数合集_第17张图片

         其中,通过加入每个batch的权重和来避免网络在早期训练阶段收敛慢的问题。

(1)代码实现:

def bbox_iou(box1, box2, x1y1x2y2=True, GIoU=False, DIoU=False, CIoU=False,  EIoU=False, eps=1e-7):
    # Returns the IoU of box1 to box2. box1 is 4, box2 is nx4
    box2 = box2.T

    # Get the coordinates of bounding boxes
    if x1y1x2y2:  # x1, y1, x2, y2 = box1
        b1_x1, b1_y1, b1_x2, b1_y2 = box1[0], box1[1], box1[2], box1[3]
        b2_x1, b2_y1, b2_x2, b2_y2 = box2[0], box2[1], box2[2], box2[3]
    else:  # transform from xywh to xyxy
        b1_x1, b1_x2 = box1[0] - box1[2] / 2, box1[0] + box1[2] / 2
        b1_y1, b1_y2 = box1[1] - box1[3] / 2, box1[1] + box1[3] / 2
        b2_x1, b2_x2 = box2[0] - box2[2] / 2, box2[0] + box2[2] / 2
        b2_y1, b2_y2 = box2[1] - box2[3] / 2, box2[1] + box2[3] / 2

    # Intersection area
    inter = (torch.min(b1_x2, b2_x2) - torch.max(b1_x1, b2_x1)).clamp(0) * \
            (torch.min(b1_y2, b2_y2) - torch.max(b1_y1, b2_y1)).clamp(0)

    # Union Area
    w1, h1 = b1_x2 - b1_x1, b1_y2 - b1_y1 + eps
    w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1 + eps
    union = w1 * h1 + w2 * h2 - inter + eps

    iou = inter / union
    if GIoU or DIoU or CIoU or EIoU:
        cw = torch.max(b1_x2, b2_x2) - torch.min(b1_x1, b2_x1)  # convex (smallest enclosing box) width
        ch = torch.max(b1_y2, b2_y2) - torch.min(b1_y1, b2_y1)  # convex height
        if CIoU or DIoU or EIoU:  # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1
            c2 = cw ** 2 + ch ** 2 + eps  # convex diagonal squared
            rho2 = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 +
                    (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4  # center distance squared
            if DIoU:
                return iou - rho2 / c2  # DIoU
            elif CIoU:  # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47
                v = (4 / math.pi ** 2) * torch.pow(torch.atan(w2 / h2) - torch.atan(w1 / h1), 2)
                with torch.no_grad():
                    alpha = v / (v - iou + (1 + eps))
                return iou - (rho2 / c2 + v * alpha)  # CIoU
            elif EIoU:
                rho_w2 = ((b2_x2 - b2_x1) - (b1_x2 - b1_x1)) ** 2
                rho_h2 = ((b2_y2 - b2_y1) - (b1_y2 - b1_y1)) ** 2
                cw2 = cw ** 2 + eps
                ch2 = ch ** 2 + eps
                return iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2)
        else:  # GIoU https://arxiv.org/pdf/1902.09630.pdf
            c_area = cw * ch + eps  # convex area
            return iou - (c_area - union) / c_area  # GIoU
    else:
        return iou  # IoU

9.CDIoU Loss

论文:https://arxiv.org/pdf/2103.11696.pdf

        Control Distance IoU Loss是由同济大学学者提出的,文章的主要贡献是在几乎不增强计算量的前提下有效提升了边界框回归的精准度。目前检测领域主要两大问题:(1SOTA算法虽然有效但计算成本高(2)边界框回归损失函数设计不够合理。

常用的损失函数合集_第18张图片

        文章首先提出了一种对于Region PropaslRP)和Ground TruthGT)之间的新评估方式,即CDIoU。可以发现,它虽然没有直接中心点距离和长宽比,但最终的计算结果是有反应出RPGT的差异。计算公式如下:

常用的损失函数合集_第19张图片

常用的损失函数合集_第20张图片

        对比以往直接计算中心点距离或是形状相似性的损失函数,CDIoU能更合理地评估RPGT的差异并且有效地降低计算成本。然后,根据上述的公式,CDIoU Loss可以定义为:

        通过观察这个公式,可以直观地感受到,在权重迭代过程中,模型不断地将RP的四个顶点拉向GT的四个顶点,直到它们重叠为止,如下图所示:

常用的损失函数合集_第21张图片


2、分类损失(针对离散型变量)

1.1 Entropy

更详细的了解:

(1)视频:“交叉熵”如何做损失函数?打包理解“信息量”、“比特”、“熵”、“KL散度”、“交叉熵”_哔哩哔哩_bilibili

(2)博客:

交叉熵损失函数原理详解_Cigar丶的博客-CSDN博客_交叉熵损失函数交叉熵损失函数原理详解_Cigar丶的博客-CSDN博客_交叉熵损失函数交叉熵损失函数原理详解_Cigar丶的博客-CSDN博客_交叉熵损失函数

【深度学习】损失函数详解_LogosTR_的博客-CSDN博客_损失函数

1.2 Cross Entropy 交叉熵

        交叉熵损失函数的标准形式如上:(公式中x表示样本,y表示实际的标签,a表示预测的输出, n表示样本总数量。

常用的损失函数合集_第22张图片

        交叉熵(cross-entropy)刻画了两个概率分布之间的距离,更适合用在分类问题上,因为交叉熵表达预测输入样本属于某一类的概率。

1、二分类问题中的loss函数(输入数据是softmax或者sigmoid函数的输出):

常用的损失函数合集_第23张图片

2多分类问题中的loss函数(输入数据是softmax或者sigmoid函数的输出):

常用的损失函数合集_第24张图片

(1)性能:

交叉熵损失特点:

1、当使用sigmoid作为激活函数的时候,常用交叉熵损失函数而不用均方误差损失函数,因为它可以完美解决平方损失函数权重更新过慢的问题,具有误差大的时候,权重更新快;误差小的时候,权重更新慢的良好性质。

(2)代码实现

(Pytorch)

        当训练有 C 个类别的分类问题时很有效. 可选参数 weight 必须是一个1 Tensor, 权重将被分配给各个类别. 对于不平衡的训练集非常有效。

        在多分类任务中,经常采用 softmax 激活函数+交叉熵损失函数,因为交叉熵描述了两个概率分布的差异,然而神经网络输出的是向量,并不是概率分布的形式。所以需要 softmax激活函数将一个向量进行归一化成概率分布的形式,再采用交叉熵损失函数计算 loss

常用的损失函数合集_第25张图片

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

参数:

weight (Tensor, optional) – 自定义的每个类别的权重. 必须是一个长度为C Tensor

ignore_index (int, optional) – 设置一个目标值, 该目标值会被忽略, 从而不会影响到 输入的梯度。

reduction-三个值,none: 不使用约简;mean:返回loss和的平均值;sum:返回loss的和。默认:mean

tensorflow2keras

网址:TensorFlow2损失函数大全_bigcindy的博客-CSDN博客_tensorflow二分类损失函数

1、交叉熵损失CrossEntropyLoss——数字标签

        计算预测值与标签值之间的交叉熵损失,通常在两个或两个以上类别分类任务上使用,标签是单独的数字格式。

tf.keras.losses.SparseCategoricalCrossentropy(
    from_logits=False, reduction=losses_utils.ReductionV2.AUTO,
    name='sparse_categorical_crossentropy'
)

参数:

from_logits

一般情况下选择True,这样数据更稳定。

reduction

可选参数,一般为默认即可

name

可选参数,默认为 'sparse_categorical_crossentropy'.

别名:

tf.losses.SparseCategoricalCrossentropy()

2、交叉熵损失CrossEntropyLoss——one_hot标签

        计算预测值与标签值之间的交叉熵损失,通常在两个或两个以上类别分类任务上使用,标签是one_hot形式。

tf.keras.losses.CategoricalCrossentropy(
    from_logits=False, label_smoothing=0, reduction=losses_utils.ReductionV2.AUTO,
    name='categorical_crossentropy'
)

参数:

from_logits

一般情况下选择True,这样数据更稳定。

label_smoothing

浮点数,取值[0,1]

reduction

可选参数,一般为默认即可

name

可选参数,默认为 'sparse_categorical_crossentropy'.

别名:

tf.losses.CategoricalCrossentropy()

网址:【常见的损失函数总结】_菜菜雪丫头的博客-CSDN博客_常见损失函数

#Sigmoid交叉熵

tf.nn.simoid_cross_entropy_with_logits(y_pred, y, name=None)

#softmax交叉熵

tf.nn.softmax_cross_entropy_with_logits(y_pred, y, name=None)

#Sparse交叉熵

tf.nn.sparse_cross_entropy_with_logits(y_pred, y, name=None)

#加权Sigmoid交叉熵

tf.nn.weighter_cross_entropy_with_logits(y_pred, y, pos_weight,name=None)

2.K-L Divergence KL散度(相对熵

常用的损失函数合集_第26张图片

        机器学习中,往往存在两种分布,一个是数据样本的真实分布,分布由原始数据决定;另一个是模型预测的分布,KL散度来衡量以上两个分布的差异程度。其中P数据样本概率分布, Q为模型预测的概率分布。当PQ的分布越接近, DKL的值越小,表明模型对原始数据分布特点预测的越准。

(1)性能:

KL散度含义:

 KL散度是衡量两个概率分布间差异的非对称性度量标准

通俗来讲,KL散度是用来衡量同一个随机变量的两个不同概率分布之间的距离

比如:交叉熵就是表示一个随机变量的预测概率分布Q与真实概率分布P之间的差距。

KL散度特性:

非负性:由吉布斯不等式可知,KL散度恒大于等于0

非对称性:相对熵是两个概率分布的不对称性度量,即:

假设P表示随机变量的真实分布,Q表示理论、预测或拟合分布。

注意: 只有在PQ概率分布一模一样的时候,前向KL散度才与后向KL散度相等。

结论: 相对熵(KL散度)可以衡量两个随机分布之间的距离,当两个随机分布相同时,它们的相对熵为零,当两个随机分布的差别增大时,它们的相对熵也会增大。

(2)代码实现:

Pytorch)

torch.nn.KLDivLoss(size_average=None, reduce=None, reduction='mean', log_target=False)

注意:和NLLLoss一样,输入应该是log_softmax

tensorflow2keras

1、KLDivergence class

  • 用来计算y_truey_predict之间的KL散度
  • loss = y_true * log(y_true / y_pred)
tf.keras.losses.KLDivergence(reduction="auto", name="kl_divergence")

参数:

Y_true

标签值。

Y_pred

预测值

2、kl_divergence function

用法和上面的差不多

tf.keras.losses.kl_divergence(y_true, y_pred)

参数:

Y_true

标签值。

Y_pred

预测值

3. Hinge 损失函数(SVM

        在机器学习中,hinge loss是一种损失函数,它通常用于"maximum-margin"的分类任务中,如支持向量机(SVM)。数学表达式为:

常用的损失函数合集_第27张图片

4.Dice Loss 即骰子损失

        即骰子损失,出自V-Net是一种用于评估两个样本之间相似性度量的函数,取值范围为0~1,值越大表示两个值的相似度越高。

5.Focal Loss即 焦点损失

        焦点损失,出自何凯明的《Focal Loss for Dense Object Detection出发点是解决目标检测领域中one-stage算法如YOLO系列算法准确率不高的问题。作者认为样本的类别不均衡(比如前景和背景)是导致这个问题的主要原因。比如在很多输入图片中,我们利用网格去划分小窗口,大多数的窗口是不包含目标的。如此一来,如果我们直接运用原始的交叉熵损失,那么负样本所占比例会非常大,主导梯度的优化方向,即网络会偏向于将前景预测为背景。即使我们可以使用OHEM(在线困难样本挖掘)算法来处理不均衡的问题,虽然其增加了误分类样本的权重,但也容易忽略掉易分类样本。而Focal loss则是聚焦于训练一个困难样本的稀疏集,通过直接在标准的交叉熵损失基础上做改进,引进了两个惩罚因子,来减少易分类样本的权重,使得模型在训练过程中更专注于困难样本。

6.Tversky loss

        Tversky loss,发表于CVPR 2018上的一篇《Tversky loss function for image segmentation using 3D fully convolutional deep networks》文章,是根据Tversky 等人于1997年发表的《Features of Similarity》文章所提出的Tversky指数所改造的。Tversky系数主要用于描述两个特征(集合)之间的相似度。


六、如何选择损失函数

Pytorch-工业应用中如何选取合适的损失函数(MAE、MSE、Huber)_tt姐whaosoft的博客-CSDN博客_mse pytorch

七、总结

        本文章从整理了计算机视觉常用的损失函数,分别从出处、原理、优缺点和代码实现几个方面进行编写;由于损失函数变种太多,所以这里只提供了一部分,当然弄懂了这一部分,对于另外的大部分的理解也就差不多了。后续,我会总结自己在项目中见到或用过的损失,把他们归类展示,并且尝试分析一下什么场景应选择哪些损失函数训练。如果你觉得有用的话,请点个,谢谢。

八、参考链接 

1、文章主要参考的链接有:

CNN损失函数学习(最全)_张小波的博客-CSDN博客_cnn的损失函数(这里的L1和L2优缺点评价弄反了)

【深度学习】损失函数详解_LogosTR_的博客-CSDN博客_损失函数

损失函数loss大总结_watersink的博客-CSDN博客_loss损失函数

【常见的损失函数总结】_菜菜雪丫头的博客-CSDN博客_常见损失函数

TensorFlow2损失函数大全_bigcindy的博客-CSDN博客_tensorflow二分类损失函数

2、个别损失的参考链接

2.1 MAE损失参考链接:

深度学习_损失函数(MSE、MAE、SmoothL1_loss...)_ClFH的博客-CSDN博客_mse损失函数

tensorflow中的loss函数总结_fkyyly的博客-CSDN博客_tensorflow的loss

2.2 K-L Divergence 即KL散度(相对熵)参考链接:

通俗理解交叉熵和KL散度(包括标签平滑的pytorch实现)_栋次大次的博客-CSDN博客_kl loss pytorch

使用tensorflow2.x解决离散分布之间的KL散度_InceptionZ的博客-CSDN博客_kl tensorflow

你可能感兴趣的:(损失函数,深度学习,深度学习,机器学习,人工智能)