目标检测之YOLO V3
个人成果,禁止转载!
前言
《YOLOv3: An Incremental Improvement》
论文地址:https://arxiv.org/pdf/1804.02767.pdf.
这篇论文很短,而且作为一篇论文,其语言也是特别的special,摘出来一些给大伙儿感受一下:
1.Sometimes you just kinda phone it in for a year, you know? I didn’t do a whole lot of research this year. Spent a lot of time on Twitter. Played around with GANs a little.
2.It has 53 convolutional layers so we call it… wait for it… Darknet-53!
3.I guess at least we know the technology is in good hands and definitely won’t be used to harvest your personal information and sell it to… wait, you’re saying that’s exactly what it will be used for?? Oh.
言归正转,如果YOLO采用COCO average AP between 0.5 and 0.95
IOU metric做评估标准的话在精确率上的表现就弱:
但是采用0.5IoU,性能就很明显:
模型框架
Darknet53没有池化层,缩小尺寸是靠stride=2的卷积层实现的,这样的好处是防止低特征被直接扔掉,改善对小物体的检测能力。速度和精度都很好,可能是ResNet层数太多,效率不太高。
在YOLO3更进一步采用了3个不同尺度的特征图来进行对象检测,下面是FPN的四种形式,V3采用的就是最后一种:
V2和V3的比较(上面是V2的形式,只不过是下采样,右边的箭头反过来画;下面是V3):
Darknet53特征图的具体抽取方式见下图:
图源:https://blog.csdn.net/qq_37541097/article/details/81214953
上采样的方式:即尺寸增加四倍,通道维度减少四倍。还是看源码比较快
void upsample_cpu(float *in, int w, int h, int c, int batch, int stride, int forward, float scale, float *out)
{
int i, j, k, b;
for(b = 0; b < batch; ++b){
for(k = 0; k < c; ++k){
for(j = 0; j < h*stride; ++j){
for(i = 0; i < w*stride; ++i){
int in_index = b*w*h*c + k*w*h + (j/stride)*w + i/stride;
int out_index = b*w*h*c*stride*stride + k*w*h*stride*stride + j*w*stride + i;
if(forward) out[out_index] = scale*in[in_index];
else in[in_index] += scale*out[out_index];
}
}
}
}
}
//float*in out是输入和输出图像。
//stride控制要上采样的步长,stride = 2,它将宽度和高度加倍。scale是将图像数值缩放系数。
// w h宽高 c通道数 batch是batchsize
从代码可知,实现的功能就是如此:(13x13x256–>26x26x256)
pytorch的实现方法,更清晰易懂,哈哈哈。
class MyUpsample2(nn.Module):
def forward(self, x):
return x[:, :, :, None, :, None].expand(-1, -1, -1, 2, -1, 2).reshape(x.size(0), x.size(1), x.size(2)*2, x.size(3)*2)
激活函数使用的是LeakyRelu,9个先验框是通过k-means聚类得到的,分别分配给三个尺度:
13x13:(116 × 90),(156 × 198),(373 × 326)
26x26:(30×61),(62×45),(59×119)
52x52:(10×13),(16×30),(33×23)
这里对模型输出特征进一步的说明:
如何确定使用哪个预测框呢?将会考虑每个bbox的置信度与各个物体的概率的乘积。
用Sigmoid代替Softmax,这个改进主要是用于多标签分类。Softmax输出的结果有互斥性,只能预测一类,而如果一个物体有多个标签(如:人和女人),那么Softmax是做不到的。但是在真实的检测场景中存在这样的情况,所以作者使用了Sigmoid函数替代。
损失函数
目标置信度损失binary cross-entropy loss:
目标类别损失 binary cross-entropy loss:
目标定位损失sum of squared error loss:计算的是真实偏差值与预测偏差值差的平方和,与yolo v1的边界框坐标损失类似,v3中使用误差平方损失函数分别计算(x, y, w, h)的Loss,然后加在一起。v1中作者对宽高(w, h)做了开根号处理,为了弱化边界框尺寸对损失值的影响。在v3中作者没有采取开根号的处理方式,而是增加1个与物体框大小有关的权重,权重=2 - 相对面积,取值范围(1~2)。
还要注意的一点:如果先验框没有框住真实物体(IoU),那么是不会计算其定位和分类损失的,这里和V2 V1相一致。
这也是保证了样本不平衡所带来的问题,因为对于单阶段的目标检测算法来说,一张图片中能够匹配到目标的候选框(正样本)个数比较少,而负样本却约能有104 个。
此外,作者在训练的时候还使用了多尺度训练。
边框选择
先将置信度低于阈值的边框过滤掉,然后按置信度从大到小排序,最后采用非极大值抑制算法NMS。
举例:
假设过滤并排序后的边框集A里有[a,b,c,d],现有空集B。
step1:抽出a加入B,然后将a与b,c,d进行对比。
step2:首先对比两框是否同类(假设a,b,c同类)。
step3:若同类,再进行计算IOU,若IOU大于阈值则为同一物体,则将其扔掉。(假设a与b的IOU大于阈值,a与c的IOU小于阈值,则将A里面的b扔掉,c保留。)
step4:此时A里面还剩c,d,B里有a,重复step1-3,直到A为空为止。
由上述的假设可得B为[a,c,d],即最终得到的边框为a,c,d。
此处参考:https://blog.csdn.net/weixin_39994739/article/details/106936139
Things We Tried That Didn’t Work
1.Anchor box x, y offset predictions.
2.Linear x, y predictions instead of logistic.
3.Focal loss.
作者说了,也不一定是完全没有用,可能还是需要仔细去调节参数才会起作用。
“It is possible that some of these techniques could eventually produce good results,perhaps they just need some tuning to stabilize the training.”
上一篇:目标检测之YOLO V2