YOLO v7在今年7月份推出,模型的性能和速度相比以往版本有了很大的提升。我也想好好研究一下YOLO v7模型,因此把官方的代码库下载下来进行研究,尝试更好的理解这个模型。
从文档中我们可以看到,如果要从头开始训练,可以输入以下命令,
python train.py --workers 8 --device 0 --batch-size 32 --data data/coco.yaml --img 640 640 --cfg cfg/training/yolov7.yaml --weights '' --name yolov7 --hyp data/hyp.scratch.p5.yaml
因此我们就以train.py为入口开始研究,这里面加载的模型配置文件是yolov7.yaml,但是只看这个配置不好直观的查看模型的结构,因此我先尝试用Netron这个神经网络的可视化工具来展示。
在根目录还有一个export.py文件,这个是可以把yolo的模型导出为其他的格式,例如导出为onnx格式的模型,Netron可以支持这种格式的展示。
在这个网址https://github.com/WongKinYiu/yolov7/releases/download/v0.1/yolov7.pt下载yolov7的已训练好的模型。之后运行命令
python export.py --weights ./yolov7.pt
在netron.app网站打开刚才导出的yolov7.onnx文件,可以展示整个模型的结构。
在以上的模型中,我把主要的结构用不同的颜色标注了,红色的是论文中提到的ELAN结构,紫色的是增强的ELAN结构。绿色框以上的是模型的Backbone,从绿色框开始属于模型的检测部分,绿色框对应的是SPPCSPC结构。浅蓝色和蓝色框组成了最后各个尺度下的检测结构。可以看到总共有三个输出,其维度分别为1*3*80*80*85, 1*3*40*40*85, 1*3*20*20*85,分别对应大中小这三个粒度的检测。例如1*3*80*80*85表示有3个Anchor,图像分为80*80个格子,85表示每个格子的每个Anchor输出的检测结果的维度,其中有4位表示图像中心点的x,y坐标,长,宽,有1位代表是否有检测到图像,剩下的80位对应80个图像类别。
以上的模型结构图虽然很细致,但是不容易从宏观上把握模型设计的思路。为此我把通用部分进行了整合,绘制了一个模型图,其中橙色部分的是Backbone,绿色的是Head,蓝色的是输出不同尺度的检测。
这个模型图能更好的帮我们理解作者设计模型的思路。
从以上的模型图,我们可以理解到在Backbone里面,除了最后一次ELAN模块,前面几个ELAN模块变换,分辨率不变,但是通道数增加一倍。每个ELAN模块后都会进行Maxpool和卷积变换,降低分辨率。所以我们可以看到经过Backbone的处理,输出了80*80, 40*40, 20*20三个尺度的特征表达,即在不同的尺度下提取图像的特征信息。
在Head里面,处理流程和Backbone是相反的。即从最粗的尺度20*20开始,经过SPPCSPC处理后,通过Upsample处理为40*40的尺度,然后和Backbone的40*40尺度的特征卷积后组合,再通过ELAN-A模块进行特征的变换,从512的输入特征维度降为256。这里面ELAN-A的作用和Backbone的是相反的,ELAN的是特征通道丰富一倍,但是ELAN-A是特征通道减少一倍。最后Head里面的三个ELAN-A模块也是输出了80*80, 40*40, 20*20三个尺度的特征表达,即在不同的尺度下提取图像的特征信息。最后每个尺度的特征表达经过两次卷积后,把特征维度转为255(即3*85,对应三个不同size的Anchor的输出)
经过以上的分析,现在我们对于Yolo v7的结构应该是比较清楚了,在下一篇文章中,我将继续研究模型训练设计到的一些技巧和细节。