目标检测 One Stage Detection (Yolo系列下)
- 因为YoloV4信息量其实是比较大的,但是创新点确实是比较少。所以把它单独拿出来讲。其中还有很多的优化和网络参数的调节技巧。
YoloV4:
- 很可惜,Joe Sir退出了CV界,虽然Yolo系列仍然在更新,但是还是不免有些寂寞了。YoloV4的更新主要是有以下几个方面:数据増广方面,还有模型Module方面,把CBN改成了CmBN,小改了一下SAM和PAN,之后加了各种trick。
数据増广:
1. Mixup:
-
其实就是把原图的像素乘以权重相加而已,只需要将两张图片混合起来就可以了,当然标签也要进行混合。真是一个新奇的思路
x ~ = λ x i + ( 1 − λ ) x j , where x i , x j are raw input vectors y ~ = λ y i + ( 1 − λ ) y j , where y i , y j are one-hot label encodings \begin{array}{ll}\tilde{x}=\lambda x_{i}+(1-\lambda) x_{j}, & \text { where } x_{i}, x_{j} \text { are raw input vectors } \\ \tilde{y}=\lambda y_{i}+(1-\lambda) y_{j}, & \text { where } y_{i}, y_{j} \text { are one-hot label encodings }\end{array} x~=λxi+(1−λ)xj,y~=λyi+(1−λ)yj, where xi,xj are raw input vectors where yi,yj are one-hot label encodings
-
混合的时候并不需要把整个dataset的东西混合起来,只需要在某一个batch里面的数据做混合就可以了。整个数据集打乱混合的效果和在一个batch里面打乱混合的效果其实是一样的。
-
在混合的时候最好把不同标签的img进行混合。不然就没有什么提高
-
精度的提高主要指分类的精度的提高。
2. Cutout:
- 在进行裁剪之前,首先要进行Normalize,这样子会少掉很多不必要的potential effect
- 在裁剪的时候发现,其实裁剪下来的大小对准确率的影响远大于裁剪的形状的影响。
- 当然,这个方法真的是太简单了,很可能会擦除掉一些有用的信息,反而不利于训练
3. Cutmix:
- 或许哪一天我做噩梦会梦见这个图片,因为真的太吓人了。
- 主要就是Cutout加上Mixup,它的效果会比单独的Mixup效果更好。它采用了cutout的局部融合思想,并且采用了mixup的混合label策略,看起来比较make sense。
- cutmix和mixup的区别是,其混合位置是采用0-1掩码,相当于新合成的两张图是来自两张图片的紧密结合,而不是Mixup的线性组合。但是其label还是和mixup一样是线性组合。作者认为mixup的缺点是,它会让图片变得ambiguous,然后模型会看懵逼。原来模型也不想看这种四不像的东西。
- 在拼接的时候,2张图片就够了。
-
x
~
=
M
⊙
x
A
+
(
1
−
M
)
⊙
x
B
\tilde{x}=\mathbf{M} \odot x_{A}+(\mathbf{1}-\mathbf{M}) \odot x_{B}
x~=M⊙xA+(1−M)⊙xB
y ~ = λ y A + ( 1 − λ ) y B \tilde{y}=\lambda y_{A}+(1-\lambda) y_{B} y~=λyA+(1−λ)yB 其中M是和原图大小一样的矩阵,是一个mask
4. Mosaic:
-
数据増广其实还可以是4张完整图片拼接在一起,四张图片看起来就比较不会吓人了。
-
主要是增大了背景的复杂程度,增加了背景复杂程度,增加了batch_size。
-
因为一张图片里面有4张图像。即使是四张完全不同的图,位置不一样,顺序不一样。小batch也能有大batchsize的效果。
5. Disturb Label:
- 这个就比较奇葩了,说故意标错一定量的label会对模型训练是有益的。为什么是这样呢?因为这个可以等价为对输入模型的増广。
6. Dropblock:
-
由于dropBlock其实是dropout在卷积层上的推广,它是如何进行操作的呢?
-
如图像所示,它以图像的某几个点为中心,然后出去它们周围的像素块。为什么不单单去掉这个像素块本身呢?这是因为卷积时其实参数是共享的,这个像素的周围的像素其实就可以对去掉的像素进行推断,模型可以搞定这个像素块的信息还原。然而如果去掉它周围一片,株连九族之后,记得这个像素块的像素就很少了。
-
之后用高斯分布生成一个mask,其中 mask i , j < γ \operatorname{mask}_{i, j}<\gamma maski,j<γ 的话,就直接把它周围的点全部drop掉。
-
mask i , j = 0 , mask i , j < γ \operatorname{mask}_{i, j}=\mathbf{0}, \quad \operatorname{mask}_{i, j}<\gamma maski,j=0,maski,j<γ
mask i , j = 1 , \operatorname{mask}_{i, j}=1, \quad maski,j=1, mask i , j ≥ γ _{i, j} \geq \gamma i,j≥γ
激活函数:
1. ReLU的Rethinking:
- 好处:不会产生梯度消失的现象,BP的时候不需要运算,forward也很快。
- 坏处:
-
在零点的时候连续不可导,会产生什么问题呢?在下降的时候很有可能会陷入到局部极小值中。
-
会有信息的损失:在小于0的时候会丢失。
-
non_zero centered, zigzag when bp: zero centered并不是一段0为均值(如(-5,5))就是zero center。zero center真实的理解就是:中间有0(如(-2,5))就是zerocenter。
-
Relu的BP公式是:
-
f = ∑ w i x i + b , x i > 0 ( x i f=\sum w_{i} x_{i}+b, \quad x_{i}>0\left(x_{i}\right. f=∑wixi+b,xi>0(xi is activated ) ) )
∂ f ∂ w i = x i > 0 \frac{\partial f}{\partial w_{i}}=x_{i}> 0 ∂wi∂f=xi>0
∂ L ∂ w i = ∂ L ∂ f ∂ f ∂ w i = ∂ L ∂ f x i \frac{\partial L}{\partial w_{i}}=\frac{\partial L}{\partial f} \frac{\partial f}{\partial w_{i}}=\frac{\partial L}{\partial f} x_{i} ∂wi∂L=∂f∂L∂wi∂f=∂f∂Lxi
∵ x i > 0 \because x_{i}>0 ∵xi>0
∴ sign ( ∂ L ∂ f ) = sign ( ∂ L ∂ w i ) , w i \therefore \operatorname{sign}\left(\frac{\partial L}{\partial f}\right)=\operatorname{sign}\left(\frac{\partial L}{\partial w_{i}}\right), w_{i} ∴sign(∂f∂L)=sign(∂wi∂L),wi moves along same direction -
这样dL/dF的符号即是dL/w的符号。我们的目的是对全部的w求导,也就是说只要是w他们的符号已经被统一了,这样的话,所有的w都只能朝着一个方向移动。很多的w只朝着一个方向移动,有点凉凉啊。
-
从蓝色的点在初始点,要进到target。如果往target走的话,直线走的话,一个w往正方向,另一个是w是负方向,就不可能。现在只能进行迂回战术,先向左下走,太惨了。这个图一直绕,训练起来会比较慢。走的路长,就很可能会进入局部极小值,如果局部极小值不可导,那你就很爽了,估计就出不来了。
-
2. switch:
- f ( x ) = x ∗ σ ( x ) f(x)=x* {σ}(x) f(x)=x∗σ(x) 这就是公式,注意一下求导就可以了
-
f
′
(
x
)
f^{\prime}(x)
f′(x)
=
σ
(
x
)
+
x
⋅
σ
(
x
)
⋅
(
1
−
σ
(
x
)
)
=\sigma(x)+x \cdot \sigma(x) \cdot(1-\sigma(x))
=σ(x)+x⋅σ(x)⋅(1−σ(x))
= x ⋅ σ ( x ) + σ ( x ) ( 1 − x ⋅ σ ( x ) ) =x \cdot \sigma(x)+\sigma(x)(1-x \cdot \sigma(x)) =x⋅σ(x)+σ(x)(1−x⋅σ(x))
= f ( x ) + σ ( x ) ⋅ ( 1 − f ( x ) ) =f(x)+\sigma(x) \cdot(1-f(x)) =f(x)+σ(x)⋅(1−f(x)) - 下沿是有边界的。非单调的,先下再上,处处连续可导。实际使用下来,switch效果不稳定,有些很好,有些没有relu好,不能保证效果,速度慢。
3. Mish:
-
f ( x ) = x ⋅ tanh ( ς ( x ) ) f(x)=x \cdot \tanh (\varsigma(x)) f(x)=x⋅tanh(ς(x))
ς ( x ) = ln ( 1 + e x ) − − \varsigma(x)=\ln \left(1+e^{x}\right)-- ς(x)=ln(1+ex)−− softplus 以上就是公式 -
f ′ ( x ) = e x ω δ 2 f^{\prime}(x)=\frac{e^{x} \omega}{\delta^{2}} f′(x)=δ2exω
ω = 4 ( x + 1 ) + 4 e 2 x + e 3 x + e x ( 4 x + 6 ) \omega=4(x+1)+4 e^{2 x}+e^{3 x}+e^{x}(4 x+6) ω=4(x+1)+4e2x+e3x+ex(4x+6)
δ = 2 e x + e 2 x + 2 \delta=2 e^{x}+e^{2 x}+2 δ=2ex+e2x+2 看到这个求导就知道它有多慢了
-
负半轴的时候,mish和swish基本是一样,正半轴的时候mish和swish会有一点不同,就是这不同让mish会稳定很多。不保证很管用,mish基本上是现在最好的能代替relu的激活函数了。
IOU Loss家族:
- 如果看过YoloV3的源代码,就知道Yolo的loss是由五部分组成的,x,y,w,h还有置信度相加而成。这些Loss是独立进行计算的。如果出现有两组不同的x,y,w,h还有置信度,但是我们的BBox却不一样这时候要怎么挑选呢?我们的统一标准是什么呢?这时候Iou Loss就产生了,它希望把x,y,w,h当成一个整体进行Loss的计算,而不是粗暴相加。
IOU Loss:
-
这是比较显而易见的尝试:如果IOU大说明结果好,IOU小就结果不太好了。但是这个技术已经不太新了,已经没有人用这个技术了,可以稍微了解一下。
-
伪代码如下:
- 其中
L
=
−
ln
(
I
o
U
)
\mathcal{L}=-\ln (I o U)
L=−ln(IoU) 的In其实是不需要的。我们可以看这个示意图:
- 其中
L
=
−
ln
(
I
o
U
)
\mathcal{L}=-\ln (I o U)
L=−ln(IoU) 的In其实是不需要的。我们可以看这个示意图:
GIOU Loss:
- Iou Loss有一个问题:如果没有iou的时候,不相交的时候,要怎么办呢?如何判断哪个效果好呢?如果用iou评判的话,只要不相交,就都是0,这好吗,这不好。当形状不一样的时候,iou一样,但是没办法判断哪个好。
- 所以出现了general Iou,说是普世的Iou。
- Ag表示groud truth Ap表示pred bbox,Ac指代粉色区域面积,就是包含两个bbox的最小的矩形面积,或者叫凸包整体面积。U表示两个bbox的面积和。GIou就是用IOU减去面积差除以粉色面积。
-
也就是说,我们把凸包给拿进来计算的。
-
看一下伪代码,大致的情况就会很清楚了。
-
当然,这种东西想要普世是不可能的,因为当BBox相互包含而且相对面积固定,但是位置不同的时候,GIou就一样了,比如说下面的图像:
DIOU Loss:
-
为了解决GIou的问题,有人提出了DIou Loss,通过两个框框的中心点的距离来辅助计算Iou。我们可以先看看效果,听说会好一丢丢:
-
具体计算公式如下:
-
R D I o U = ρ 2 ( b , b g t ) c 2 \mathcal{R}_{D I o U}=\frac{\rho^{2}\left(\mathbf{b}, \mathbf{b}^{g t}\right)}{c^{2}} \quad RDIoU=c2ρ2(b,bgt) (Penalty Term)
L D I o U = 1 − I o U + ρ 2 ( b , b g t ) c 2 \mathcal{L}_{D I o U}=1-I o U+\frac{\rho^{2}\left(\mathbf{b}, \mathbf{b}^{g t}\right)}{c^{2}} LDIoU=1−IoU+c2ρ2(b,bgt) -
在减去Iou的同时加上与中心点距离的惩罚项,这样位置问题就解决了。
-
问题还是层出不穷的。如果在同一个位置,Iou相同但是形状不同又要怎么办?
CIOU Loss:
-
其实IOU Loss要考虑三部分:形状,重叠面积,中心距离。现在出现了一个比较完备的Iou Loss,其实它和DIou 和CIou Loss都出自同一篇文章:
-
我们直接来看公式:
-
R C I o U = ρ 2 ( b , b g t ) c 2 + α v \mathcal{R}_{C I o U}=\frac{\rho^{2}\left(\mathbf{b}, \mathbf{b}^{g t}\right)}{c^{2}}+\alpha v RCIoU=c2ρ2(b,bgt)+αv
L C I o U = 1 − I o U + ρ 2 ( b , b g t ) c 2 + α v \mathcal{L}_{C I o U}=1-I o U+\frac{\rho^{2}\left(\mathbf{b}, \mathbf{b}^{g t}\right)}{c^{2}}+\alpha v LCIoU=1−IoU+c2ρ2(b,bgt)+αv -
v = 4 π 2 ( arctan w g t h g t − arctan w h ) 2 v=\frac{4}{\pi^{2}}\left(\arctan \frac{w^{g t}}{h^{g t}}-\arctan \frac{w}{h}\right)^{2} v=π24(arctanhgtwgt−arctanhw)2
α = v ( 1 − I o U ) + v \alpha=\frac{v}{(1-I o U)+v} α=(1−IoU)+vv
-
v是用来定义BBox的形状的,用了宽高比的角度做一个归一化。如果v越大,α就会越大,惩罚项 α v \alpha v αv就会越大。所以它对形状和距离都进行了惩罚,反应了Iou Loss需要考虑的各方面因素,只不过计算和求导会慢一些。
-
我们可以看看CIou的效果,都有一丢丢的提升:
网络结构改变:
-
YoloV4网络的工程性远远应该大于学术性。主要的创新点在这里重新概括一下,主要分成5个创新点:
-
- 数据増广方法:Mosaic,已经讲过这方面的方法了
- 生成自对抗训练,和原来的通过Loss进行反向传播不同,在这一部分,Loss被冻结了,不更新参数,传播回去的就是Loss,这个Loss和输入的input相加产生新的图像进行计算,这样就相当于对数据进行了扩增。
- CBN/CmBN,这个东西对结果的提高有限。就是把多个batch_size的数据一起进行BN
- modified SAM,就是对空间注意力机制进行一定的魔改,原来的SAM是进行了Max和Avg Pooling,作者觉得太多余,直接一个卷积干掉,然后再softmax就好了,多简单
- 改变了path aggregation network(PAN)。把从下到上直接相加变成了拼接。觉得这些东西可能快,是工程性的东西。没有什么逻辑性的问题。其实就是对FPN的微调。这些创新点在下面展示了,很快就能够看懂了
-
-
YoloV4提出了两个定义比较重要,一个是bag of specials(BOS),就是通过增加耗能让效果提升,另一个是bag of freelies(BOF),就是不耗费资源让效果提升。我们最好都是追求Bof这个比较好。