前言:
在上文主要讲到了跑深度学习算法网络的一些基础环境和数据,所以这篇主要是叙述网络的运行以及了解算法中的一些小奥秘。本文主要讲述yolov3算法keras代码实现的目标检测与训练过程。
yolo简单介绍
- 深度学习中的目标检测算法如果要分类,那么一类可以是one-stage,一类是two-stage,还有一类是multi-stage。multi-stage是将Selective Serach、Feature extraction、location regressor、cls SVM这些步骤分开各自独立训练,相关算法有R-CNN,SPPNet,这里的two-stage指的是区域提取(包含了Selective Serach、Feature extraction、location regressor的功效)【Regional extract】和目标分类【target classification】,相关算法有fast-rcnn、faster-rcnn等等,而one-stage是将这两步做为一步统一处理,相关算法有RetinaNet、SSD、yolo(v1、v2、v3)等等。下面是yolo与其他目标检测算法在mAP【各类别的平均PR曲线的定积分(面积)】和时间这两个性能上的可视化,可看出yolo在时间和mAP上更胜一筹。
- YOLO-v1
实现流程:
yolo是将一幅图首先划分为SS个网格【图中黑色细框】,训练时某个目标框的中心点【图中红色点】落在一个网格中【图中绿色框】时,那么这个网格就预测该目标,每个网格要预测指定B个bounding box【图中黑色粗框】,每个bounding box要回归位置和预测一个confidence 值,该confidence值是真实框【图中红色框】与预测框【图中黑色粗框】的交并比(IOU)。若一个网格中有两个或多个目标框的中心时,则取confidence最高的哪个目标进行预测。这一步划分网格可以为模型节省大量计算时间;
在计算损失函数时,是位置误差+iou误差+分类误差,这也是为什么yolo将区域提取和目标分类做为一步处理的原因;
输出时,每个格子会输出所预测到的B个bounding box信息,每个bounding box包括width、heigh、x、y、confident,和C个物体属于某种类别的概率信息。输出维度即是SS(B*5 + C);
在box的求损失时,小box的边框偏移和大box边框偏移的值所产生的效果是不同的。当偏移量相同时,对小box精准度的影响要比大box要大得多。所以yolo为了缩小小box和大box之间偏移量所产生影响的差距,将标签box和预测box的width和height取平方根再算偏移loss;
缺点:
1、后面的输出层是全连接层,训练集和测试集的图片大小要相同,所以在计算时时间将增长,在便捷性上将下降;
2、虽说box框取平方根求loss,但这还是治标不治本,对小box任有比较大影响;
3、每个格子虽检测到了B个bounding box但输出的检测物体只是IOU最高的那个。这个导致有些物体检测不出,比如一个格子有两个目标,这对小目标物检测精准度影响很大; - YOLO-v2
在YOLO-v1上的改进:
此次主要改进的方向是改善 recall【召回率】,在提升定位的准确度的同时保持分类的准确度。
1、受FCN启发引入了anchor,并且使用K-Means方法对anchor数量进行了讨论。下图分析了模型在COCO数据集和VOC2007数据集上不同anchor数量对应的平均IOU情况,可看出在anchor=5时达到了一个折中点。大家需要知道的是anchor数量越大模型训练时间就会增长,所以这里是模型的速度和性能的一个折中;
2、将v1中的全连接层改为卷积层,这使得训练和测试模型接受任意大小的输入图像,同时也避免了重复存储和计算卷积;
3、训练时引入了树结构,主要用意是进一步将检测和分类问题做成了一个统一的框架,并提出了层次性联合训练方法,这可以将分类数据集和检测数据集同时对模型进行训练,大大提高了模型训练的灵活性能。
4、使用 Batch Normalization 对网络进行优化,即对卷积层后面加上Batch Normalization。这不仅仅加快了收敛过程,极大提升了训练速度,而且替换掉了网络中 Dropout而不会产生过拟合。最终使得模型的mAP提升了2%。
缺点:
1、在社会生活中,小物体检测要比大物体检测更加重要,尤其是在军事领域。然而这里对小物体的检测效果还是得不到较大改善。 - YOLO-v3
在YOLO-v2上的改进:
1、yolo-v2网络中有层叫 passthrough layer,该层作用是将卷积层提取出的feature map与前面一层卷积层提取的连接起来,主要是为了加强算法对小目标检测的精确度,在yolo-v3这里是对该思想进行了强化,采用了类似FPN网络的上采样(upsample)和融合做法(最终融合了3个scale),并且在多个scale的feature map上做检测,因此每个网格需要预测3*N个边界框,这步明显提升了小目标检测效果。
2、由于当时算法发展非常快,涌现出大量优秀的算法网络,所以yolo-v3在基础分类算法上选择了Resnet和darknet-53
算法准备
本文主要讲解的是Keras实现Yolov3
- GitHub源码: https://github.com/qqwweee/keras-yolo3
- 我实现时的环境和包是:
anaconda3-4.6.14、python3.6.7、tensorflow-gpu1.8.0、keras2.1.6、setuptools41.2.0、pillow【PIL】、matplotlib、h5py、opencv。当然github上的环境和我的不一样,所以一个原则就是环境只要兼容而且比github上的那版本高上一点就行,环境兼容问题可以参考我的上一篇博客。 - 下面是用cmd中的tree命令展示了对所下载的包进行展开,以及描述了每个模块文件的作用:
- 这里说下常见的一些深度学习模型和数据保存的文件格式,主要讲下.ckpt、.cfg、.h5、.json、.pkl、.pth这6种格式;
cpkt格式文件是由 tf.train.Saver() 对象调用 saver.save() 生成的,用于TensorFlow保存模型数据的一个文件,计算图的结构和图上参数取值分开保存,保存后在save这个文件夹下会有3个文件;
cfg中文意思叫做控制流图,它是一种用在编译器中的抽象数据结构,是一种程序或者过程的抽象表现,这种格式文件一般用作保存模型的结构;
h5该文件全名是HDF5,一般都用于keras保存整个模型权值的格式;
json该文件用的地方很多,keras一般序列化保存模型结构会用到json格式文件;
pkl是python里面保存文件的一种格式,在pytorch保存模型时会用到该文件;
pth一般会用于pytorch保存模型数据。
检测目标
- 检测目标需要模型的权值,这个权值可以通过自己训练据所得,也可以点击这里进行相应的下载。来到下图这里,可以看到右边黄色字体,cfg代表的是你的模型配置,weights就是你的权值了,左边的320,416说的是检测图大小,50-500、101-800说的是网络层数和检测图大小,所以根据自己需要选择模型下载权值weight以及对应的网络配置cfg。
- 检测图片、视频
1、 keras一般所需的权值格式是.h5文件,如果得到的数据是.weight,则需要对文件格式进行转换。可通过convert.py文件进行转换,用命令行传参时主要修改一下几个参数【模型结构配置路径、权值路径名、数据权值路径名:
命令行如下,分别对应上图的三个参数
注意:一般yolov3》配置文件yolov3.cfg修改主要修改一下几个:
该文件中有三个[yolo],每个[yolo]下的anchors改为自己kmeans聚类出来的结果,classes改为自己的类别数。自己的训练数据最好在kmeans.py文件中聚类生成anchors。
2、检测图片或视频时主要在yolo_video.py这个文件里面,主要修改的参数如下图:
注意检测视频的时候不需要传–image参数,只需传–input参数就行,在命令行输入传带‘–’参数时这必须要把参数名写上,如下是我要检测图片的命令
这里我之所以只传两个参数是因为我在yolo.py这个文件下设置了默认参数,所以红色框里的三个参数要么在这里或yolo_video.py文件下默认参数,要么从命令行里传。
3、欧克,下面是检测出来图片和视频的结果
训练模型
- 准备数据
首先这里我用到的是VOC2012数据集,下载下来会有如下五个文件,红框里的是有关于目标检测的文件
对目标检测分训练集、验证集和测试集是在ImageSets/Main/文件下,如图
在voc_annotation.py这个文件中可以吧训练集、验证集和测试集转为如下格式:
图片路径、图片位置框和1个类别id(path,xmin,ymin,xmax,ymax,id)
注意:如图红色标记处,一张图片有两个或多个目标时,中间用空格隔开
- 修改文件
1、如果你只想训练voc数据集里某一部分类或者想训练自己标注的类别,那么你的数据类必须存在在voc_annotation.py文件中的classes列表中,并且要与类txt文本中的类位置对应好如下:
2、解释预测特征图的anchor框集合;
(1)、3个尺度的特征图,每个特征图3个anchor框,共9个框,从小到大排列
(2)、框1-3在大尺度5252特征图中使用,框4-6是中尺度2626,框7-9是小尺度13*13;
(3)、大尺度特征图检测小物体,小尺度特征图检测大物体;
(4)、9个anchor框来源于K-Means聚类得来通过修改kmeans.py里输入.txt文件路径写入.txt文件路径,放入已标注边界框的图片数据集和想写入的文件路径,在运行就可把anchor框集合写入。
3、预训练模型,用于迁移学习中的微调,在train.py文件中将所下载的权值文件放到weight_path中,并且load_pretrained=True如图:
4、在train.py文件中修改以下路径即可开始训练:
- 训练模型
上面工作的做完了就可以运行train.py文件进行训练了。下面是我用voc数据里的508张船的图片作数据,其中百分之90做训练,百分之10做验证,所有图片分为10批,每批次10张图,训练1000个周期的过程【这里我只训练了船这一类数据】。
如图就是训练后【没有用模型所给的与训练权值】所得到的权值做检测的效果。可以看出这里的分类准确率和框的置信度没有上面模型所给到的训练权值检测得好。