Python Gluon引數和模組命名操作教程
本文例項講述了Python Gluon引數和模組命名操作。分享給大家供大家參考,具體如下:
Gluon引數和模組命名教程
在gluon裡,每個引數和塊都有一個名字(和字首)。引數名可以由使用者指定,block名也可以由使用者指定,也可以自動建立。
本教程中,我們將討論命名方面的最佳實踐。首先,import MXNet和Gluon
from __future__ import print_function import mxnet as mx from mxnet import gluon
Blocks命名
在建立block時,可以指定一個字首給它:
mydense = gluon.nn.Dense(100,prefix='mydense_') print(mydense.prefix) mydense_
若沒有指定字首,gluon會自動生成一個字首
dense0 = gluon.nn.Dense(100) print(dense0.prefix) dense0_
當你建立更多同類塊時,它們將遞增字尾命名,以避免衝突:
dense1 = gluon.nn.Dense(100) print(dense1.prefix) dense1_
引數命名
blocks中的引數將用過將block的字首新增到引數的名稱來命名:
print(dense0.collect_params()) dense0_ ( Parameter dense0_weight (shape=(100,0),dtype=<type 'numpy.float32'>) Parameter dense0_bias (shape=(100,),dtype=<type 'numpy.float32'>) )
名稱空間
為了管理巢狀block的名稱,每個塊附加有一個name_scope(名稱空間)。在name_scope中建立的block都會在其名稱前加上父block的名稱。
我們將定義一個簡單的神經網路來說明這點:
class Model(gluon.Block): def __init__(self,**kwargs): super(Model,self).__init__(**kwargs) with self.name_scope(): self.dense0 = gluon.nn.Dense(20) self.dense1 = gluon.nn.Dense(20) self.mydense = gluon.nn.Dense(20,prefix='mydense_') def forward(self,x): x = mx.nd.relu(self.dense0(x)) x = mx.nd.relu(self.dense1(x)) return mx.nd.relu(self.mydense(x))
現在例項化這個神經網路
- 注意:
model0.dense0
的名稱是model0_dense0_
而非dense0_
- 注意:我們指定
model.mydense
的字首為mydense_
,它的父類字首會自動生成並新增到前面變成model0_mydense_
這裡的名稱字首和變數名model0沒有關係,這裡就算把model0換成其他變數名比如net,字首還是model?,? 表示這是一個遞增的數字,這裡的名稱字首和
class Model
有關 若將類名Model換成Hodel,那麼後面的字首都會變成 hodel?
model0 = Model() model0.initialize() model0(mx.nd.zeros((1,20))) print(model0.prefix) print(model0.dense0.prefix) print(model0.dense1.prefix) print(model0.mydense.prefix) model0_ model0_dense0_ model0_dense1_ model0_mydense_
若我們再次例項化Model
,在Dense
前會生成一個不同的名稱。
- 注意:
model1.dense0
的名稱依然是dense0_
而非dense2_
,遵循之前在model0
中建立的dense層的命名規則。這是因為每個model的名稱空間是相互獨立
model1 = Model() print(model1.prefix) print(model1.dense0.prefix) print(model1.dense1.prefix) print(model1.mydense.prefix) model1_ model1_dense0_ model1_dense1_ model1_mydense_
建議手動為頂層的model指定一個字首,即model = Model(prefix=‘mymodel_'),以避免命名時可能出現的混淆。
相同的規則同樣適用於像Sequential這類容器block.name_scope
既可以在__init__
內使用,也可以在__init__
外使用:
注意:這裡
Sequential
也有引數prefix,是可以自己指定名稱的,不指定的話就叫Sequential
net = gluon.nn.Sequential() with net.name_scope(): net.add(gluon.nn.Dense(20)) net.add(gluon.nn.Dense(20)) print(net.prefix) print(net[0].prefix) print(net[1].prefix) sequential0_ sequential0_dense0_ sequential0_dense1_
gluon.model_zoo
也一樣
net = gluon.nn.Sequential() with net.name_scope(): net.add(gluon.model_zoo.vision.alexnet(pretrained=True)) net.add(gluon.model_zoo.vision.alexnet(pretrained=True)) print(net.prefix,net[0].prefix,net[1].prefix) sequential1_ sequential1_alexnet0_ sequential1_alexnet1_
儲存和載入
由於model0和model1有不同的字首,所以它們的引數是有不同名字的:
print(model0.collect_params(),'\n') print(model1.collect_params()) model0_ ( Parameter model0_dense0_weight (shape=(20L,20L),dtype=<type 'numpy.float32'>) Parameter model0_dense0_bias (shape=(20L,dtype=<type 'numpy.float32'>) Parameter model0_dense1_weight (shape=(20L,dtype=<type 'numpy.float32'>) Parameter model0_dense1_bias (shape=(20L,dtype=<type 'numpy.float32'>) Parameter model0_mydense_weight (shape=(20L,dtype=<type 'numpy.float32'>) Parameter model0_mydense_bias (shape=(20L,dtype=<type 'numpy.float32'>) ) model1_ ( Parameter model1_dense0_weight (shape=(20,dtype=<type 'numpy.float32'>) Parameter model1_dense0_bias (shape=(20,dtype=<type 'numpy.float32'>) Parameter model1_dense1_weight (shape=(20,dtype=<type 'numpy.float32'>) Parameter model1_dense1_bias (shape=(20,dtype=<type 'numpy.float32'>) Parameter model1_mydense_weight (shape=(20,dtype=<type 'numpy.float32'>) Parameter model1_mydense_bias (shape=(20,dtype=<type 'numpy.float32'>) )
若你嘗試將model0的引數載入到model1中,你將會得到一個名稱不匹配的錯誤
model0.collect_params().save('model.params') try: model1.collect_params().load('model.params',mx.cpu()) except Exception as e: print(e)
Parameter 'model1_dense0_weight' is missing in file 'model.params',which contains parameters: 'model0_mydense_weight','model0_dense1_bias','model0_dense1_weight','model0_dense0_weight','model0_dense0_bias','model0_mydense_bias'. Please make sure source and target networks have the same prefix.
為了解決這個問題,我們使用save_parameters
/load_parameters
而不是 collect_params
和save
/load. save_parameters
。使用模型結構而非引數名稱來匹配引數。
model0.save_parameters('model.params') model1.load_parameters('model.params') print(mx.nd.load('model.params').keys()) ['dense0.bias','mydense.bias','dense1.bias','dense1.weight','dense0.weight','mydense.weight']
替換網路中的block並進行fine-turning
有時需要載入一些預訓練的模型,並替換其中某些block並進行fine-turning。
For example,the alexnet in model zoo has 1000 output dimensions,but maybe you only have 100 classes in your application.
例如,alexnet有1000個輸出維度但你只有100類。
我們首先載入預訓練的AlexNet
- 在Gluon Model Zoo,所有影象分類模型的格式都是特徵提取層叫
features
,輸出層叫output
. - 注意到輸出層是一個dense block,有1000個維度的輸出
alexnet = gluon.model_zoo.vision.alexnet(pretrained=True) print(alexnet.output) print(alexnet.output.prefix) Dense(4096 -> 1000,linear) alexnet0_dense2_
改變輸出為100維,使用一個新block替換它
with alexnet.name_scope(): alexnet.output = gluon.nn.Dense(100) alexnet.output.initialize() print(alexnet.output) print(alexnet.output.prefix) Dense(None -> 100,linear) alexnet0_dense3_
原文:http://mxnet.incubator.apache.org/versions/master/tutorials/gluon/naming.html
更多關於Python相關內容可檢視本站專題:《Python數學運算技巧總結》、《Python圖片操作技巧總結》、《Python資料結構與演算法教程》、《Python函式使用技巧總結》、《Python字串操作技巧彙總》及《Python入門與進階經典教程》
希望本文所述對大家Python程式設計有所幫助。