看了很多关于yolov3的算法讲解,但是对于损失函数一直没怎么看懂,再看代码,发现完全不懂,所以决定再仔细看看yolov3的损失函数。
由于是自己总结加分析,可能存在错误,如果有错误,请告诉我~
另外记录笔记只是为了自己学习,如果能帮助到别人很好,很开心~帮助不了,我也只是自己学习记录笔记,可以不看哦,请勿吐嘈谢谢感谢,因为不想打击 积极性啊哈~

先回顾下YOLOv1的损失函数
Loss=λcoord∑i=0S2∑j=0BIijobj[(xij−x^ij)2+(yij−y^ij)2]+λcoord∑i=0S2∑j=0BIijobj[(wij−w^ij)2+(hij−h^ij)2]+∑i=0S2∑j=0BIijobj(Cij−C^ij)2+λnoobj∑i=0S2∑j=0BIijnoobj(Cij−C^ij)2+∑i=0S2Iijobj∑c∈classes(Pij(c)−P^ij(c))2Loss=\lambda_{coord} \sum_{i=0}^{S^2} \sum_{j=0}^B {I_{ij}^{obj} [(x_i^j-\hat x_i^j)^2+ (y_i^j-\hat y_i^j)^2 ] }+ \\ \lambda_{coord} \sum_{i=0}^{S^2} \sum_{j=0}^B {I_{ij}^{obj} [ ( \sqrt { w_i^j}-\sqrt{\hat w_i^j} )^2+ (\sqrt { h_i^j}-\sqrt{\hat h_i^j})^2 ] }+ \\ \sum_{i=0}^{S^2} \sum_{j=0}^B {I_{ij}^{obj} (C_i^j -\hat C_i^j)^2 } +\\ \lambda_{noobj} \sum_{i=0}^{S^2} \sum_{j=0}^B {I_{ij}^{noobj} (C_i^j -\hat C_i^j)^2 } +\\\sum_{i=0}^{S^2} { I_{ij}^{obj} } \sum_{c \in {classes}} (P_i^j(c) - \hat P_i^j(c))^2 Loss=λcoord​i=0∑S2​j=0∑B​Iijobj​[(xij​−x^ij​)2+(yij​−y^​ij​)2]+λcoord​i=0∑S2​j=0∑B​Iijobj​[(wij​​−w^ij​​)2+(hij​​−h^ij​​)2]+i=0∑S2​j=0∑B​Iijobj​(Cij​−C^ij​)2+λnoobj​i=0∑S2​j=0∑B​Iijnoobj​(Cij​−C^ij​)2+i=0∑S2​Iijobj​c∈classes∑​(Pij​(c)−P^ij​(c))2

yolov2的损失函数
只是在yolov1基础上改动了关于bbox的w和h的损失计算方式 即从:
∑i=0S2∑j=0BIijobj[(wij−w^ij)2\sum_{i=0}^{S^2} \sum_{j=0}^B {I_{ij}^{obj} [ ( \sqrt { w_i^j}-\sqrt{\hat w_i^j} )^2}∑i=0S2​∑j=0B​Iijobj​[(wij​​−w^ij​​)2改到了∑i=0S2∑j=0BIijobj[(wij−w^ij)2+(hij−h^ij)2]\sum_{i=0}^{S^2} \sum_{j=0}^B {I_{ij}^{obj} [(w_i^j-\hat w_i^j)^2+ (h_i^j-\hat h_i^j)^2 ] }∑i=0S2​∑j=0B​Iijobj​[(wij​−w^ij​)2+(hij​−h^ij​)2]
去掉了w和h的二次根号,作者认为没有必要。

YOLOv3的损失函数
是在yolov2基础上改动的,最大的变动是分类损失换成了二分交叉熵,这是由于yolov3中剔除了softmax改用logistic。

为什么交叉熵可以作为机器学习的损失函数:

交叉熵

  • 刻画了两个概率分布之间的距离,也就是说,交叉熵值越小,两个概率分布越接近
  • 通过 p 来表示 q 的交叉熵:H(p,q)=−Σp(xi)logq(xi)H(p, q) = -\Sigma p(x_i)logq(x_i)H(p,q)=−Σp(xi​)logq(xi​)p 为正确答案的分布,q 为预测的分布,这个log是以e为底的
  • 代码示例
p = tf.constant([1.0, 0.0, 0.0])
q = tf.constant([0.88, 0.12, 0.0])
# tf.clip_by_value 函数的作用是:将元素数值限制在指定的范围内,防止一些错误运算
# 具体是:q 中的元素小于 1e-10 则用 1e-10 代替,大于 1.0 则用 1.0 代替
cross_entropy = -p * tf.log(tf.clip_by_value(q, 1e-10, 1.0))    # 逐元素相乘
sess.run(cross_entropy)
>>> array([ 0.12783338,  0.        ,  0.        ], dtype=float32)

所以yolov3中损失函数为:
Loss=λcoord∑i=0S2∑j=0BIijobj[(xi−x^ij)2+(yi−y^ij)2]+λcoord∑i=0S2∑j=0BIijobj[(wij−w^ij)2+(hij−h^ij)2]−∑i=0S2∑j=0BIijobj[C^ijlog⁡(Cij)+(1−C^ij)log⁡(1−Cij)]−λnoobj∑i=0S2∑j=0BIijnoobj[C^ijlog⁡(Cij)+(1−C^ij)log⁡(1−Cij)]−∑i=0S2Iijobj∑c∈classes([P^ijlog⁡(Pij)+(1−P^ij)log⁡(1−Pij)]Loss=\lambda_{coord} \sum_{i=0}^{S^2} \sum_{j=0}^B {I_{ij}^{obj} [(x_i-\hat x_i^j)^2+ (y_i-\hat y_i^j)^2 ] }+ \\ \lambda_{coord} \sum_{i=0}^{S^2} \sum_{j=0}^B {I_{ij}^{obj} [ ( \sqrt { w_i^j}-\sqrt{\hat w_i^j} )^2+ (\sqrt { h_i^j}-\sqrt{\hat h_i^j})^2 ] }- \\ \sum_{i=0}^{S^2} \sum_{j=0}^B { I_{ij}^{obj} [ \hat C_i^{j} \log (C_i^{j}) + (1- \hat C_i^{j}) \log(1-C_i^{j}) ]} -\\ \lambda_{noobj} \sum_{i=0}^{S^2} \sum_{j=0}^B {I_{ij}^{noobj} [ \hat C_i^{j} \log (C_i^{j}) + (1- \hat C_i^{j}) \log(1-C_i^{j}) ] } -\\\sum_{i=0}^{S^2} { I_{ij}^{obj} } \sum_{c \in {classes}} ([ \hat P_i^{j} \log (P_i^{j}) + (1- \hat P_i^{j}) \log(1-P_i^{j}) ]Loss=λcoord​i=0∑S2​j=0∑B​Iijobj​[(xi​−x^ij​)2+(yi​−y^​ij​)2]+λcoord​i=0∑S2​j=0∑B​Iijobj​[(wij​​−w^ij​​)2+(hij​​−h^ij​​)2]−i=0∑S2​j=0∑B​Iijobj​[C^ij​log(Cij​)+(1−C^ij​)log(1−Cij​)]−λnoobj​i=0∑S2​j=0∑B​Iijnoobj​[C^ij​log(Cij​)+(1−C^ij​)log(1−Cij​)]−i=0∑S2​Iijobj​c∈classes∑​([P^ij​log(Pij​)+(1−P^ij​)log(1−Pij​)]

网格一共是S∗SS*SS∗S个,每个网格产生BBB个候选框anchor box,每个候选框会经过网络最终得到相应的bounding box。最终会得到S∗S∗BS*S*BS∗S∗B个bounding box,那么哪些bounding box会用来计算误差更新权重?又是如何计算误差?需要仔细了解公式。

评论区有一条评论说损失函数有问题:评论如下:
YOLOV3的损失函数应该有一部分错了,从YOLOV2开始,作者发现对于解决不同框大小对于损失函数贡献不一致问题,使用根号宽高的差方误差效果不是很明显,于是还是直接使用box宽高差方误差,但是在该项前面添加了系数(2 - groundtruth.w * groundtruth.h)用来加大对小框的损失。
我没有再去研究这个损失函数了,大家斟酌的看我这个损失吧。

  • 参数IijobjI_{ij}^{obj}Iijobj​
    IijobjI_{ij}^{obj}Iijobj​表示:第iii个网格的第jjj个anchor box是否负责这个object, 如果负责那么Iijobj=1I_{ij}^{obj}=1Iijobj​=1,否则为0。
    那么什么叫做负责呢? 那第iii个网格的BBB个anchor box中与该对象的ground truth box的IOU在所有的anchor box(与一个grid cell中所有bounding box对应,COCO数据集中是9个)与ground truth box的IOU中最大,那它就负责预测这个对象,因为这个形状、尺寸最符合当前这个对象,此时Iijobj=1I_{ij}^{obj}=1Iijobj​=1。
    IijnoobjI_{ij}^{noobj}Iijnoobj​表示iii个网格的第jjj个anchor box不负责该目标。
    论文中是这么规定正负样本的,但是我看代码是,只要目标所在网格产生的9个anchor中和目标的真实框的iou大于阈值的就为正样本,如果都小于阈值,那么和目标iou最大的为正样本。

  • 参数置信度C^ij\hat C_{i}^{j}C^ij​
    训练中,C^ij\hat C_{i}^{j}C^ij​表示真实值,C^ij\hat C_{i}^{j}C^ij​的取值是由grid cell的bounding box有没有负责预测某个对象决定的。如果负责,那么C^ij=1\hat C_{i}^{j}=1C^ij​=1,否则,C^ij=0\hat C_{i}^{j}=0C^ij​=0。
    下面我们来说明如何确定某个grid cell的bounding box是否负责预测该grid cell中的对象:前面在说明anchor box的时候提到每个bounding box负责预测的形状是依据与其对应的anchor box相关的,那这个anchor box与该对象的ground truth box的IOU在所有的anchor box(与一个grid cell中所有bounding box对应,COCO数据集中是9个)与ground truth box的IOU中最大,那它就负责预测这个对象,因为这个形状、尺寸最符合当前这个对象,这时C^ij=1\hat C_{i}^{j}=1C^ij​=1,其他情况下C^ij=0\hat C_{i}^{j}=0C^ij​=0。注意,你没有看错,就是所有anchor box与某个ground truth box的IOU最大的那个anchor box对应的bounding box负责预测该对象,与该bounding box预测的box没有关系。

一项一项分析损失函数

  • 中心坐标误差 ∑i=0S2∑j=0BIijobj[(xij−x^ij)2+(yij−y^ij)2]\sum_{i=0}^{S^2} \sum_{j=0}^B {I_{ij}^{obj} [(x_i^j-\hat x_i^j)^2+ (y_i^j-\hat y_i^j)^2 ] }i=0∑S2​j=0∑B​Iijobj​[(xij​−x^ij​)2+(yij​−y^​ij​)2]首先,通过这篇博客我们可以知道,实际上,网络输出的应当是txt_xtx​和tyt_yty​,然后通过σ(tx)\sigma(t_x)σ(tx​)和σ(ty)\sigma(t_y)σ(ty​),再乘以步长,就映射到了416∗416416*416416∗416大小的图上的目标了,所以在计算误差的时候,其实也是用的这一项σ(tx)∗stride\sigma(t_x)*strideσ(tx​)∗stride和σ(ty)∗stride\sigma(t_y)*strideσ(ty​)∗stride和真实目标经过resize到416∗416416*416416∗416上的目标的大小,去计算误差。
    整个这一项表示的是:当第iii个网格的第jjj个anchor box负责某一个真实目标时,那么这个anchor box所产生的bounding box就应该去和真实目标的box去比较,计算得到中心坐标误差。

  • 宽高坐标误差:∑i=0S2∑j=0BIijobj[(wij−w^ij)2+(hij−h^ij)2]\sum_{i=0}^{S^2} \sum_{j=0}^B {I_{ij}^{obj} [ ( \sqrt { w_i^j}-\sqrt{\hat w_i^j} )^2+ (\sqrt { h_i^j}-\sqrt{\hat h_i^j})^2 ] }i=0∑S2​j=0∑B​Iijobj​[(wij​​−w^ij​​)2+(hij​​−h^ij​​)2]首先,通过这篇博客我们可以知道,实际上,网络输出的应当是(tw)(t_w)(tw​)和(th)(t_h)(th​),所以在计算误差的时候,其实也是用的这一项(tw)∗stride(t_w)*stride(tw​)∗stride和(th)∗stride(t_h)*stride(th​)∗stride和真实目标经过resize之后的值,去计算误差的。所以可以认为公式里的wiw_iwi​就是(tw)∗stride(t_w)*stride(tw​)∗stride等等。
    整个这一项表示的是:当第iii个网格的第jjj个anchor box负责某一个真实目标时,那么这个anchor box所产生的bounding box就应该去和真实目标的box去比较,计算得到宽高的误差。

  • 置信度误差 −∑i=0S2∑j=0BIijobj[C^ijlog⁡(Cij)+(1−C^ij)log⁡(1−Cij)]−λnoobj∑i=0S2∑j=0BIijnoobj[C^ijlog⁡(Cij)+(1−C^ij)log⁡(1−Cij)]- \sum_{i=0}^{S^2} \sum_{j=0}^B { I_{ij}^{obj} [ \hat C_i^{j} \log (C_i^{j}) + (1- \hat C_i^{j}) \log(1-C_i^{j}) ]} \\ -\lambda_{noobj} \sum_{i=0}^{S^2} \sum_{j=0}^B {I_{ij}^{noobj} [ \hat C_i^{j} \log (C_i^{j}) + (1- \hat C_i^{j}) \log(1-C_i^{j}) ] }−i=0∑S2​j=0∑B​Iijobj​[C^ij​log(Cij​)+(1−C^ij​)log(1−Cij​)]−λnoobj​i=0∑S2​j=0∑B​Iijnoobj​[C^ij​log(Cij​)+(1−C^ij​)log(1−Cij​)]首先需要知道,置信度误差使用交叉熵来表示。另外需要清楚不管anchor box是否负责某个目标,都会计算置信度误差。因为置信度表示:框出的box内确实有物体的自信程度和框出的box将整个物体的所有特征都包括进来的自信程度。具体可以参考博客。
    损失函数分为两部分:有物体,没有物体,其中没有物体损失部分还增加了权重系数。添加权重系数的原因是,对于一幅图像,一般而言大部分内容是不包含待检测物体的,这样会导致没有物体的计算部分贡献会大于有物体的计算部分,这会导致网络倾向于预测单元格不含有物体。因此,我们要减少没有物体计算部分的贡献权重,比如取值为:0.5。

下面我们来说明如何确定某个grid cell的bounding box是否负责预测该grid cell中的对象:前面在说明anchor box的时候提到每个bounding box负责预测的形状是依据与其对应的anchor box(bounding box prior)相关的,那这个anchor box与该对象的ground truth box的IOU在所有的anchor box(与一个grid cell中所有bounding box对应,COCO数据集中是9个)与ground truth box的IOU中最大,那它就负责预测这个对象.

  • 第一项是:存在对象的bounding box的置信度误差。带有IijobjI_{ij}^{obj}Iijobj​意味着只有"负责"(IOU比较大)预测的那个bounding box的置信度才会计入误差。

另外,这里有个例外,当某个bounding box不负责对应grid cell中ground truth box的预测,但是又与该ground truth box的IOU大于设定的阈值时(论文中是0.5,darknet中针对COCO数据集使用的是0.7),忽略该bounding box所有输出的对loss的误差贡献,包括置信度误差。其他情况(负责某个对象即IOU最大的,不负责对象即IOU不是最大,而且IOU<0.5)要计算置信度误差。

  • 第二项是:不存在对象的bounding box的置信度误差。因为不存在对象的bounding box应该老老实实的说"我这里没有对象",也就是输出尽量低的置信度。如果它不恰当的输出较高的置信度,会与真正"负责"该对象预测的那个bounding box产生混淆。其实就像对象分类一样,正确的对象概率最好是1,所有其它对象的概率最好是0。

  • 分类误差−∑i=0S2Iijobj∑c∈classes([P^ijlog⁡(Pij)+(1−P^ij)log⁡(1−Pij)]- \sum_{i=0}^{S^2} { I_{ij}^{obj} } \sum_{c \in {classes}} ([ \hat P_i^{j} \log (P_i^{j}) + (1- \hat P_i^{j}) \log(1-P_i^{j}) ]−i=0∑S2​Iijobj​c∈classes∑​([P^ij​log(Pij​)+(1−P^ij​)log(1−Pij​)]首先需要知道分类误差也是选择了交叉熵作为损失函数。当第iii个网格的第jjj个anchor box负责某一个真实目标时,那么这个anchor box所产生的bounding box才会去计算分类损失函数。

训练的时候,我们是知道某一图片中目标的真实框的x,y,w,hx,y,w,hx,y,w,h,以及置信度confidence(1或0)和分类概率P(i)P(i)P(i)([1,0,0,0,0…]、[0,1,0,0,0…])。
当第iii个网格的第jjj个anchor box负责某一真实目标时,我们需要对这个anchor box产生的bounding box进行 求中心坐标误差,求宽高误差,求置信度误差,求分类误差。(因为这个anchor box负责了某一个目标,那么这个anchor box产生的bounding box自然很重要,计算所有的损失函数,用来更新权重)
其他的不对真实目标负责的anchor box所产生的bounding box,只需要求一个置信度误差就可以了。
(因为这个anchor box不负责目标,那么这个anchor box产生的bounding box的坐标,宽高,分类都不重要,也就不需要计算坐标,宽高,分类的损失函数,但是置信度仍然重要,因为置信度还可以表示这个anchor box产生的bounding box中并不包含对象,所以仍然需要计算置信度损失函数的。)

参考:

yolov3的损失函数公式
交叉熵简单理解
为什么交叉熵可以作为机器学习的损失函数
yolov3一些参数的理解以及损失函数公式
损失函数yolov123的变化

【论文理解】yolov3损失函数相关推荐

  1. 你对YOLOV3损失函数真的理解正确了吗?

    1. 前言 昨天行云大佬找到我提出了他关于GiantPandaCV公众号出版的<从零开始学YOLOV3>电子书中关于原版本的YOLOV3损失的一个质疑,并给出了他的理解.昨天晚上我仔细又看 ...

  2. 【论文理解】理解yolov3的anchor、置信度和类别概率

    以前写过一篇博客,都是转载其余博主的内容,对yolov3有了基本认识,但是当时只浮于表面,并没有真正的理解yolov3,现在对于yolov3的anchor计算,损失函数的计算有了一些新的理解,记录一下 ...

  3. DL之YoloV3:YoloV3论文《YOLOv3: An Incremental Improvement》的翻译与解读

    DL之YoloV3:YoloV3论文<YOLOv3: An Incremental Improvement>的翻译与解读 目录 YoloV3论文翻译与解读 Abstract 1. Intr ...

  4. 论文理解【RL - Exp Replay】—— 【ReMERN ReMERT】Regret Minimization Exp Replay in Off-Policy RL

    标题:Regret Minimization Experience Replay in Off-Policy Reinforcement Learning 文章链接:Regret Minimizati ...

  5. InfoGAN论文理解及复现

    InfoGAN论文理解及复现 by AHU Random_Walker 主要从四个方面来了解相关工作,即 Motivation Related Work-Method Experiments Conc ...

  6. Focal Loss 论文理解及公式推导

    原文:Focal Loss 论文理解及公式推导 - AIUAI 题目: Focal Loss for Dense Object Detection - ICCV2017 作者: Tsung-Yi, L ...

  7. 论文理解【RL - Exp Replay】—— 【LFIW】Experience Replay with Likelihood-free Importance Weights

    标题:Experience Replay with Likelihood-free Importance Weights 文章链接:An Equivalence between Loss Functi ...

  8. A Learned Representation for Artistic Style论文理解

    A Learned Representation for Artistic Style论文理解 这篇论文是在Perceptual losses for real-time style transfer ...

  9. 图卷积网络进行骨骼识别代码_【骨骼行为识别】2s-AGCN论文理解

    Two-Stream Adaptive Graph Convolutional Networks for Skeleton-Based Action Recognition 论文链接: https:/ ...

最新文章

  1. 记一次网站部署遇到的问题
  2. FPGA之道(33)Verilog数据类型
  3. python几岁开始学_python编程少儿几岁可以学?有哪些优势?
  4. 一分钟开启Tomcat https支持
  5. oracle 12.2.0.1 搭建 active dataguard
  6. Java—Iterator接口介绍及使用
  7. python网络-多线程(22)
  8. 亲自动手用HTK实现YES NO孤立词识别
  9. 多硬盘分区格式化及挂载
  10. 对null值的小知识
  11. windows服务初识
  12. 【预测模型】Gompertz 曲线方程预测
  13. 打印图形输出三角形 *
  14. “分集”与“复用”辨析
  15. Learn C++学习笔记:第M章—最常用的智能指针:std::unique_ptr std::make_unique
  16. CVPR2022Oral专题系列(一):低光增强
  17. 视频播放器 layui-ckplayer
  18. CSV是什么文件格式
  19. 【Debug】安装labelme过程中出现的问题
  20. Everypixel –图库图片设计师的搜索引擎

热门文章

  1. 荷兰华侨新天地:海牙小龙虾泛滥 政府头痛不已
  2. Flutter开发环境在Mac上的搭建(iOS和Android图文详细过程)
  3. 搭建Gitolite
  4. 第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-983 最大获利
  5. 天源迪科笔试20121115
  6. 变形金刚插曲Baby ComeBack
  7. webshell检测方式深度剖析 --- 行业内的实践方案
  8. Python环境安装Spyder
  9. 非单文件组件和单文件组件区别
  10. 计算机办公软件应用期末考试,办公软件应用期末考试试题