MXNet實戰之多層感知機
阿新 • • 發佈:2018-12-18
這是來自MXNet官網裡面的一個例子,利用module包[1]來構建一個多層感知機,並在UCI letter recognition[2]中進行訓練。利用module包來訓練網路,可以採用兩種介面:中層介面和高層介面。高層介面可以看做是對中層介面的一種封裝。 其基本步驟大致如下:載入資料、定義網路、建立module模組、呼叫介面進行訓練。
載入資料
載入資料的目的是將訓練集和驗證集載入到記憶體中。因為,我們訓練網路的資料集比較大,所以我們一般使用一個迭代器,這樣每次只用載入batch大小的資料。 下面是下載該資料集,並將資料集按照8:2的比例分為訓練集和測試集。
import logging logging.getLogger().setLevel(logging.INFO) import mxnet as mx import numpy as np mx.random.seed(1234) fname = mx.test_utils.download('https://s3.us-east-2.amazonaws.com/mxnet-public/letter_recognition/letter-recognition.data') data = np.genfromtxt(fname, delimiter=',)[:,1:] #data.shape = (10000L, 16L) 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)
定義網路
利用symbol介面定義網路模型,包括網路的輸入和標籤。
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=26) net = mx.sym.SoftmaxOutput(net, name="softmax") mx.viz.plot_network(net) # 顯示網路模型
建立module模組
mod = mx.mod.Module(symbol=net, context=mx.cpu(), # context指定cpu或是gpu
data_names=['data'],
label_names=['softmax_label'])
中層介面
採用中層介面的好處是便於debug。因為,中層介面需要明確寫出forward和backward。如下程式碼:
mod.bind(data_shapes=train_iter.provide_data, label_shapes=train_iter.provide_label) mod.init_params(initializer=mx.init.Uniform(scale=.1)) mod.init_optimizer(optimizer='sgd',optimizer_params=(('learning_rate',0.1),)) metric=mx.metric.create('acc') for epoch in range(5): train_iter.reset() metric.reset() for batch in train_iter: mod.forward(batch, is_train=True) mod.update_metric(metric, batch.label) mod.backward() mod.update() print('Epoch %d, Training %s' % (epoch, metric.get()))
採用高層介面
train_iter.reset()
mod = mx.mod.Module(symbol=net, context=mx.cpu(),
data_names=['data'], label_name=['softmax_label'])
mod.fit(train_iter, eval_data=val_iter,
optimizer='sgd', optimizer_params={'learning_rate':0.1},
eval_metric='acc', num_epoch=60)
可以看出,module為了方便,將訓練、預測和評價等操作都進行了封裝。與中層介面不同,需要一步一步來操作,module包直接呼叫了fit函式介面就完成相同的操作。
預測和指標評價
可以採用兩種方式:
# 方式一:直接獲得預測結果
y = mod.predict(val_iter)
# 方式二:直接獲得指標結果
score = mod.score(val_iter, ['acc'])
print("Accuracy score is %f" % (score[0][1]))
使用第二種方式,我們可以直接獲得指標結果,而指標我們也可以根據實際情況進行替換。如top_k_acc,F1,RMSE等等。
儲存和載入模型
使用checkpoint callback來控制每一輪迭代後是否需要自動儲存模型,如下:
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函式。這個函式載入symbol以及對應的引數,然後我們將這些模型和引數來初始化module。如下:
sym, arg_params, aux_params = mx.model.load_checkpoint(model_prefix, 3)
assert sym.tojson()==net.tojson()
mod.set_params(arg_params, aux_params)
如果我們想從某個節點訓練模型,那麼我們可以直接呼叫fit函式。在fit函式中,我們可以直接載入這些引數,而不是初始化。另外,我們可以設定begin_epoch引數,讓模型知道我們是從之前某個節點開始訓練。
mod=mx.mod.Module(symbol=sym)
mod.fit(train_iter, num_epoch=21,
arg_params=arg_params,
aux_params=aux_params,
begin_epoch=3)