利用Module模塊把構建的神經網絡跑起來


訓練一個神經網絡往往只需要簡單的幾步:

  1. 准備訓練數據
  2. 初始化模型的參數
  3. 模型向往計算與向后計算
  4. 更新模型參數
  5. 設置相關的checkpoint

如果上述的每個步驟都需要我們寫Python的代碼去一步步實現,未免顯的繁瑣,好在MXNet提供了Module模塊來解決這個問題,Module把訓練和推理中一些常用到的步驟代碼進行了封裝。對於一定已經用Symbol定義好的神經網絡,我們可以很容易的使用Module提供的一些高層次接口或一些中間層次的接口來讓整個訓練或推理容易操作起來。

下面我們將通過在UCI letter recognition數據集上訓練一個多層感知機來說明Module模塊的用法。

第一步 加載一個數據集

我們先下載一個數據集,然后按80:20的比例划分訓練集與測試集。我們通過MXNet的IO模塊提供的數據迭代器每次返回一個batch size =32的訓練樣本

import logging
logging.getLogger().setLevel(logging.INFO)
import mxnet as mx
import numpy as np

# 數據以文本形式保存,每行一個樣本,每一行數據之間用','分割,每一個字符為label
fname = mx.test_utils.download('http://archive.ics.uci.edu/ml/machine-learning-databases/letter-recognition/letter-recognition.data')
data = np.genfromtxt(fname, delimiter=',')[:,1:]
label = np.array([ord(l.split(',')[0])-ord('A') for l in open(fname, 'r')])

batch_size = 32
ntrain = int(data.shape[0]*0.8)
train_iter = mx.io.NDArrayIter(data[:ntrain, :], label[:ntrain], batch_size, shuffle=True)
val_iter = mx.io.NDArrayIter(data[ntrain:, :], label[ntrain:], batch_size)

第二步 定義一個network

net = mx.sym.var('data')
net = mx.sym.FullyConnected(data=net, name='fc1', num_hidden=64)
net = mx.sym.Activation(data=net, name='relu1', act_type='relu')
net = mx.sym.FullyConnected(data=net, name='fc2', num_hidden=26)
net = mx.sym.SoftmaxOutput(net, name='softmax')
mx.viz.plot_network(net)

第三步 創建一個Module

我們可以通過mx.mod.Module接口創建一個Module對象,它接收下面幾個參數:

  • symbol:神經網絡的定義
  • context:執行運算的設備
  • data_names:網絡輸入數據的列表
  • label_names:網絡輸入標簽的列表

對於我們在第二步定義的net,只有一個輸入數據即data,輸入標簽名為softmax_label,這個是我們在使用SoftmaxOutput操作時,自動命名的。

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

Module的中間層次的接口

中間層次的接口主要是為了給開發者足夠的靈活性,也方便排查問題。我們下面會先列出來Moduel模塊有哪些常見的中間層API,然后再利用這個API來訓練我們剛才定義的網絡。

  • bind:綁定輸入數據的形狀,分配內存
  • init_params:初始化網絡參數
  • init_optimizer:指定優化方法,比如sgd
  • metric.create:指定評價方法
  • forward:向前計算
  • update_metric:根據上一次的forward結果,更新評價指標
  • backward:反射傳播
  • update:根據優化方法和梯度更新模型的參數
# allocate memory given the input data and label shapes
mod.bind(data_shapes=train_iter.provide_data, label_shapes=train_iter.provide_label)
# initialize parameters by uniform random numbers
mod.init_params(initializer=mx.init.Uniform(scale=.1))
# use SGD with learning rate 0.1 to train
mod.init_optimizer(optimizer='sgd', optimizer_params=(('learning_rate', 0.1), ))
# use accuracy as the metric
metric = mx.metric.create('acc')
# train 5 epochs, i.e. going over the data iter one pass
for epoch in range(5):
    train_iter.reset()
    metric.reset()
    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
    print('Epoch %d, Training %s' % (epoch, metric.get()))

Module 高層次的API

訓練

Moudle模塊同時提供了高層次的API來完成訓練、預測和評估。不像使用中間層次API那樣繁瑣,我們只需要一個接口fit就可以完成上面的步驟。

# reset train_iter to the beginning
train_iter.reset()

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

# fit the module
mod.fit(train_iter,
        eval_data=val_iter,
        optimizer='sgd',
        optimizer_params={'learning_rate':0.1},
        eval_metric='acc',
        num_epoch=8)

預測和評估

使用Moudle.predict可以得到數據的predict的結果。如果我們對結果不關心,我們可以使用score接口直接計算驗證數據集的准確率。

y = mod.predict(val_iter)
score = mod.score(val_iter, ['acc'])
print("Accuracy score is %f" % (score[0][1]))

上面的代碼中我們使用了acc來計算准確率,我們還可以設置其他評估方法,如:top_k_acc,F1,RMSE,MSE,MAE,ce等。

訓練模型的保存

我們可以通過設計一個checkpoint calback來在訓練過程中每個epoch結束后保存模型的參數

# 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(train_iter, num_epoch=5, epoch_end_callback=checkpoint)

使用load_checkpoint來加載已經保存的模型參數,隨后我們可以把這些參數加載到Moudle中

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

我們也可以不使用set_params,而是直接在fit接口中指定已經保存的checkpoint的參數,這些保存的參數會替代fit原本的參數初始化。

mod = mx.mod.Module(symbol=sym)
mod.fit(train_iter,
        num_epoch=21,
        arg_params=arg_params,
        aux_params=aux_params,
        begin_epoch=3)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM