Mxnet中的Gluoncv提供darknet53和mobilenetv1的Yolov3,由于model_zoo中有很多写好的分类模型,因此可以快速地为Yolov3更换基础网络。首先需要下载Gluoncv源码并将其修改,然后可以在本地训练中import更改的模型。我们以Gluoncv中提供的mobilenetv3_large为示例,增加一个基于mobilenetv3_large的Yolov3,并命名成‘yolo3_mobilenetv3_large_voc’,若想替换其它基础网络,方法类似。
Gluoncv代码链接:https://github.com/dmlc/gluon-cv
其中已经有的Yolov3模型:
'yolo3_darknet53_voc',
'yolo3_darknet53_coco',
'yolo3_darknet53_custom',
'yolo3_mobilenet1_0_coco',
'yolo3_mobilenet1_0_voc',
'yolo3_mobilenet1_0_custom',
'yolo3_mobilenet0_25_coco',
'yolo3_mobilenet0_25_voc',
'yolo3_mobilenet0_25_custom'
我们需要的mobilenetv3_large模型文件存放在gluoncv/model_zoo中,和mobilenetv1以及众多分类模型放在一起,因此我们只需要分析给出的基于mobilenetv1的Yolov3模型,便可以找到快速替换基础网络的方式。
根据gluoncv/model_zoo/yolo/yolo3.py中yolo3_mobilenet1_0_voc代码(如下所示)分析,我们只需要传入mobilenetv3_large的base_net,并找到strides=[8,16,32]对应的特征层,便可以使用封装好的get_yolov3函数得到基于mobilenetv3_large的Yolov3。
def yolo3_mobilenet1_0_voc(pretrained_base=True, pretrained=False,
norm_layer=BatchNorm, norm_kwargs=None, **kwargs):
from ...data import VOCDetection
pretrained_base = False if pretrained else pretrained_base
base_net = get_mobilenet(
multiplier=1,
pretrained=pretrained_base,
norm_layer=norm_layer, norm_kwargs=norm_kwargs,
**kwargs)
stages = [base_net.features[:33],
base_net.features[33:69],
base_net.features[69:-2]]
anchors = [[10, 13, 16, 30, 33, 23],
[30, 61, 62, 45, 59, 119],
[116, 90, 156, 198, 373, 326]]
strides = [8, 16, 32]
classes = VOCDetection.CLASSES
return get_yolov3(
'mobilenet1.0', stages, [512, 256, 128], anchors, strides, classes, 'voc',
pretrained=pretrained, norm_layer=norm_layer, norm_kwargs=norm_kwargs, **kwargs)
1. 首先在yolo3.py中根据相对路径import model_zoo中的mobilenetv3模型
from ..mobilenetv3 import get_mobilenet_v3
2. 在yolo3.py中__all__里面加入新增的模型名字
__all__ = ['YOLOV3',
'get_yolov3',
'yolo3_darknet53_voc',
'yolo3_darknet53_coco',
'yolo3_darknet53_custom',
'yolo3_mobilenet1_0_coco',
'yolo3_mobilenet1_0_voc',
'yolo3_mobilenet1_0_custom',
'yolo3_mobilenet0_25_coco',
'yolo3_mobilenet0_25_voc',
'yolo3_mobilenet0_25_custom',
'yolo3_mobilenet_v3_large_voc',
]
3. 在yolo3.py中增加yolo3_mobilenet_v3_large_voc函数
Gluoncv的网络模块化设计使得调用非常方便,mobilenetv3_large被封装为“features”和“output”两部分,通过get_mobilenet_v3得到分类网络,通过base_net.features获取基础特征网络,然后便可以通过索引得到不同层构成的网络块,需要注意的是要和strides=[8,16,32]对应。
def yolo3_mobilenet_v3_large_voc(pretrained_base=True, pretrained=False,
norm_layer=BatchNorm, norm_kwargs=None, **kwargs):
from ...data import VOCDetection
pretrained_base = False if pretrained else pretrained_base
base_net = get_mobilenet_v3(model_name="large", multiplier=1, pretrained=pretrained_base,
norm_layer=norm_layer, norm_kwargs=norm_kwargs,
**kwargs)
stages = [base_net.features[:9],
base_net.features[9:15],
base_net.features[15:18]]
anchors = [[10, 13, 16, 30, 33, 23],
[30, 61, 62, 45, 59, 119],
[116, 90, 156, 198, 373, 326]]
strides = [8, 16, 32]
classes = VOCDetection.CLASSES
return get_yolov3(
'mobilenet_v3_large', stages, [512, 256, 128], anchors, strides, classes, 'voc',
pretrained=pretrained, norm_layer=norm_layer, norm_kwargs=norm_kwargs, **kwargs)
4. 在gluoncv/model_zoo/model_zoo.py中增加yolo3_mobilenet_v3_large_voc
'yolo3_darknet53_coco': yolo3_darknet53_coco,
'yolo3_darknet53_voc': yolo3_darknet53_voc,
'yolo3_darknet53_custom': yolo3_darknet53_custom,
'yolo3_mobilenet1.0_coco': yolo3_mobilenet1_0_coco,
'yolo3_mobilenet1.0_voc': yolo3_mobilenet1_0_voc,
'yolo3_mobilenet1.0_custom': yolo3_mobilenet1_0_custom,
'yolo3_mobilenet0.25_coco': yolo3_mobilenet0_25_coco,
'yolo3_mobilenet0.25_voc': yolo3_mobilenet0_25_voc,
'yolo3_mobilenet0.25_custom': yolo3_mobilenet0_25_custom,
'yolo3_mobilenet_v3_large_voc': yolo3_mobilenet_v3_large_voc,
经过以上修改,我们便得到了yolo3_mobilenet_v3_large_voc模型,模型将基础网络替换为mobilenet_v3_large,将整个gluoncv文件夹重命名为gluoncv_new放到特定路径下,便可以通过如下方式import get_model,然后和平时的get_model使用方法一样得到yolo3_mobilenet_v3_large_voc网络。
from gluoncv_new.model_zoo import get_model