從零開始學習MXnet(三)之Model和Module

  在咱們在MXnet中定義好symbol、寫好dataiter而且準備好data以後,就能夠開開心的去訓練了。通常訓練一個網絡有兩種經常使用的策略,基於model的和基於module的。今天,我想談一談他們的使用。html

1、Modelpython

  按照老規矩,直接從官方文檔裏面拿出來的代碼看一下:api

  

 # configure a two layer neuralnetwork
    data = mx.symbol.Variable('data')
    fc1 = mx.symbol.FullyConnected(data, name='fc1', num_hidden=128)
    act1 = mx.symbol.Activation(fc1, name='relu1', act_type='relu')
    fc2 = mx.symbol.FullyConnected(act1, name='fc2', num_hidden=64)
    softmax = mx.symbol.SoftmaxOutput(fc2, name='sm')
# create a model using sklearn-style two-step way
#建立一個model 
   model = mx.model.FeedForward(
         softmax,
         num_epoch=num_epoch,
         learning_rate=0.01)
#開始訓練
    model.fit(X=data_set)

  具體的API參照http://mxnet.io/api/python/model.html。網絡

  而後呢,model這部分就說完了。。。之因此這麼快主要有兩個緣由:框架

    1.確實東西很少,通常都是查一查文檔就能夠了。ide

    2.model的可定製性不強,通常咱們是不多使用的,經常使用的仍是module。函數

2、Module設計

  Module真的是一個很棒的東西,雖然深刻了解後,你會以爲「哇,好厲害,可是感受沒什麼鳥用呢」這種想法。。實際上我就有過,如今回想起來,從代碼的設計和使用的角度來說,Module確實是一個很是好的東西,它能夠爲咱們的網絡計算提升了中級、高級的接口,這樣一來,就能夠有不少的個性化配置讓咱們本身來作了。htm

  Module有四種狀態:blog

    1.初始化狀態,就是顯存尚未被分配,基本上啥都沒作的狀態。

    2.binded,在把data和label的shape傳到Bind函數裏而且執行以後,顯存就分配好了,能夠準備好計算能力。

    3.參數初始化。就是初始化參數

    3.Optimizer installed 。就是傳入SGD,Adam這種optimuzer中去進行訓練 

 

 先上一個簡單的代碼:

  

import mxnet as mx

    # construct a simple MLP
    data = mx.symbol.Variable('data')
    fc1  = mx.symbol.FullyConnected(data, name='fc1', num_hidden=128)
    act1 = mx.symbol.Activation(fc1, name='relu1', act_type="relu")
    fc2  = mx.symbol.FullyConnected(act1, name = 'fc2', num_hidden = 64)
    act2 = mx.symbol.Activation(fc2, name='relu2', act_type="relu")
    fc3  = mx.symbol.FullyConnected(act2, name='fc3', num_hidden=10)
    out  = mx.symbol.SoftmaxOutput(fc3, name = 'softmax')

    # construct the module
    mod = mx.mod.Module(out)
   
     mod.bind(data_shapes=train_dataiter.provide_data,
         label_shapes=train_dataiter.provide_label)
   
     mod.init_params()
     mod.fit(train_dataiter, eval_data=eval_dataiter,
            optimizer_params={'learning_rate':0.01, 'momentum': 0.9},
            num_epoch=n_epoch)

  分析一下:首先是定義了一個簡單的MLP,symbol的名字就叫作out,而後能夠直接用mx.mod.Module來建立一個mod。以後mod.bind的操做是在顯卡上分配所需的顯存,因此咱們須要把data_shapehe label_shape傳遞給他,而後初始化網絡的參數,再而後就是mod.fit開始訓練了。這裏補充一下。fit這個函數咱們已經看見兩次了,實際上它是一個集成的功能,mod.fit()實際上它內部的核心代碼是這樣的:

  

for epoch in range(begin_epoch, num_epoch): 
             tic = time.time() 
             eval_metric.reset() 
             for nbatch, data_batch in enumerate(train_data): 
                 if monitor is not None: 
                     monitor.tic() 
                 self.forward_backward(data_batch) #網絡進行一次前向傳播和後向傳播
                 self.update()  #更新參數
                 self.update_metric(eval_metric, data_batch.label) #更新metric 
 
 
                 if monitor is not None: 
                     monitor.toc_print() 
 

                 if batch_end_callback is not None: 
                     batch_end_params = BatchEndParam(epoch=epoch, nbatch=nbatch, 
                                                      eval_metric=eval_metric, 
                                                      locals=locals()) 
                     for callback in _as_list(batch_end_callback): 
                         callback(batch_end_params) 

  正是由於module裏面咱們能夠使用不少intermediate的interface,因此能夠作出不少改進,舉個最簡單的例子:若是咱們的訓練網絡是大小可變怎麼辦? 咱們能夠實現一個mutumodule,基本上就是,每次data的shape變了的時候,咱們就從新bind一下symbol,這樣訓練就能夠照常進行了。

  

  總結:實際上學一個框架的關鍵仍是使用它,要說訣竅的話也就是多看看源碼和文檔了,我寫這些博客的目的,一是爲了記錄一些東西,二是讓後來者少走一些彎路。因此有些東西不會說的很全。。

相關文章
相關標籤/搜索