溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python Gluon參數和模塊命名操作教程

發(fā)布時間:2020-08-26 15:55:15 來源:腳本之家 閱讀:127 作者:團長sama 欄目:開發(fā)技術

本文實例講述了Python Gluon參數和模塊命名操作。分享給大家供大家參考,具體如下:

Gluon參數和模塊命名教程

在gluon里,每個參數和塊都有一個名字(和前綴)。參數名可以由用戶指定,block名也可以由用戶指定,也可以自動創(chuàng)建。

本教程中,我們將討論命名方面的最佳實踐。首先,import MXNet和Gluon

from __future__ import print_function
import mxnet as mx
from mxnet import gluon

Blocks命名

在創(chuàng)建block時,可以指定一個前綴給它:

mydense = gluon.nn.Dense(100, prefix='mydense_')
print(mydense.prefix)
mydense_

若沒有指定前綴,gluon會自動生成一個前綴

dense0 = gluon.nn.Dense(100)
print(dense0.prefix)
dense0_

當你創(chuàng)建更多同類塊時,它們將遞增后綴命名,以避免沖突:

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中創(chuàng)建的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中創(chuàng)建的dense層的命名規(guī)則。這是因為每個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_'),以避免命名時可能出現的混淆。

相同的規(guī)則同樣適用于像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, 20L), dtype=<type 'numpy.float32'>)
 Parameter model0_dense1_bias (shape=(20L,), dtype=<type 'numpy.float32'>)
 Parameter model0_mydense_weight (shape=(20L, 20L), dtype=<type 'numpy.float32'>)
 Parameter model0_mydense_bias (shape=(20L,), dtype=<type 'numpy.float32'>)
) 
model1_ (
 Parameter model1_dense0_weight (shape=(20, 0), dtype=<type 'numpy.float32'>)
 Parameter model1_dense0_bias (shape=(20,), dtype=<type 'numpy.float32'>)
 Parameter model1_dense1_weight (shape=(20, 0), dtype=<type 'numpy.float32'>)
 Parameter model1_dense1_bias (shape=(20,), dtype=<type 'numpy.float32'>)
 Parameter model1_mydense_weight (shape=(20, 0), 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_paramssave/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程序設計有所幫助。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI