![feb8d72eaee5030840e784d0e1ed4a1f.png](https://i-blog.csdnimg.cn/blog_migrate/bfb304cba08d2bf236e08f35961c8db3.jpeg)
之前写了yolov1,yolov2我自己的理解。现在写了这篇yolov'3的,写得非常详细,看完这篇文章回头看以前的即使有不太清楚的地方也会有新的收获。
不谈创新点,我们先看yolov3的流程是什么样的,讲完流程会铺开讲细节,带着疑问慢慢往下看。
首先传入(batch_size, image_size, image_size, 3)的张量,其中imagesize为416.经过一个网络,darknet-53(当然做检测的话,要把最后的全连接层去掉)。我们能够得到三个输出(batch_size, 13,13, 255),(batch_size, 26,26, 255),(batch_size, 52,52, 255),对每个输出的每个方格会有三个先验框,对每个输出的框进行筛选,选出符合要求的作为检测的目标框,计算各部分loss。
ok,接下来依次讲述下列问题:1,darknet-53结构,为什么会有三个输出。2,输出的每个数字是什么意思,预测的是什么值。3,框的筛选。4,loss。
- darknet-53
首先我们看一下作者贴的网络性能图,可以说非常厉害了。
![4edd068661b0349903065f2633fa7abc.png](https://i-blog.csdnimg.cn/blog_migrate/18555bdf7ef9b65ae1045e11902ce4b5.png)
首先保持了非常高的精度,与resnet-152差不多,大家有兴趣可以看一下resnet-152的网络有多深。并且在速度上也非常快,自然而言计算次数也少,真的非常强。接着我们看一下网络结构
![02b79b6831c5b967acc8649f7d9b8463.png](https://i-blog.csdnimg.cn/blog_migrate/caf4bdca300e34b79fe1bb5d68079e9e.jpeg)
红线以上是yolov3的网络结构(下面全连接层是为了分类,并且加了全连接就限制了输入尺寸为固定256,引入大量参数,这也是作者为什么去掉全连接层的原因)。这个网络是32倍下采样(也就是将原始尺寸缩小32倍),实际输入为416*416,缩小32倍所以应该是13*13,而不是上面的8。对于这个网络,作者继续借鉴了残差网络的东西,大量运用了残差结构。
用蓝色画笔圈出来的是作者选择提取的不同层的特征图。实际输入416*416对应的三个篮圈部分分别为52*52,26*26,13*13。因为现在很多算法都注意到不同层特征图的表征能力不同,从浅层到高层捕捉细节的能力也越强。特征图尺寸越小,感受野越大。所以这些输入,分别用作检测小目标,中目标,大目标。接下来,把这三层分别进行1*1,3*3的卷积,改变通道数的同时,继续提高非线性程度,提高精度,最终将通道数变成我们想要的255。ok,第一部分结束。
2. 输出数字的含义
我们从上面得到三个(batch_size, 13,13, 255),(batch_size, 26,26, 255),(batch_size, 52,52, 255)张量,13,26,52三个数字上一部分已解释,下面解释一下255的由来。以13*13的特征图为例。将图片分成13*13个部分。如果一个物体的中心落在这个格子中,那么这个格子就要负责检测出这个物体。每一个格子会产生3个框对应的值,每个框有85个值,分别是4个坐标,一个得分score,,80个类别概率(因为作者用的coco数据集,总共80类,每个数对应这个类的概率)。坐标表示框的位置,得分是表示这个框是否含有物体。那么对于一个格子,总共需要预测出
对于预测的坐标,要详细说一下。首先为什么不能直接预测坐标实际值,而要做一个encode,化成一个0-1之间的数。预测的值越大,模型越不稳定,最后计算loss也会比较大,容易波动。作者的用法如图
![8602af1cdc86fd6a6a5bdb2172a0881f.png](https://i-blog.csdnimg.cn/blog_migrate/46cd42de036b82f0fe2cb35283754318.jpeg)
网络输出的是
3. 框的筛选
我们来计算一下总共得到了多少个框,分为三层,13那层对应
4. loss
首先,从上面我们知道,框分成两类,有目标和没有目标的。只有有目标的会计算三个损失,坐标损失,物体得分损失(存在物体,要让值为1),类别损失(属于这个类的值为1,其他要全为0)。没有目标的只会计算物体得分损失(不存在物体,要让值为0)。除了坐标损失用的均方误差外,得分loss和类别loss都用的交叉熵损失。别的较于yolov1中的损失函数就没什么改动了。
最后吐槽一句,这种大神写得文章,很多细节都默认你知道,真的要看看别人讲解,结合代码在理解理解,也算慢慢成长的过程。下面准备用这个算法,跑一跑自己的数据集(当然还要写一些文件处理的代码,太蛋疼了),等弄完,也会把自己的心得细节详细介绍给大家,奥利给。
补充
关于yolov2(yolov3同理)中作者提到的用聚类的方法,选择先验框的数量和尺寸,我们具体看一下做法。选择voc2012数据集,将所有的ground true的长宽都记录下来,考虑到图片尺寸可能不一样,所以有一个归一化的操作,即将长和宽分别除以原图片的尺寸,总共40138个框,所以我们有(40138, 2)的矩阵。在github上有长宽的分布图。
![7505a6ba0ebf26e8b9c96527053dcc7e.png](https://i-blog.csdnimg.cn/blog_migrate/fe389f6234d95d9d04b8a97e7b9a694e.jpeg)
接下来运用kmeans的算法,作者设置了k从2到10(不能再大因为框越多检测速度会越慢)。以k=2为例,我们有(40138, 2)的矩阵记录每个框的w和h,首先随机选择两个中心wh,接着计算其余每个wh与我们选好的中心wh的距离。距离计算公式为
![fa03d309f4980300ef89bb8fb61ccb7e.png](https://i-blog.csdnimg.cn/blog_migrate/90d548efb6f5803e8c529d47011cb5a6.png)
最后可以看出,其实k越大,效果越好,为了兼顾精度与速度,在yolov2中作者选择了5个先验框。这部分代码能够从github上找到,我也是借用别人的实验图,项目地址。