Python Gluon参数和模块命名操作教程
本文实例讲述了PythonGluon参数和模块命名操作。分享给大家供大家参考,具体如下:
Gluon参数和模块命名教程
在gluon里,每个参数和块都有一个名字(和前缀)。参数名可以由用户指定,block名也可以由用户指定,也可以自动创建。
本教程中,我们将讨论命名方面的最佳实践。首先,importMXNet和Gluon
from__future__importprint_function importmxnetasmx frommxnetimportgluon
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_( Parameterdense0_weight(shape=(100,0),dtype=) Parameterdense0_bias(shape=(100,),dtype= ) )
名称空间
为了管理嵌套block的名称,每个块附加有一个name_scope(名称空间)。在name_scope中创建的block都会在其名称前加上父block的名称。
我们将定义一个简单的神经网络来说明这点:
classModel(gluon.Block): def__init__(self,**kwargs): super(Model,self).__init__(**kwargs) withself.name_scope(): self.dense0=gluon.nn.Dense(20) self.dense1=gluon.nn.Dense(20) self.mydense=gluon.nn.Dense(20,prefix='mydense_') defforward(self,x): x=mx.nd.relu(self.dense0(x)) x=mx.nd.relu(self.dense1(x)) returnmx.nd.relu(self.mydense(x))
现在实例化这个神经网络
- 注意:model0.dense0的名称是model0_dense0_而非dense0_
- 注意:我们指定model.mydense的前缀为mydense_,它的父类前缀会自动生成并添加到前面变成model0_mydense_
这里的名称前缀和变量名model0没有关系,这里就算把model0换成其他变量名比如net,前缀还是model?,?表示这是一个递增的数字,这里的名称前缀和classModel有关若将类名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() withnet.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() withnet.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_( Parametermodel0_dense0_weight(shape=(20L,20L),dtype=) Parametermodel0_dense0_bias(shape=(20L,),dtype= ) Parametermodel0_dense1_weight(shape=(20L,20L),dtype= ) Parametermodel0_dense1_bias(shape=(20L,),dtype= ) Parametermodel0_mydense_weight(shape=(20L,20L),dtype= ) Parametermodel0_mydense_bias(shape=(20L,),dtype= ) ) model1_( Parametermodel1_dense0_weight(shape=(20,0),dtype= ) Parametermodel1_dense0_bias(shape=(20,),dtype= ) Parametermodel1_dense1_weight(shape=(20,0),dtype= ) Parametermodel1_dense1_bias(shape=(20,),dtype= ) Parametermodel1_mydense_weight(shape=(20,0),dtype= ) Parametermodel1_mydense_bias(shape=(20,),dtype= ) )
若你尝试将model0的参数载入到model1中,你将会得到一个名称不匹配的错误
model0.collect_params().save('model.params') try: model1.collect_params().load('model.params',mx.cpu()) exceptExceptionase: print(e)
Parameter'model1_dense0_weight'ismissinginfile'model.params',whichcontainsparameters:'model0_mydense_weight','model0_dense1_bias','model0_dense1_weight','model0_dense0_weight','model0_dense0_bias','model0_mydense_bias'.Pleasemakesuresourceandtargetnetworkshavethesameprefix.
为了解决这个问题,我们使用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。
Forexample,thealexnetinmodelzoohas1000outputdimensions,butmaybeyouonlyhave100classesinyourapplication.
例如,alexnet有1000个输出维度但你只有100类。
我们首先载入预训练的AlexNet
- 在GluonModelZoo,所有图像分类模型的格式都是特征提取层叫features,输出层叫output.
- 注意到输出层是一个denseblock,有1000个维度的输出
alexnet=gluon.model_zoo.vision.alexnet(pretrained=True) print(alexnet.output) print(alexnet.output.prefix) Dense(4096->1000,linear) alexnet0_dense2_
改变输出为100维,使用一个新block替换它
withalexnet.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程序设计有所帮助。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。