構成符號:
符號對我們想要進行的計算進行了描述, 下圖展示了符號如何對計算進行描述. 下圖定義了符號變量A, 符號變量B, 生成了符號變量C, 其中, A, B為參數節點, C為內部節點! mxnet.symbol.Variable可以生成參數節點, 用於表示計算時的輸入.
一個Symbol具有的屬性和方法如下圖所示:
對神經網絡進行配置:
一個Symbol的list_argument()屬性可以用來檢查計算圖的輸入參數; list_output()屬性可以返回此Symbol的所有輸出! 輸出的自動命名遵循了一定的規則,具體見下面的程序!
input = mx.sym.Variable('data') # 生成一個符號變量,名字是可以隨便取的 fc1 = mx.sym.FullyConnected(data=input, num_hidden=128,name='fc1') # 全連接層 act1 = mx.sym.Activation(fc1, act_type='relu') # 激活
type(fc1) # mxnet.symbol.Symbol, act1的類型也是這個!!!
fc1.list_outputs() # ['fc1_output'],自動在輸入name屬性名的后面加上"_output"作為本節點名稱
fc1.list_arguments() # ['data','fc1_weight','fc1_bias'],自動生成fc1_weight,fc1_bias兩個參數節點
act1.list_outputs() # ['actvation0_output'] 這個名字就不是隨便起的了!!!
act1.list_arguments() # ['data','fc1_weight','fc1_bias'
mxnet.symbol.Symbol.infer_shape(self, *args, **kwargs): 推測輸入參數和輸出參數的shape, 返回一個list of tuple;
a = mx.sym.Variable('A') b = mx.sym.Variable('B') c = (a + b) / 10 d = c + 1 input_shapes = {'A':(10,2), 'B':(10,2)} # 定義輸入的shape d.infer_shape(**input_shapes) # ([(10L, 2L), (10L, 2L)], [(10L, 2L)], []) arg_shapes, out_shapes, aux_shapes = d.infer_shape(**input_shapes) In [1]: arg_shapes Out[1]: [(10L, 2L), (10L, 2L)] In [2]: out_shapes Out[2]: [(10L, 2L)] In [3]: aux_shapes Out[3]: []
多輸入網絡實例:
下面的圖對一個多輸入神經網絡進行配置:
綁定以及執行Symbol:
當需要對符號圖進行執行時,我們需要調用綁定函數(bind function:*.bind)來綁定NDArrays(下圖中的a/b/d)到參數節點(argument nodes: A/B/D,不是內部節點C/E),從而獲得一個執行器(Executor)
然后,調用Executor.Forward 便可以得到輸出結果.
A = mx.sym.Variable('A') B = mx.sym.Variable('B') C = A * B D = mx.sym.Variable('D') E = C + D a = mx.nd.empty(1) # 生成一個維度為1的隨機值 b = mx.nd.ones(1) # b等於1 d = mx.nd.ones(1) executor = E.bind(ctx=mx.cpu(), args={'A':a, 'B':b, 'D':d}) type(executor) # mxnet.executor.Executor executor.arg_dict # {'A': <NDArray 1 @cpu(0)>, 'B': <NDArray 1 @cpu(0)>, 'D': <NDArray 1 @cpu(0)>} executor.forward() # [<NDArray 1 @cpu(0)>] executor.outputs[0] # <NDArray 1 @cpu(0)>, 值呢? 還是看不到值啊???
executor.outputs[0].asnumpy() # array([ 1.], dtype=float32)
一個Executor具有的屬性和方法如下圖所示:
綁定多個輸出:
我們可以使用mx.symbol.Group([])來將symbols進行分組,然后將它們進行綁定: 下圖中,A/B/D為參數節點,C/E為內部節點,將E/C綁定為G,這樣,E和C的計算結果都可以得到! 但是建議如果我們只需要E的計算結果的話,建議只綁定E自己,這樣更加優化!
梯度計算:
在綁定函數中,可以指定NDArrays來保存梯度,在Executor.forward()的后面調用Executor.backward()可以得到相應的梯度值.
神經網絡的簡單綁定接口:
有時,將一大推的NDArrays傳遞給綁定函數是很繁瑣的,Symbol.simple_bind()這個函數可以幫助我們簡化這個過程,你僅僅需要指定輸入數據的大小(shape),這個函數可以定位到這個參數並將其綁定為Executor.
輔助變量:
參考文獻:
[1] Symbolic Configuration and Execution in Pictures: http://mxnet-bing.readthedocs.io/en/latest/supported_languages/python/symbol_in_pictures.html
[2] MXNet實戰: http://www.linuxeden.com/html/news/20160413/165698.html