MXNet基本指南
打开mxnet
source activate gluon # 注意Windows下不需要 source
退出环境source deactivate
GPU版本进入环境后如果用指定的卡可以
CUDA_VISIBLE_DEVICES=2 python
,这样数据只能分配在一个GPU上- 可以尝试将数据全部放进内存,如果是不规则数据集,numpy处理不了可以用python自带的数组处理
CUDA_VISIBLE_DEVICES=2 jupyter notebook
,进入jupyter后再导入mxnet,如果使用GPU训练,也只训练在一块卡上- 升级
pip install mxnet --upgrade
,安装每日更新版本可以加上--pre
参数。pip search mxnet
可以看到还有许多mxnet版本,比如mxnet-cu75、mxnet-cu80、mxnet-cu90等 - 可以不让MXNet占用过多显存,设置保留的百分数
export MXNET_GPU_MEM_POOL_RESERVE=5
MXNet如何处理训练模式和测试模式
Gluon:若在调研网络时被with autograd.record()
包裹,那么这时Gluon是训练模式。如果没有则是测试模式。可以参见在论坛的帖子得到一些证明
MNNet的Module加载模型并运算默认是训练模式,测试模式需要指明mod.forward(Batch([x]),is_train=False),MNNet的新版加载函数(v1.2.1以上)加载模型方式(mx.gluon.nn.SymbolBlock.imports
)并运算默认是测试模式
C++:默认是测试模式
模型的导入导出
在1.3.0版本之前,我对于Hybrid模型采用export导出,LSTM这种无法Hybrid化的模型采用save_params的方式。
但是save_params方式一方面无法载入C++,一方面每次Python导入模型都要重新定义网络结构,很麻烦
今天才知道一个v1.2.1之后引入了有趣的导入函数mx.gluon.nn.SymbolBlock.imports
,模型采用export导出后(1.3.0版本之后rnn、lstm等也可以顺利导出了),就有params和json两个文件,分别存储权重和网络结构,即可预测了
下面这个例子显示的结果一样,但是更简单便捷。
DNN的输入: (batch, 535) 输出:(batch, 43)
LSTM的输入:(duration, batch, 535) 输出:(duration, batch, 43)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21import mxnet as mx
from mxnet import gluon
from collections import namedtuple
data= mx.random.uniform(shape=(3,535))
##### New way #####
# import LSTM model
net = gluon.nn.SymbolBlock.imports('LSTM-symbol.json', ['data'], param_file='LSTM-0000.params', ctx=mx.cpu())
print net(mx.nd.zeros(shape=(3,1,535))) #100 can be other number
# import DNN model
net = gluon.nn.SymbolBlock.imports('DNN-symbol.json', ['data'], param_file='DNN-0000.params', ctx=mx.cpu())
print net(data) #100 can be other number
##### Old way #####
# import DNN model
sym = mx.symbol.load('DNN-symbol.json')
mod=mx.mod.Module(symbol=sym)
mod.bind(data_shapes=[('data',(1,535))])
mod.load_params('DNN-0000.params')
Batch=namedtuple('Batch',['data'])
mod.forward(Batch([data]),is_train=False)
print mod.get_outputs()[0]
数据操作
expand_dims和flatten
data是(3,4)的形状,如果想变成(3,1,4),可以reshape,但是更好的办法是.expand_dims(axis=1)
,再变回去也只要.flatten()
就行,因为flatten函数会将输入的(d1,d2,d3…)维度变为(d1,d2d3…)
nd.concatenate(被弃用,改为nd.concat)
1 | print img_list[0].shape #(1L, 3L, 64L, 64L) 每个都是这样的形状 |
nd.concatenate([history,temp],axis=1)
或者nd.concat(history,temp,dim=1)
对应F.concat(history, temp, dim=1)
计算L2Loss
1 | import mxnet as mx |
网络
RNN
1 | layer = mx.gluon.rnn.RNN(100, 3) |
Embedding
1 | net.weight.data().asnumpy() |
mask-RNN
重要的SequenceMask函数
第二个参数表示这个mini-batch内几个样本是真实的,这里代表两个真实1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25x = mx.nd.array([[[ 1., 2., 3.],
[ 4., 5., 6.]],
[[ 7., 8., 9.],
[ 10., 11., 12.]],
[[ 13., 14., 15.],
[ 16., 17., 18.]]])
#x.shape=(3L,2L,3L)
res=mx.nd.SequenceMask(x,mx.nd.array([2,1]), use_sequence_length=True)
print res
#表明第一个batch保留两个time-stseps,第二个batch保留1个time-stsep
# 得到
# [[ 1. 2. 3.]
# [ 4. 5. 6.]]
# [[ 7. 8. 9.]
# [ 0. 0. 0.]]
# [[ 0. 0. 0.]
# [ 0. 0. 0.]]]
#这样的话 res[:,0,:]取出的就是第一个batch加了mask的结果
# [[ 1. 2. 3.]
# [ 7. 8. 9.]
# [ 0. 0. 0.]]
# res[:,1,:]取出的就是第2个batch加了mask的结果
# [[ 4. 5. 6.]
# [ 0. 0. 0.]
# [ 0. 0. 0.]]
首先解决带mask的loss
1 | # -*- coding: utf-8 -*- |
网络可视化
sym.list_outputs()
列出一个模型输出端口的名字
sym.list_arguments()
列出一个模型的输入端口的名字以及权重和偏置的名字
sym.tojson()
可以打印出网络结构
mod.get_outputs()
列出前馈的输出
显示网络结构 viz.plot_network
直接显示网络结构mx.viz.plot_network(symbol=sym)
1 | graph = Import["ExampleData/mxnet_example2.json", {"MXNet", "NodeGraphPlot"}] |
1 | graph = Import["ExampleData/mxnet_example2.json", {"MXNet", "NodeGraph"}] |
MXNet高阶应用
MXNet与C++联动
步骤
- 在python中训练MXNet模型
- 在python中导入模型,并进行预测
- 在C++中导入模型(在小例子上进行验证两个接口结果一致)
- 在C++项目中使用模型
配置C++平台
- 在C++/常规中添加“附加包含目录”,即工作目录,方便定位c_predict_api.h的位置。如果能成功#include的话,不设置也行
- 在链接器/输入中增加“附加依赖项”,即libmxnet.lib
- 修改“活动解决方案平台”为x64
- 拷贝libmxnet.dll和libmxnet.lib和c_predict_api.h到工作目录
- cpp文件加入#include <c_predict_api.h>
C++使用指南
- 可运行单输入单输出 默认采用预测方式
- 可运行多输入多输出 默认采用预测方式
- 可运行多输入多输出 但是在输出端口可以只输出一个端口的数据
- 修改预测支持一个mini-batch只需要修改input_shape_data中的batch_size,并且将一个mini-batch的输入数据压平送进网络。在设置输入输出端口的vector的大小时候都要把它设置为一个batch数据长度的batch_size倍
利用HDF5文件做迭代器用于训练
1 | import mxnet as mx |
单输入单输出Seq2Seq模型
Python代码(HybridBlock版本)
1 | import mxnet as mx |
C++导入模型再预测 代码
1 |
|
简单的多输入多输出网络
Python代码(普通版本)
1 | from mxnet import nd |
Python代码(HybridBlock版本)
1 | from mxnet import nd |
C++导入模型再预测 代码
1 |
|
训练模板
单输入单输出
1 | import mxnet as mx |
导入测试
1 | import mxnet as mx |
多输入多输出
1 | import mxnet as mx |
导入测试
1 | import mxnet as mx |
MXNet源码阅读
io.py
位于E:\Anaconda\envs\gluon\Lib\site-packages\mxnet
阅读如何自定义迭代器