MXNet官方文档教程(7):训练和推断模型

训练和推断模型

我们在module(缩写mod)包中模块化了经常用到的训练和推断模型的代码。这个包提供了中层和高层接口来执行已定义好的网络。

 

基础用法

准备

在本部分教程中,我们将使用一个十类的多层感知机和一个综合数据集。

import mxnet as mx

from data_iter import  SyntheticData

 

# mlp

net = mx.sym.Variable('data')

net = mx.sym.FullyConnected(net,name='fc1', num_hidden=64)

net = mx.sym.Activation(net,name='relu1', act_type="relu")

net = mx.sym.FullyConnected(net,name='fc2', num_hidden=10)

net = mx.sym.SoftmaxOutput(net,name='softmax')

# synthetic 10classes dataset with 128 dimension

data = SyntheticData(10, 128)

mx.viz.plot_network(net)


建立模型

最常应用的模块类是包括一个Symbol和一个或多个Executor的Module。

 

为了构建一个模型,我们需要指定:

l  symbol:网络符号

l  context:执行设备(设备列表)

l  data_names:数据变量名称列表

l  label_names:标签变量名称列表

 

可以通过参考data.ipynb获得后两个参数的详细及信息。这里我们仅有一个名称为data的数据,和一个名称为softmax_label的标签。softmax_label是由名称softname自动得到的名称,softname是我们指定的SoftmaxOutput 操作符的名称。

mod= mx.mod.Module(symbol=net,
                    context=mx.cpu(),
                    data_names=['data'],
                    label_names=['softmax_label'])

 

训练,预测和评估

Modules提供训练/预测/评估的高层API。为了适配一个模型,只需要使用fit函数和一些DataIters。

# @@@ AUTOTEST_OUTPUT_IGNORED_CELL
import logging
logging.basicConfig(level=logging.INFO)
 
batch_size=32
mod.fit(data.get_iter(batch_size),
        eval_data=data.get_iter(batch_size),
        optimizer='sgd',
        optimizer_params={'learning_rate':0.1},
        eval_metric='acc',
        num_epoch=5)

输出

INFO:root:Epoch[0] Train-accuracy=0.081250
INFO:root:Epoch[0] Time cost=0.103
INFO:root:Epoch[0] Validation-accuracy=0.228125
INFO:root:Epoch[1] Train-accuracy=0.178125
INFO:root:Epoch[1] Time cost=0.070
INFO:root:Epoch[1] Validation-accuracy=0.181250
INFO:root:Epoch[2] Train-accuracy=0.150000
INFO:root:Epoch[2] Time cost=0.061
INFO:root:Epoch[2] Validation-accuracy=0.112500
INFO:root:Epoch[3] Train-accuracy=0.196875
INFO:root:Epoch[3] Time cost=0.073
INFO:root:Epoch[3] Validation-accuracy=0.187500
INFO:root:Epoch[4] Train-accuracy=0.250000
INFO:root:Epoch[4] Time cost=0.076
INFO:root:Epoch[4] Validation-accuracy=0.078125

为了使用一个模型进行预测,只需要使用predict函数和一个DataIter。它会收集并返回所有的预测结果。

y= mod.predict(data.get_iter(batch_size))
'shape of predict: %s'% (y.shape,)

输出

'shape of predict: (320L, 10L)'

当预测结果过大以至于存储器无法满足时,另一个的方便的API是iter_predict:

# @@@ AUTOTEST_OUTPUT_IGNORED_CELL
for preds, i_batch, batch in mod.iter_predict(data.get_iter(batch_size)):
    pred_label = preds[0].asnumpy().argmax(axis=1)
    label = batch.label[0].asnumpy().astype('int32')
    print('batch %d, accuracy %f'% (i_batch, float(sum(pred_label==label))/len(label)))

输出

batch 0, accuracy 0.062500
batch 1, accuracy 0.156250
batch 2, accuracy 0.187500
batch 3, accuracy 0.000000
batch 4, accuracy 0.062500
batch 5, accuracy 0.000000
batch 6, accuracy 0.062500
batch 7, accuracy 0.093750
batch 8, accuracy 0.062500
batch 9, accuracy 0.062500

如果我们不需要预测输出结果,只需要在一个数据集上评估性能,我们可以使用score函数与一个DataIter以及一个EvalMetric:

# @@@ AUTOTEST_OUTPUT_IGNORED_CELL
mod.score(data.get_iter(batch_size), ['mse','acc'])

输出

[('mse', 27.438781929016113), ('accuracy', 0.115625)]

 

保存与载入

我们可以通过使用一个检查点回调函数,来保存每一轮训练的模型参数。

# @@@ AUTOTEST_OUTPUT_IGNORED_CELL
# construct a callback function to save checkpoints
model_prefix='mx_mlp'
checkpoint= mx.callback.do_checkpoint(model_prefix)
 
mod= mx.mod.Module(symbol=net)
mod.fit(data.get_iter(batch_size), num_epoch=5, epoch_end_callback=checkpoint)

输出

INFO:root:Epoch[0] Train-accuracy=0.140625
INFO:root:Epoch[0] Time cost=0.062
INFO:root:Saved checkpoint to "mx_mlp-0001.params"
INFO:root:Epoch[1] Train-accuracy=0.106250
INFO:root:Epoch[1] Time cost=0.075
INFO:root:Saved checkpoint to "mx_mlp-0002.params"
INFO:root:Epoch[2] Train-accuracy=0.146875
INFO:root:Epoch[2] Time cost=0.084
INFO:root:Saved checkpoint to "mx_mlp-0003.params"
INFO:root:Epoch[3] Train-accuracy=0.140625
INFO:root:Epoch[3] Time cost=0.077
INFO:root:Saved checkpoint to "mx_mlp-0004.params"
INFO:root:Epoch[4] Train-accuracy=0.190625
INFO:root:Epoch[4] Time cost=0.073
INFO:root:Saved checkpoint to "mx_mlp-0005.params"

使用load_checkpoint函数来载入保存的模型参数。load_checkpoint载入符号和与其相关的参数。之后,我们可以将载入的参数设置到模型中。

sym, arg_params, aux_params = mx.model.load_checkpoint(model_prefix,3)
print(sym.tojson()== net.tojson())
 
# assign the loaded parameters to the module
mod.set_params(arg_params, aux_params)

输出

True

或者我们只是想在保存的检查点继续训练,我们可以直接使用fit函数代替set_params函数传递载入的参数。这样fit函数就知道使用这些参数开始训练,而不是随机初始化参数。我们也可以设置begin_epoch ,这样fit函数知道我们是在一个之前保存的训练轮次上继续的。

# @@@ AUTOTEST_OUTPUT_IGNORED_CELL
mod= mx.mod.Module(symbol=sym)
mod.fit(data.get_iter(batch_size),
        num_epoch=5,
        arg_params=arg_params,
        aux_params=aux_params,
        begin_epoch=3)

输出

INFO:root:Epoch[3] Train-accuracy=0.115625
INFO:root:Epoch[3] Time cost=0.064
INFO:root:Epoch[4] Train-accuracy=0.115625
INFO:root:Epoch[4] Time cost=0.058

 

 

使用Module作为计算“机”

我们已经知道如何使用module来进行基本的训练和推断。现在我们将展示module的一个更加灵活的用法。

 

一个module代表着一个计算组成。module的设计目的就是抽象一个可以接收Symbol程序和数据的计算“机”。然后我们可以在其上执行正向传播算法、反向传播算法、更新参数等。

 

我们致力于使API简单灵活,尤其是当我们需要使用必要的API来处理多模型的情况时(例如随机深度网络)。

 

module包括以下声明:

l 初始化声明:此时还未为其分配初始化空间,也还未准备好开始计算。

l 绑定:输入输出的大小和参数都已知,内存被分配,为计算做好了准备。

l 变量初始化:对于带参数的module,在初始化参数之前执行计算可能会导致未定义的输出。

l 优化器安装:优化器可被安装到一个module上。之后,在计算出梯度后,模型的参数可以根据优化器进行更新。

以下代码实现了一个简化的fit()。在此我们用到的初始化器(Initalizer)、优化器(Optimizer)和度量(Metric)在其他的教程中有所解释。

# @@@ AUTOTEST_OUTPUT_IGNORED_CELL
# initial state
mod= mx.mod.Module(symbol=net)
 
# bind, tell the module the data and label shapes, so
# that memory could be allocated on the devices for computation
train_iter= data.get_iter(batch_size)
mod.bind(data_shapes=train_iter.provide_data, label_shapes=train_iter.provide_label)
 
# init parameters
mod.init_params(initializer=mx.init.Xavier(magnitude=2.))
 
# init optimizer
mod.init_optimizer(optimizer='sgd', optimizer_params=(('learning_rate',0.1), ))
 
# use accuracy as the metric
metric= mx.metric.create('acc')
 
# train one epoch, i.e. going over the data iter one pass
for batch in train_iter:
    mod.forward(batch, is_train=True)       # compute predictions
    mod.update_metric(metric, batch.label)  # accumulate prediction accuracy
    mod.backward()                          # compute gradients
    mod.update()                            # update parameters using SGD
    
# training accuracy
print(metric.get())

输出

('accuracy', 0.59375)

除了优化器之外,module还提供了大量有用的信息。

 

基本名称:

l data_name:所需数据的名称的string列表。

l output_name:输出名称的string列表。

声明信息:

l binded:bool类型,表示计算所需的存储空间是否已被分配。

l for_training:module是否已经绑定了训练数据(如果已被分配空间)。

l params_initialized:bool类型,表示模型的参数是否已经初始化。

l inputs_need_grad:bool类型,表示是否需要输入数据的梯度。在实现模型组成时有用。

输入输出信息:

l data_shape:(name,shape)列表。理论上,只要内存分配好了,我们可以直接提供数据数组。但是在数据并行的情况下,数据数组大小在外界世界看了可能不是同样的大小。

l label_shape:(name,shape)列表。这个变量有可能为空如果模型不需要标签(例如在顶层不包含损失函数loss function),或者module没被绑定为训练。

l output_shanpe:module输出的(name,shape)列表。

参数变量(模型参数):

l get_params():返回(arg_params,aux_params)元组。每一个元素为一个从名称到NDArray映射的字典。这些NDArray通常位于CPU。真实的用于计算的参数也可能位于其他设备(GPU),这个函数将返回最新的参数(的复制)。

l get_outputs():获取前一个操作的输出。

l get_input_grads():获取之前由反向传播操作计算出的输入的梯度。

print((mod.data_shapes, mod.label_shapes, mod.output_shapes))
print(mod.get_params())

输出

([DataDesc[data,(32, 128),<type 'numpy.float32'>,NCHW]], [DataDesc[softmax_label,(32,),<type 'numpy.float32'>,NCHW]], [('softmax_output', (32, 10L))])
({'fc2_bias': <NDArray 10 @cpu(0)>, 'fc2_weight': <NDArray 10x64 @cpu(0)>, 'fc1_bias': <NDArray 64 @cpu(0)>, 'fc1_weight': <NDArray 64x128 @cpu(0)>}, {})

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值