学习mxnet也有一段时间了,但依然感觉对mxnet没有入门,于是计划了一个yolo实验,
主要不是复现yolo,而是按照自己的喜好整理一下mxnet的各个接口,希望有助于加深对mxnet的理解.

抛开mxnet, 一个识别算法应该包括如下几个模块:
* 样本生成/加载
* 模型生成/加载
* 模型训练/预测

下面以gluon教程中yolo的例子,重新按上述模块划分代码,实现教程中的yolo

样本生成/加载

生成rec文件

参见mxnet源码中的im2rec.py脚本.
im2rec.py要求输入的图片按类分组,脚本自动给类分配ID

DataIter

mxnet中数据集都是用DataIter封装,一般会支持data augment. 对于目标检测算法, 推荐的是ImageDetIter()接口.

模型生成/加载

yolo和很多检测算法类似,需要一个预先训练好的网络提取特征,然后检测算法各显其能,基于特征完成检测.

本次实验中使用mxnet.gluon.model_zoo.vision中提供的resnet18提取特征,在其后追加一个卷积核为1x1的卷积层网络,构成yolo网络,
yolo算法的精髓就在这个卷积层.
* 卷积核是1x1的,即不会改变前一层的特征图尺寸
* 卷积通道数等于每个像素位置上期望预测的值的个数:
比如我们让每个像素位置上预测N个候选目标(类似SSD中的AnchorBox),每个候选目标包括C个类别置信度,一个objectness置信度以及4个坐标值.那么追加的这一层卷积层通道数就是
N(C+1+4)N(C+1+4), 每个通道表示个预测值.

模型训练/预测

mxnet的老接口里,直接一个fit()函数就启动了训练,
训练参数都通过fit()的参数传递,但gluon接口开放了训练代码,gluon只提供一些核心的函数,整个训练代码需要自己去写.基本套路如下:

定义损失函数

mxnet.gluon.loss下选择合适的接口,yolo因为同时预测类别和回归坐标,需要两类loss:
SoftmaxCrossEncropyLoss()和L1Loss().

定义trainer

gluon.Trainer()最主要的参数是”学习算法”的选择,一般是”sgd”,
至于学习速率的初值和修改机制,可以不设置,而是在后面自己定义函数修改,更加灵活.

训练循环

训练代码一般由两重循环组成,第一重是epoch-loop,第二重循环是batch-loop. epoch-loop中的一轮逻辑上是遍历了一次训练集,
batch-loop中的一轮是使用dataIter的一个batch训练网络.

所有需要反向传播的量的计算都要在autograd.record()域之内计算,可以用autograd.pause()生成要给域,处理不参与反向传播的量.一般autograd.record()域里就是计算loss.
反向传播通过两行代码就可以搞定: loss.backward()和trainer.step(batchSize).

Yolo中两个特殊模块

如前所述,yolo最后一层卷积层输出的是C×H×WC×H×W, 其中H×WH×W和最后特征图保持一致,可以认为是把输入图下采样到这个特殊尺度上.
但是训练集中,给出的label只是图中每个目标的位置和类别,输入和输出如何匹配?

format_net_output()

解析yolo输出结果,对C×H×WC×H×W中的CC中每个值做解释,给出每个像素位置上预测处的结果.
yolo论文中有一部分就是在讨论如何对这些预测结果做规范化,提高训练效率或预测精度.

format_groundtruth()

利用已知的目标位置和类别,对yolo每个预测结果给出目标值(目标类别或目标位置), 这个目标置将被用来计算loss.
yolo论文中有一部分讨论如何利用groundtruth信息选择anchor负责预测,并给出预测值. 这里是anchor box发挥作用的地方, anchor
box用来限定最后一个层,每个像素允许涉及的邻域范围.

实验代码

源码 <https://github.com/z01nl1o02/toy-yolo>

友情链接
ioDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信