文章首发于微信公众号《与有三学AI》

【mxnet速成】mxnet图像分类从模型自定义到测试

这是给大家准备的mxnet速成例子

这一次我们讲讲mxnet,相关的代码、数据都在我们 Git 上,希望大家 Follow 一下这个 Git 项目,后面会持续更新不同框架下的任务。

https://github.com/longpeng2008/LongPeng_ML_Course

作者&编辑 | 言有三

01 mxnet是什么

mxnet是amazon的官方框架,下面参考mxnet的官方简介

https://mxnet-bing.readthedocs.io/en/latest/zh/overview.html

深度学习系统通常有两种编程方式,一种是声明式编程(declarative programming),用户只需要声明要做什么,而具体执行则由系统完成。以Caffe,TensorFlow的计算图为代表。优点是由于在真正开始计算的时候已经拿到了整个计算图,所以可以做一系列优化来提升性能。实现辅助函数也容易,例如对任何计算图都提供forward和backward函数,另外也方便对计算图进行可视化,将图保存到硬盘和从硬盘读取。缺点是debug很麻烦,监视一个复杂的计算图中的某个节点的中间结果并不简单,逻辑控制也不方便。

一种是命令式编程(imperative programming),以numpy,torch/pytorch为代表,每个语句按照原来的意思顺序执行。它 的特点是语义上容易理解,灵活,可以精确控制行为。通常可以无缝地和主语言交互,方便地利用主语言的各类算法,工具包,debug和性能调试器,但是实现统一的辅助函数和提供整体优化都很困难。

MXNet尝试将两种模式无缝的结合起来。在命令式编程上MXNet提供张量运算,进行模型的迭代训练和更新中的控制逻辑;在声明式编程中MXNet支持符号表达式,用来描述神经网络,并利用系统提供的自动求导来训练模型。

随着pytorch的崛起,mxnet已经掉出前三梯队,但不影响喜欢它的人使用。相比于重量级的tensorflow,mxnet非常轻量,占用内存少,分布式训练方便,常被用于比赛刷榜(见笔者以前用来刷榜的文)。

如何步入深度学习刷榜第一重境界

02 mxnet安装配置

喜欢自定义安装和精确控制版本的朋友,可以自行编译,喜欢偷懒的pip安装即可,方便快捷。

sudo pip install mxnet

不过如果你要多机多卡使用,还是源码编译安装吧。

https://github.com/apache/incubator-mxnet

03 mxnet自定义数据

下面就开始我们的任务,跟以往项目一样,从自定义数据和自定义网络开始。

mxnet分类任务要求的输入分类文件的格式与caffe不一样,为下面的格式,其中分别是序号,标签,路径

01../../../../../datas/mouth/1/182smile.jpg

11../../../../../datas/mouth/1/435smile.jpg

数据的载入需要用到接口DataBatch和DataIter

https://mxnet.incubator.apache.org/api/python/io/io.html

首先我们定义一下相关的参数配置,主要用于载入训练/测试数据集路径data-train,data-val,rgb均值rgb-mean,类别数目num-classes与训练样本集大小num-examples

def add_data_args(parser):

data = parser.add_argument_group('Data', 'the input images')

data.add_argument('--data-train', type=str, help='the training data')

data.add_argument('--data-val', type=str, help='the validation data')

data.add_argument('--rgb-mean', type=str, default='123.68,116.779,103.939',help='a tuple of size 3 for the mean rgb')

data.add_argument('--pad-size', type=int, default=0,

help='padding the input image')

data.add_argument('--image-shape', type=str,

help='the image shape feed into the network, e.g. (3,224,224)')

data.add_argument('--num-classes', type=int,help='the number of classes')

data.add_argument('--num-examples', type=int, help='the number of training examples')

data.add_argument('--data-nthreads', type=int, default=4,help='number of threads for data decoding')

data.add_argument('--benchmark', type=int, default=0,

help='if 1, then feed the network with synthetic data')

data.add_argument('--dtype', type=str, default='float32',help='data type: float32 or float16')

return data

然后,使用mx.img.ImageIter来载入图像数据

train = mx.img.ImageIter(

label_width         = 1,

path_root    = 'data/',

path_imglist         = args.data_train,

data_shape          = (3, N_pix, N_pix),

batch_size          = args.batch_size,

rand_crop           = True,

rand_resize         = True,

rand_mirror         = True,

shuffle             = True,

brightness          = 0.4,

contrast            = 0.4,

saturation          = 0.4,

pca_noise           = 0.1,

num_parts           = nworker,

part_index          = rank)

注意到上面配置了rand_crop,rand_resize,rand_mirror,shuffle,brightness,contrast,saturation,pca_noise等选项,这些就是常见的数据增强操作了,如果不懂,可以去看看我们以前的文章

[综述类] 一文道尽深度学习中的数据增强方法(上)

【技术综述】深度学习中的数据增强(下)

【开源框架】一文道尽主流开源框架中的数据增强

mxnet的数据增强接口使用非常的方便,定义如下

def add_data_aug_args(parser):

aug = parser.add_argument_group(

'Image augmentations', 'implemented in src/io/image_aug_default.cc')

aug.add_argument('--random-crop', type=int, default=1,help='if or not randomly crop the image')

aug.add_argument('--random-mirror', type=int, default=1,help='if or not randomly flip horizontally')

aug.add_argument('--max-random-h', type=int, default=0,help='max change of hue, whose range is [0, 180]')

aug.add_argument('--max-random-s', type=int, default=0,help='max change of saturation, whose range is [0, 255]')

aug.add_argument('--max-random-l', type=int, default=0,help='max change of intensity, whose range is [0, 255]')

aug.add_argument('--max-random-aspect-ratio', type=float, default=0,help='max change of aspect ratio, whose range is [0, 1]')

aug.add_argument('--max-random-rotate-angle', type=int, default=0,help='max angle to rotate, whose range is [0, 360]')

aug.add_argument('--max-random-shear-ratio', type=float, default=0,help='max ratio to shear, whose range is [0, 1]')

aug.add_argument('--max-random-scale', type=float, default=1,help='max ratio to scale')

aug.add_argument('--min-random-scale', type=float, default=1,help='min ratio to scale, should >= img_size/input_shape. otherwise use --pad-size')

return aug

可以看到level >= 1,就可以使用随机裁剪,镜像操作,level >= 2,就可以使用对比度变换操作,level >= 3,就可以使用旋转,缩放等操作。

def set_data_aug_level(aug, level):

if level >= 1:

aug.set_defaults(random_crop=1, random_mirror=1)

if level >= 2:

aug.set_defaults(max_random_h=36, max_random_s=50, max_random_l=50)

if level >= 3:

aug.set_defaults(max_random_rotate_angle=10, max_random_shear_ratio=0.1, max_random_aspect_ratio=0.25)

04 mxnet网络搭建

同样是三层卷积,两层全连接的网络,话不多说,直接上代码,使用到的api是mxnet.symbol

import mxnet as mx

def get_symbol(num_classes, **kwargs):
   if 'use_global_stats' not in kwargs:
       use_global_stats = False
   else:
       use_global_stats = kwargs['use_global_stats']

data = mx.symbol.Variable(name='data')
   conv1 = mx.symbol.Convolution(name='conv1', data=data , num_filter=12, kernel=(3,3), stride=(2,2), no_bias=True)
   conv1_bn = mx.symbol.BatchNorm(name='conv1_bn', data=conv1 , use_global_stats=use_global_stats, fix_gamma=False, eps=0.000100)
   conv1_scale = conv1_bn
   relu1 = mx.symbol.Activation(name='relu1', data=conv1_scale , act_type='relu')
   conv2 = mx.symbol.Convolution(name='conv2', data=relu1 , num_filter=24, kernel=(3,3), stride=(2,2), no_bias=True)
   conv2_bn = mx.symbol.BatchNorm(name='conv2_bn', data=conv2 , use_global_stats=use_global_stats, fix_gamma=False, eps=0.000100)
   conv2_scale = conv2_bn
   relu2 = mx.symbol.Activation(name='relu2', data=conv2_scale , act_type='relu')
   conv3 = mx.symbol.Convolution(name='conv3', data=relu2 , num_filter=48, kernel=(3,3), stride=(2,2), no_bias=True)
   conv3_bn = mx.symbol.BatchNorm(name='conv3_bn', data=conv3 , use_global_stats=use_global_stats, fix_gamma=False, eps=0.000100)
   conv3_scale = conv3_bn
   relu3 = mx.symbol.Activation(name='relu3', data=conv3_scale , act_type='relu')
   pool = mx.symbol.Pooling(name='pool', data=relu3 , pooling_convention='full', global_pool=True, kernel=(1,1), pool_type='avg')
   fc = mx.symbol.Convolution(name='fc', data=pool , num_filter=num_classes, pad=(0, 0), kernel=(1,1), stride=(1,1), no_bias=False)
   flatten = mx.symbol.Flatten(data=fc, name='flatten')
   softmax = mx.symbol.SoftmaxOutput(data=flatten, name='softmax')
   return softmax

if __name__ == "__main__":
   net = get_symbol(2)  ##二分类任务
   net.save('simpleconv3-symbol.json')

最后我们可以将其存到json文件里,net.save('simpleconv3-symbol.json'),下面是conv1的部分,详细大家可以至git查看

{

"op": "Convolution",

"name": "conv1",

"attr": {

"kernel": "(3, 3)",

"no_bias": "True",

"num_filter": "12",

"stride": "(2, 2)"

},

"inputs": [[0, 0, 0], [1, 0, 0]]

},

05 模型训练、测试

5.1 模型训练

准备工作都做好了,训练代码非常简洁,下面就是全部的代码

import os
import argparse
import logging
logging.basicConfig(level=logging.DEBUG)
from common import find_mxnet
from common import data, fit
import mxnet as mx

import os, urllib

if __name__ == "__main__":
   parser = argparse.ArgumentParser(description="simple conv3 net",
                                    formatter_class=argparse.ArgumentDefaultsHelpFormatter)
   train = fit.add_fit_args(parser)
   data.add_data_args(parser)
   aug = data.add_data_aug_args(parser)
   data.set_data_aug_level(parser, 1)
   parser.set_defaults(image_shape='3,48,48', num_epochs=200,
                       lr=.001, wd=0)
   args = parser.parse_args()

# define simpleconv3
   net = mx.sym.load('models/simple-conv3-symbol.json')
   print "net",net

# train
   fit.fit(args        = args,
           network     = net,
           data_loader = data.get_rec_iter)

其中调用了fit接口定义优化目标和策略,我们只分析其中的核心代码,首先是模型创建

model = mx.mod.Module(
       context       = devs,
       symbol        = network
   )

然后是optimizer配置,默认使用adam

optimizer_params = {
           'learning_rate': lr,
           'wd' : args.wd

}

初始化

initializer = mx.init.Xavier(rnd_type='gaussian', factor_type="in", magnitude=2.34)

最后是完整的接口

model.fit(train,
       begin_epoch        = args.load_epoch if args.load_epoch else 0,
       num_epoch          = args.num_epochs,
       eval_data          = val,
       eval_metric        = eval_metrics,
       kvstore            = kv,
       optimizer          = args.optimizer,
       optimizer_params   = optimizer_params,
       initializer        = initializer,
       arg_params         = arg_params,
       aux_params         = aux_params,
       batch_end_callback = batch_end_callbacks,
       epoch_end_callback = checkpoint,
       allow_missing      = True,
       monitor            = monitor)

然后开始愉快的训练吧

python train.py --gpus 0 \
   --data-train data/train.txt \
   --model-prefix 'models/simple-conv3' \
   --batch-size 80 --num-classes 2 --num-examples 900 2>&1 | tee log.txt

训练模型会存为simple-conv3-epoch.params的格式。

5.2 训练过程可视化

由于前面我们的tensorflow,pytorch,keras都使用了tensorborad进行可视化,mxnet也可以借助tensorboard进行可视化,只需要再设计一些mxnet接口即可。具体方法不再赘述,参考https://github.com/awslabs/mxboard

网络结构的可视化则可用mx.viz.plot_network(sym).view()。

5.3 模型测试

使用mx.model.load_checkpoint载入预训练的模型,如下

epoch = int(sys.argv[1]) #check point step
gpu_id = int(sys.argv[2]) #GPU ID for infer
prefix = sys.argv[3]
ctx = mx.gpu(gpu_id)
sym, arg_params, aux_params = mx.model.load_checkpoint(prefix, epoch)
arg_params, aux_params = ch_dev(arg_params, aux_params, ctx)

然后使用bind接口进行forward,具体操作如下

sym  = mx.symbol.SoftmaxOutput(data = sym, name = 'softmax')

img_full_name = os.path.join(imgdir,imgname)
img = cv2.cvtColor(cv2.imread(img_full_name), cv2.COLOR_BGR2RGB)
img = np.float32(img)
rows, cols = img.shape[:2]
resize_width = 48
resize_height = 48
img = cv2.resize(img, (resize_width, resize_height), interpolation=cv2.INTER_CUBIC)
h, w, _ = img.shape

img_crop = img[0:h,0:w] ##此处使用整图
img_crop = np.swapaxes(img_crop, 0, 2)
img_crop = np.swapaxes(img_crop, 1, 2)  # mxnet的训练是rgb的顺序输入,所以需要调整为r,g,b训练
img_crop = img_crop[np.newaxis, :]

arg_params["data"] = mx.nd.array(img_crop, ctx)
arg_params["softmax_label"] = mx.nd.empty((1,), ctx)
exe = sym.bind(ctx, arg_params ,args_grad=None, grad_req="null", aux_states=aux_params)
exe.forward(is_train=False)
probs = exe.outputs[0].asnumpy()

06 总结

好了,就这么多。到今天为止,主流的机器学习框架caffe,tensorflow,pytorch,paddlepaddle,keras,mxnet我们已经全部给大家提供了快速入门【文末提供了全部链接】。从自定义数据集,自定义网络,到模型的训练,可视化,测试,全套脚本都提供到了github上,欢迎star和fork。

同时,在我的知乎专栏也会开始同步更新这个模块,欢迎来交流

https://zhuanlan.zhihu.com/c_151876233

注:部分图片来自网络

本系列完整文章:

第一篇:【caffe速成】caffe图像分类从模型自定义到测试

第二篇:【tensorflow速成】Tensorflow图像分类从模型自定义到测试

第三篇:【pytorch速成】Pytorch图像分类从模型自定义到测试

第四篇:【paddlepaddle速成】paddlepaddle图像分类从模型自定义到测试

第五篇:【Keras速成】Keras图像分类从模型自定义到测试

第六篇:【mxnet速成】mxnet图像分类从模型自定义到测试

第七篇:【cntk速成】cntk图像分类从模型自定义到测试

第八篇:【chainer速成】chainer图像分类从模型自定义到测试

第九篇:【DL4J速成】Deeplearning4j图像分类从模型自定义到测试

第十篇:【MatConvnet速成】MatConvnet图像分类从模型自定义到测试

第十一篇:【Lasagne速成】Lasagne/Theano图像分类从模型自定义到测试

第十二篇:【darknet速成】Darknet图像分类从模型自定义到测试

感谢各位看官的耐心阅读,不足之处希望多多指教。后续内容将会不定期奉上,欢迎大家关注有三公众号 有三AI

【mxnet速成】mxnet图像分类从模型自定义到测试相关推荐

  1. 【MatConvnet速成】MatConvnet图像分类从模型自定义到测试

    欢迎来到专栏<2小时玩转开源框架系列>,这是我们第10篇,前面已经说过了caffe,tensorflow,pytorch,mxnet,keras,paddlepaddle,cntk,cha ...

  2. 【darknet速成】Darknet图像分类从模型自定义到测试

    欢迎来到专栏<2小时玩转开源框架系列>,这是我们第12篇文章,前面已经说过了caffe,tensorflow,pytorch,mxnet,keras,paddlepaddle,cntk,c ...

  3. 【DL4J速成】Deeplearning4j图像分类从模型自定义到测试

    文章首发于微信公众号<有三AI> [DL4J速成]Deeplearning4j图像分类从模型自定义到测试 欢迎来到专栏<2小时玩转开源框架系列>,这是我们第九篇,前面已经说过了 ...

  4. 【chainer速成】chainer图像分类从模型自定义到测试

    文章首发于微信公众号<有三AI> [chainer速成]chainer图像分类从模型自定义到测试 欢迎来到专栏<2小时玩转开源框架系列>,这是我们第八篇,前面已经说过了caff ...

  5. 【cntk速成】cntk图像分类从模型自定义到测试

    文章首发于微信公众号<有三AI> [cntk速成]cntk图像分类从模型自定义到测试 欢迎来到专栏<2小时玩转开源框架系列>,这是我们第七篇,前面已经说过了caffe,tens ...

  6. 【paddlepaddle速成】paddlepaddle图像分类从模型自定义到测试

    文章首发于微信公众号<与有三学AI> [paddlepaddle速成]paddlepaddle图像分类从模型自定义到测试 这是给大家准备的paddlepaddle与visualdl速成例子 ...

  7. 【pytorch速成】Pytorch图像分类从模型自定义到测试

    文章首发于微信公众号<与有三学AI> [pytorch速成]Pytorch图像分类从模型自定义到测试 前面已跟大家介绍了Caffe和TensorFlow,链接如下. [caffe速成]ca ...

  8. 【Keras速成】Keras图像分类从模型自定义到测试

    文章首发于微信公众号<与有三学AI> [Keras速成]Keras图像分类从模型自定义到测试 这是给大家准备的Keras速成例子 这一次我们讲讲keras这个简单.流行的深度学习框架,一个 ...

  9. 【tensorflow速成】Tensorflow图像分类从模型自定义到测试

    文章首发于微信公众号<与有三学AI> [tensorflow速成]Tensorflow图像分类从模型自定义到测试 这是给大家准备的tensorflow速成例子 上一篇介绍了 Caffe , ...

最新文章

  1. Udacity机器人软件工程师课程笔记(七)-ROS介绍和Turtlesim包的使用
  2. js中表单验证常用到的正则表达式
  3. 【Qt】2D绘图之窗口-视口转换
  4. 取模除法(逆元)(费马小定理)(线性求逆元)
  5. 克罗内克内积 Kronecker product
  6. DWR第五篇之文件上传
  7. vscode配置c++11
  8. 23.3.3 Web存储机制【JavaScript高级程序设计第三版】
  9. 基于WebRTC开源框架的实时视频聊天项目,搭建私人实时通信服务
  10. 金仓数据库KingbaseES的连接方法
  11. 【SSM框架项目 客户关系管理系统CRM 学习开发 Day3】市场活动模块的数据导入与导出
  12. 滴滴拉屎v1.20 一款非常好用的找厕所工具
  13. 质数的判断(Python)找到100(1000)以内的所有质数
  14. 手动型三轴五档手动变速器设计(设计说明书+CAD图纸+外文翻译)
  15. 清华大学计算机崔勇,崔勇 简历 - 名人简历
  16. 在小故事中懂得10之内加法减法
  17. 正则表达式贪婪模式、懒惰模式与独占模式浅析
  18. 小满 | 清和暑夏,小得盈满
  19. Python-自动化测试之接口基础
  20. Seam 对话以及工作区管理

热门文章

  1. 一些恶心的代码片段,你看了就知道!
  2. Linux 需要的常用操作,你只差这篇文章
  3. MySQL数据库备份之主从同步配置
  4. org.springframework.dao.InvalidDataAccessApiUsageException: Write operations
  5. java时钟面板clock
  6. 使用tab键分割的文章能快速转换成表格。( )_电脑上Tab键的8种超强用法,每一个都让人大开眼界!...
  7. 一个简单的jQuery例子,动态添加表格和删除
  8. 安装mysql.dox_linux虚拟机上装mysql数据库-Go语言中文社区
  9. python降温了吗_为“Python将纳入高考”降温
  10. 13道BGP属性面试题