深度理解YOLOV3损失函数
本博客为本人学习YOLOV3过程中所作笔记,为本人自己理解,本人并非大佬,固可能有理解错误之处,欢迎大家指正。
前言
从阅读YOLO系列论文我们知道其损失函数大致一样,都为box的中心点误差、框大小误差、置信度误差、不存在box时置信度误差、分类的误差的和,但是YOLO每一代损失函数公式都有一些改变,其中YOLOV3其损失函数具体公式为:
1、损失函数分析
下面我们先来对其中每一项来进行分析,对其有一个大概认识。
1.1、矩形框中心点误差
−
λ
c
o
o
r
d
Σ
i
=
0
S
2
Σ
j
=
0
B
I
i
j
o
b
j
[
x
^
i
j
log
(
x
i
j
)
+
(
1
−
x
^
i
j
)
log
(
1
−
x
i
j
)
+
y
^
i
j
log
(
y
i
j
)
+
(
1
−
y
^
i
j
)
log
(
1
−
y
i
j
)
]
-{\lambda _{coord}}\mathop \Sigma \limits_{i = 0}^{{S^2}} \mathop \Sigma \limits_{j = 0}^B I_{ij}^{obj}\left[ {\hat x_i^j\log \left( {x_i^j} \right) + \left( {1 - \hat x_i^j} \right)\log \left( {1 - x_i^j} \right) + \hat y_i^j\log \left( {y_i^j} \right) + \left( {1 - \hat y_i^j} \right)\log \left( {1 - y_i^j} \right)} \right]
−λcoordi=0ΣS2j=0ΣBIijobj[x^ijlog(xij)+(1−x^ij)log(1−xij)+y^ijlog(yij)+(1−y^ij)log(1−yij)]
其中
(
x
i
j
,
y
i
j
)
\left( {x_i^j,y_i^j} \right)
(xij,yij)是网络预测的矩形框中心坐标,
(
x
^
i
j
,
y
^
i
j
)
\left( {\hat x_i^j,\hat y_i^j} \right)
(x^ij,y^ij)是标记矩形框的中心坐标,
I
i
j
o
b
j
I_{ij}^{obj}
Iijobj 表示该矩形框是否负责预测一个目标物体,如果该矩形框负责预测一个目标则其大小为1,否则等于0。
λ
c
o
o
r
d
{\lambda _{coord}}
λcoord 是用来协调不同大小矩形框对误差函数贡献不一致所设置的一个协调系数,其大小等于
λ
c
o
o
r
d
=
(
2
−
w
^
i
j
∗
h
^
i
j
)
{\lambda _{coord}} = \left( {2 - \hat w_i^j{\rm{*\hat h}}_i^j} \right)
λcoord=(2−w^ij∗h^ij),当矩形框的大小比较小时,这个系数就更大,从而增大了小矩形框对损失函数的贡献,相反当矩形框比较大时,该系数也就更小,从而消减了大矩形框对损失函数的贡献。因此,该函数计算了所有网格(i=0,∙∙∙,S^2 )内的每一个矩形框(j=0,∙∙∙,B)的中心坐标位置与标记框交叉熵误差损失总和。
1.2、预测框宽高误差
λ
c
o
o
r
d
1
2
Σ
i
=
0
S
2
Σ
j
=
0
B
I
i
j
o
b
j
[
(
w
i
j
−
w
^
i
j
)
2
+
(
h
i
j
−
h
^
i
j
)
2
]
{\lambda _{coord}}\frac{1}{2}\mathop \Sigma \limits_{i = 0}^{{S^2}} \mathop \Sigma \limits_{j = 0}^B I_{ij}^{obj}\left[ {{{\left( {w_i^j - \hat w_i^j} \right)}^2} + {{\left( {{\rm{h}}_i^j - {\rm{\hat h}}_i^j} \right)}^2}} \right]
λcoord21i=0ΣS2j=0ΣBIijobj[(wij−w^ij)2+(hij−h^ij)2]
其中
(
w
i
j
,
h
i
j
)
\left( {w_i^j,h_i^j} \right)
(wij,hij)为网络预测的矩形框宽高大小,
(
w
^
i
j
,
h
^
i
j
)
\left( {\hat w_i^j,\hat h_i^j} \right)
(w^ij,h^ij)是标记矩形框的宽高大小,同样这里为了协调不同大小矩形框对误差函数贡献不一致设置了参数
λ
c
o
o
r
d
{\lambda _{coord}}
λcoord。该函数计算了所有预测矩形框的宽高与标记框宽高求和平方误差损失总和。
1.3、预测框置信度损失
−
Σ
i
=
0
S
2
Σ
j
=
0
B
I
i
j
o
b
j
[
C
^
i
j
log
(
C
i
j
)
+
(
1
−
C
^
i
j
)
log
(
1
−
C
i
j
)
]
−
λ
n
o
o
b
j
Σ
i
=
0
S
2
Σ
j
=
0
B
I
i
j
n
o
o
b
j
[
C
^
i
j
log
(
C
i
j
)
+
(
1
−
C
^
i
j
)
log
(
1
−
C
i
j
)
]
- \mathop \Sigma\limits_{i = 0}^{{S^2}} \mathop \Sigma \limits_{j = 0}^B I_{ij}^{obj}\left[ {\hat C_i^j\log \left( {C_i^j} \right) + \left( {1 - \hat C_i^j} \right)\log \left( {1 - C_i^j} \right)} \right] - {\lambda _{noobj}}\mathop \Sigma \limits_{i = 0}^{{S^2}} \mathop \Sigma \limits_{j = 0}^B I_{ij}^{noobj}\left[ {\hat C_i^j\log \left( {C_i^j} \right) + \left( {1 - \hat C_i^j} \right)\log \left( {1 - C_i^j} \right)} \right]
−i=0ΣS2j=0ΣBIijobj[C^ijlog(Cij)+(1−C^ij)log(1−Cij)]−λnoobji=0ΣS2j=0ΣBIijnoobj[C^ijlog(Cij)+(1−C^ij)log(1−Cij)]
其中
C
i
j
C_i^j
Cij为预测框内含有目标物体的概率得分,
C
^
i
j
\hat C_i^j
C^ij表示真实值,
C
^
i
j
\hat C_i^j
C^ij的取值由第
(
i
,
j
)
\left( {i,j} \right)
(i,j)个矩形框是否负责预测某一个矩形框决定,如果负责,那么
C
^
i
j
=
1
\hat C_i^j = 1
C^ij=1,否则,
C
^
i
j
=
0
\hat C_i^j = 0
C^ij=0。
I
i
j
n
o
o
b
j
I_{ij}^{noobj}
Iijnoobj等于
(
1
−
I
i
j
o
b
j
)
\left( {1 - I_{ij}^{obj}} \right)
(1−Iijobj),表示如果该矩形框不负责预测一个目标则其大小为1,否则等于0。
λ
n
o
o
b
j
{\lambda _{noobj}}
λnoobj为一个权重值,表示当预测框没有预测到目标时,其置信度误差在损失函数中所占权重,由于对于一副图像,一般而言其大部分内容是不含有待检测的物体,这样会导致没有物体的计算部分贡献会大于有物体的计算部分,从而导致网络倾向于预测单元格中不含有物体,因此,我们需要减少没有物体计算部分的贡献权重,
λ
n
o
o
b
j
{\lambda _{noobj}}
λnoobj往往取值0.5。
1.4、预测框类别损失
−
Σ
i
=
0
S
2
Σ
j
=
0
B
I
i
j
o
b
j
Σ
c
∈
c
l
a
s
s
e
s
[
P
^
i
,
c
j
log
(
P
i
,
c
j
)
+
(
1
−
P
^
i
,
c
j
)
log
(
1
−
P
i
,
c
j
)
]
- \mathop \Sigma\limits_{i = 0}^{{S^2}} \mathop \Sigma\limits_{j = 0}^B I_{ij}^{obj}\mathop \Sigma\limits_{c \in classes} \left[ {\hat P_{i,c}^j\log \left( {P_{i,c}^j} \right) + \left( {1 - \hat P_{i,c}^j} \right)\log \left( {1 - P_{i,c}^j} \right)} \right]
−i=0ΣS2j=0ΣBIijobjc∈classesΣ[P^i,cjlog(Pi,cj)+(1−P^i,cj)log(1−Pi,cj)]
方程式中
P
i
,
c
j
P_{i,c}^j
Pi,cj表示第
(
i
,
j
)
\left( {i,j} \right)
(i,j)预测框属于类别c的概率,
P
^
i
,
c
j
\hat P_{i,c}^j
P^i,cj表示标记框所属类别真实值,如果属于第c类,则其大小等于1,否则为0。
2、损失函数中参数是怎样计算来的
在YOLOV3中,神经网络的输出值并不是直接参与损失函数的计算,因为网络输出值并不直接表示预测框的中心点坐标和框的宽高值,而是相对anchor box的偏移量和尺度缩放大小。在实际的神经网络输出数据中,其输出参数形状往往是 [ S , S , B × ( 5 + c l a s s e s ) ] \left[ {S,S,B \times \left( {5 + classes} \right)} \right] [S,S,B×(5+classes)],其中5是代表矩形框的2个中心坐标信息、2个宽高信息、1个置信度信息;B代表anchor的个数,S表示输出特征网格尺寸,classes表示类别数目。这里分别用参数 t x , t y , t w , t h {t_x},{t_y},{t_w},{t_{\rm{h}}} tx,ty,tw,th 表示网络直接输出的预测矩形框空间偏移量和缩放信息值。下面我们具体了解损失函数中各项参数是怎样得到的。
2.1、损失函数中 x ^ , y ^ , w ^ , h ^ \hat x,\hat y,\hat w,\hat h x^,y^,w^,h^参数的获取
在模型训练过程中,我们的ground truth往往是相对于原始图像的四个坐标值,表示bounding box的左上和右下点坐标,而这是肯定不能直接用于模型训练,通过前面边框预测公式我们可以知道,我们需要将ground truth转换成网络模型输出值相同的类型(即:包含标记框中心点相对于anchor box的偏移量和标记框相对于anchor box的尺度变换),因此我们需要经过以下步骤:
步骤一:将原始标记框按原始图像到416×416尺寸变换比例同比例缩放到符合416×416尺寸的大小(简单说就是因为网络输入是416×416大小,所以输入图像会先reshape到这个尺寸,这时要将标记框也同比例进行缩放),然后计算标记框中心点坐标和宽高值。
步骤二:计算标记框在feature map上的中心点坐标和宽高值。将上一步得到的标记框中心点坐标和宽高值都除以stride(比如feature map为13×13,此时stride=416/13=32),得到标记框在feature map上位置信息
G
x
,
G
y
,
G
w
,
G
h
{G_x},{G_y},{G_w},{G_{\rm{h}}}
Gx,Gy,Gw,Gh
步骤三:计算标记框相对于anchor box的偏移量和尺度缩放大小。使用下面公式:
x
^
=
G
x
−
C
x
\hat x = {G_x} - {C_x}
x^=Gx−Cx
y
^
=
G
y
−
C
y
\hat y = {G_y} - {C_y}
y^=Gy−Cy
w
^
=
l
o
g
(
G
w
/
P
w
)
\hat w = {\rm{log}}\left( {{G_w}/{P_w}} \right)
w^=log(Gw/Pw)
h
^
=
l
o
g
(
G
h
/
P
h
)
{\rm{\hat h}} = {\rm{log}}\left( {{G_{\rm{h}}}/{P_{\rm{h}}}} \right)
h^=log(Gh/Ph)
其中
C
x
,
C
y
{C_x},{C_y}
Cx,Cy为feature map上grid cell左上角坐标,
P
w
,
P
h
{P_w},{P_{\rm{h}}}
Pw,Ph为anchor box在feature map上宽高大小,通过将标记框宽高与anchor box宽高比值的对数计算它们的缩放比例,通过取对数而不是直接预测相对形变
G
w
/
P
w
{G_w}/{P_w}
Gw/Pw,是因为如果直接计算相对形变,那么要求预测w值要大于0,因为你的框的宽高不可能为负数,因此,该问题变成一个有不等式条件约束的优化问题,没法直接用SGD来做,所以先取一个对数变换将这个不等式约束去掉就可以了。
至此,我们对标记框的偏移量和尺度缩放大小就求出来了,损失函数里面就可以使用
x
^
,
y
^
,
w
^
,
h
^
\hat x,\hat y,\hat w,{\rm{\hat h}}
x^,y^,w^,h^作为标记框数据参与运算了。
2.2、损失函数中 x , y , w , h x,y,w,h x,y,w,h参数的获取
在边框预测公式中我们可以了解到网络的输出是可以代表预测框偏移量和尺度缩放大小的,但是这里还是要注意一下,网络输出
t
x
,
t
y
{t_x},{t_y}
tx,ty由于不在0-1范围内(网络输出层激活函数为线性激活函数),跟ground truth的范围不一致,这里就需要经过sigmoid函数使得其偏移量在0-1之间,因此损失函数中参数
x
,
y
,
w
,
h
x,y,w,h
x,y,w,h由下列公式获得:
x
=
σ
(
t
x
)
x = \sigma ({t_x})
x=σ(tx)
y
=
σ
(
t
y
)
y = \sigma ({t_y})
y=σ(ty)
w
=
t
w
w = {t_w}
w=tw
h
=
t
h
{\rm{h}} = {t_{\rm{h}}}
h=th
由此获得了损失函数中的参数
x
,
y
,
w
,
h
x,y,w,h
x,y,w,h。
2.3、损失函数中的置信度C和P的获取
你也许会问置信度和类概率不是直接就是网络输出的参数吗?其实我们想一下,网络输出其实不是0-1的范围,所以我们还是需要将其归一化到0-1范围内,跟之前处理方法一样,使用一个sigmoid函数即可:
C
=
s
i
g
m
o
i
d
(
C
)
C = sigmoid\left( C \right)
C=sigmoid(C)
P
=
s
i
g
m
o
i
d
(
P
)
P = sigmoid\left( P \right)
P=sigmoid(P)
至于标记框的
C
^
\hat C
C^就更简单,如果含有标记框则为1,否则直接等于0,同时对于
P
^
\hat P
P^也一样,将标记框相应类别概率设为1,其他设置为0即可。
2.4、损失函数中参数 I i j o b j I_{ij}^{obj} Iijobj和 I i j n o o b j I_{ij}^{noobj} Iijnoobj的获取
在损失函数定义时解释过,
I
i
j
o
b
j
I_{ij}^{obj}
Iijobj表示该矩形框是否负责预测一个目标物体,如果该矩形框负责预测一个目标则其大小为1,否则等于0,
I
i
j
n
o
o
b
j
I_{ij}^{noobj}
Iijnoobj则跟其相反。所以我们这里就需要确定一个预测框是否负责预测一个目标,怎么确定呢?
首先对于feature map中那些grid cell上没有ground truth的预测框,我们直接就可以认定其为noobj,此时将
I
i
j
o
b
j
=
0
I_{ij}^{obj} = 0
Iijobj=0即可。而对于那些含有ground truth的grid cell,我们知道一个尺度的feature map有三个anchors,也就是说现在有三个备选预测框,YOLOV3假定每个cell至多含有一个ground truth,在实际情况中,其实基本也不会出现多于1个的情况,所以我们怎样确定选哪个预测框来预测这个物体呢?这需要在训练中确定,即由那个与ground truth标记框的IOU值最大的预测框预测它,此时
I
i
j
o
b
j
=
1
I_{ij}^{obj} = 1
Iijobj=1,而剩余的不与该grund truth匹配,此时
I
i
j
o
b
j
=
0
I_{ij}^{obj} = 0
Iijobj=0。
3、边框预测公式
我们知道网络的输出值
t
x
,
t
y
,
t
w
,
t
h
{t_x},{t_y},{t_w},{t_{\rm{h}}}
tx,ty,tw,th并不能直接反应预测框的空间信息,而是需要通过一定变换得到,作者使用了下面公式来获取在特征图上预测矩形框,其实这也可以通过之前计算标记框相对偏移量和尺度变换公式中获得:
b
x
=
σ
(
t
x
)
+
c
x
{b_x} = \sigma \left( {{t_x}} \right) + {c_x}
bx=σ(tx)+cx
b
y
=
σ
(
t
y
)
+
c
y
{b_y} = \sigma \left( {{t_y}} \right) + {c_y}
by=σ(ty)+cy
b
w
=
p
w
e
t
w
{b_w} = {p_w}{e^{{t_w}}}
bw=pwetw
b
h
=
p
h
e
t
h
{b_{\rm{h}}} = {p_{\rm{h}}}{e^{{t_{\rm{h}}}}}
bh=pheth
其中,
(
c
x
,
c
y
)
({c_x},{c_y})
(cx,cy)代表特征图中当前位置相对左上角网格偏移的网格数坐标,
σ
(
)
\sigma \left( {\rm{\;}} \right)
σ()是sigmoid函数,其作用是将坐标归一化到0~1之间,
(
p
w
,
p
h
)
({p_w},{p_{\rm{h}}})
(pw,ph)是预设的anchor box映射到特征图中的宽高。所以
b
x
{b_x}
bx、
b
y
{b_y}
by值是预测框在feature map上的中心点坐标,
b
w
{b_w}
bw、
b
h
{b_{\rm{h}}}
bh是预测框在feature map上宽高值。所以,通过网络输出值
t
x
,
c
y
,
t
w
,
t
h
{t_x},{c_y},{t_w},{t_{\rm{h}}}
tx,cy,tw,th我们就可以得到预测框在feature map上的中心点坐标和宽高值
c
x
,
c
y
,
p
w
,
p
h
{c_x},{c_y},{p_w},{p_{\rm{h}}}
cx,cy,pw,ph。(这里再说明一点:网络输出值例如
t
x
{t_x}
tx由于其输出层使用的是线性激活函数,所以其大小范围并不在0-1之间,所以需要通过sigmoid函数将坐标归一化到0-1之间,使得预测框中心点始终在该网格内,而不至于落在其他网格中去)。
因此我们可以获得预测框在feature map上的中心点坐标和宽高大小,为了能够方便将预测框还原到原图尺寸,往往我们再对其进行归一化可以得到归一化的预测框:
b
x
=
(
σ
(
t
x
)
+
c
x
)
/
W
{b_x} = \left( {\sigma \left( {{t_x}} \right) + {c_x}} \right)/W
bx=(σ(tx)+cx)/W
b
y
=
(
σ
(
t
y
)
+
c
y
)
/
H
{b_y} = \left( {\sigma \left( {{t_y}} \right) + {c_y}} \right)/H
by=(σ(ty)+cy)/H
b
w
=
(
p
w
e
t
w
)
/
W
{b_w} = \left( {{p_w}{e^{{t_w}}}} \right)/W
bw=(pwetw)/W
b
h
=
(
p
h
e
t
h
)
/
H
{b_{\rm{h}}} = \left( {{p_{\rm{h}}}{e^{{t_{\rm{h}}}}}} \right)/H
bh=(pheth)/H
其中W,H分别代表feature map的尺寸大小,比如最后输出feature map为13×13,则W=13,H=13。这样我们得到了正对于输入图片416×416的归一化预测框,但是我们原图往往不是416×416大小,是经过了reshape到416尺寸的操作,所以我们还需要将得到的归一化预测框reshape回去到符合原图尺寸比例的归一化预测框,然后直接乘以原图尺寸大小就可以得到最终的预测框。
4、总结
至此,我们已经讨论完了YOLOV3损失函数和从预测结果中获取预测框,其实对于YOLOV3,其最重要两部分就是网络结构和损失函数的计算,网络结构无非就是各种卷积神经网络嵌套,这部分对于大多数神经网络来说其实看不出很多太大区别或者说创新点,而YOLOV3最具有特色的就是其损失函数,包括其对各部分损失函数的定义和ground truth的处理,只要理解了这些,差不多就对YOLOV3有了个比较深的认识,而最后所提的预测框的获取其实也是建立在之前对偏移量,尺度变换这些前提之下的后续工作。
参考:
1、【论文理解】yolov3损失函数
2、史上最详细的Yolov3边框预测分析
3、深入理解目标检测与YOLO(从v1到v3)
4、《基于深度学习的细胞计数研究》硕士论文