MXNet 的官方不是很详尽, 在使用的过程中经常要深入源码, 这里记录一下在使用的过程中总结的一些方法, 方便查阅.
回调函数参数 batch_end_callback 1 2 3 BatchEndParam = namedtuple('BatchEndParams' , ['epoch' , 'nbatch' , 'eval_metric' , 'locals' ]) batch_end_params = BatchEndParam(epoch=epoch, nbatch=nbatch, eval_metric=eval_metric, locals =locals ()) callback(batch_end_params)
epoch_end_callback 1 callback(epoch, self.symbol, arg_params, aux_params)
score_end_callback 参数和batch_end_callback相同
1 2 params = BatchEndParam(epoch=epoch, nbatch=actual_num_batch, eval_metric=eval_metric, locals =locals ()) callback(params)
CentOS 安装 MXNet pkg-config
找不到 OpenCV, pkg-config
需要配置环境变量来确定搜索路径,首先通过find
命令找到 opencv.pc
所在的目录,然后把该目录增加到环境变量 PKG_CONFIG_PATH
中。
Symbol 概述 Composite Symbol Symbol 主要是符号编程的思想
1 2 3 4 5 6 a = mx.sym.Variable('a' ) b = mx.sym.Variable('b' ) c = a + b (type (c), c.name)
Shape Inference 对于每一个 Symbol 都可以查询它的输入(或者 argument)和输出, 而且, 给定输入的 shape 还可以 inference 到输出的 shape, 这个功能的作用就是可以计算一下需要多少 memory
1 2 3 4 5 6 7 arg_name = c.list_arguments() out_name = c.list_outputs() arg_shape, out_shape, aux_shape = c.infer_shape(a=(2 ,3 ), b=(2 ,3 )) print ('inputs: %s' % (dict (zip (arg_name, arg_shape))))print ('outputs: %s' % (dict (zip (out_name, out_shape))))
Bind with Data and Evaluate 上面定义的 c
表明了需要进行什么样的计算, 但是, 只有架子没有数据填充怎么计算呢? 所以, 为了计算, 需要: feed arguments with data, 这个过程可以通过 bind
方法来解决. 参数为 1. device content 2. dict mapping free Variable name to NDArray
1 2 3 4 5 ex = c.bind(ctx=mx.cpu(), args={'a' : mx.nd.ones([2 ,3 ]), 'b' : mx.nd.ones([2 ,3 ])}) ex.forward() print ('number of outputs = %d\nthe first output = \n%s' % ( len (ex.outputs), ex.outputs[0 ].asnumpy()))
Load and Save Symbol 可以保存到文件中或者从文件中载入. 文件的格式为JSON. 当然也可以通过 cPickle 保存成二进制格式, 但是, JSON 格式易读性更好.
1 2 3 print (c.tojson())c.save('symbol-c.json' ) c2 = mx.symbol.load('symbol-c.json' )
自动求导 Symbol 和 NDArray 的一个不同点就是 Symbol 可以自动求导. 调用的方法是 grad
1 2 3 4 5 6 7 8 x = c.grad(wrt=('a' )) print x.list_arguments()print x.list_outputs()ex2 = x.bind(ctx=mx.cpu(), args={c.name+'_0_grad' : mx.nd.ones([3 ,4 ])*5 , 'a' : mx.nd.ones([3 ,4 ])*2 , 'b' : mx.nd.ones([3 ,4 ])*3 }) ex2.forward() print ex2.outputs[0 ].asnumpy()
NDArray 概述 复制 常规的 assignment 并没有真正的做 copy 操作. 只是做 reference 操作
1 2 3 4 5 6 7 a = mx.nd.ones((2 ,2 )) b = a print (b is a)def f (x ): print (id (x)) f(a) print (id (a))
真正的 copy 操作是
另外, copyto
方法和 []
操作都不会分配新的内存
1 2 3 4 5 6 b = mx.nd.ones(a.shape) print (id (b))b[:] = a print (id (b))a.copyto(b) print (id (b))
Basic Operations 对于 array
的所有的操作都是 elementwise 的. 而且会生成新的 array
, 结果保存到这个新生程的 array
中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 a = mx.nd.ones((2 ,3 )) b = mx.nd.ones((2 ,3 )) c = a + b d = - c print (d.asnumpy())e = mx.nd.sin(c**2 ).T print (e.asnumpy())f = mx.nd.maximum(a, c) print (f.asnumpy())a = mx.nd.ones((2 ,2 )) b = a * a c = mx.nd.dot(a,a) print (b.asnumpy())print (c.asnumpy())
获取中间层的输出 1 2 3 4 arg_shape, output_shape, aux_shape = net.infer_shape(input1=(8 ,3 ,32 ,32 ), input2=(8 ,3 ,32 ,32 ), input3=(8 ,3 ,32 ,32 ))
使用已有的模型初始化网络 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 old_model = mx.model.FeedForward.load("models/ir" , 1 ) model= mx.model.FeedForward( ctx=dev, symbol=get_symbol(), arg_params=old_model.arg_params, aux_params=old_model.aux_params allow_extra_params=True ) if isinstance (self.optimizer, str ): batch_size = data.batch_size if kvstore and kvstore.type == 'dist_sync' : batch_size *= kvstore.num_workers optimizer = opt.create(self.optimizer, rescale_grad=(1.0 /batch_size), **(self.kwargs)) elif isinstance (self.optimizer, opt.Optimizer): optimizer = self.optimizer
自动保存模型 1 model.fit(epoch_end_callback=mx.callback.do_checkpoint("model_name" )))
使用已有的模型初始化网络 II (推荐) 1 2 3 4 5 6 7 8 9 10 11 12 optimizer = mx.optimizer.SGD(momentum=0.99 ) model = mx.model.FeedForward( allow_extra_params=True , ctx=dev, symbol=network, num_epoch=10 , learning_rate=0.1 *1e-2 , wd=0.0001 , initializer=mx.init.Load("resnet-18-0000.params" , default_init=mx.init.Xavier(rnd_type="gaussian" , factor_type="in" , magnitude=2 )), optimizer=optimizer)
手动保存模型
获取中间层的输出结果 1 sym.get_internals()['***_output' ]
列举出所有 symbol 的 attribute 1 2 symbol.list_attr(recursive=True )
可视化网络结构 1 2 3 4 5 shape = {"data" : (128 , 3 , 28 , 28 )} g=mx.viz.plot_network(symbol=network, shape=shape) g.render(filename="filename" , cleanup=True )
其它 图片数据格式 如果使用 MXNet 提供的图片数据转换工具 im2rec.py
, 需要注意的是, 该工具把数据转换成了 RGB 格式, 所以, 实际使用的时候, 需要把通过 OpenCV 读取的图片转换成 RGB 格式, 方法如下:
1 dst = cv2.cvtColor(src, cv2.COLOR_BGR2RGB)
读取 mean.bin
在训练的过程中常常会生成 mean.bin
文件, 每张图片在 feed 到网络中之前要先减去 mean
, 因此, 在 predict 的时候, 也需要相应的减去 mean
. 首先要载入该 mean.bin
1 mean_img = mx.nd.load("./mean.bin" )['mean_img' ].asnumpy()
获取参数的 shape 1 2 3 4 ex = net.simple_bind(ctx=mx.cpu(), data=(batch_size, num_features)) args = dict (zip (net.list_arguments(), ex.arg_arrays)) for name in args: print (name, args[name].shape)