《动手学深度学习》mxnet版/第四章学习笔记
第四章
概括深度学习计算的各个重要组成部分,如模型构造、参数的访问和初始化等,自定义层,读取、存储和 使用GPU
- 模型构造
- 模型参数的访问、初始化和共享
- 读写Gluon模型的参数
模型构造
Block类是nn模块里提供的一个模型构造类,可以继承它来定义我们想要的模型。
#这里定义的MLP类重载了Block类的__init__函 数和forward函数。它们分别用于创建模型参数和定义前向计算
from mxnet import nd
from mxnet.gluon import nn
class MLP(nn.Block):
# 声明带有模型参数的层,这里声明了两个全连接层
def __init__(self, **kwargs):
# 调用MLP父类Block的构造函数来进行必要的初始化。这样在构造实例时还可以指定其他函数
# 参数,如“模型参数的访问、初始化和共享”一节将介绍的模型参数
super(MLP, self).__init__(**kwargs)
self.hidden = nn.Dense(256, activation='relu')# 隐藏层
self.output = nn.Dense(10) # 输出层
# 定义模型的前向计算,即如何根据输入x计算返回所需要的模型输出
def forward(self, x):
return self.output(self.hidden(x))
#实现一个与Sequential类有相同功能的MySequential类
class MySequential(nn.Block):
def __init__(self, **kwargs):
super(MySequential, self).__init__(**kwargs)
def add(self, block):
# block是一个Block子类实例,假设它有一个独一无二的名字。我们将它保存在Block类的
# 成员变量_children里,其类型是OrderedDict。当MySequential实例调用
# initialize函数时,系统会自动对_children里所有成员初始化
self._children[block.name] = block def forward(self, x):
# OrderedDict保证会按照成员添加时的顺序遍历成员
for block in self._children.values():
x = block(x)
return x
# 使用起来与Sequential差不多
net = MySequential()
net.add(nn.Dense(256, activation='relu'))
net.add(nn.Dense(10))
net.initialize()
net(X)
模型参数的访问、初始化和共享
在有些情况下,我们希望在多个层之间共享模型参数
#让模型的第二隐藏层(shared变量)和第三隐藏层共享模型参数
net = nn.Sequential()
shared = nn.Dense(8, activation='relu')
net.add(nn.Dense(8, activation='relu'), shared,
nn.Dense(8, activation='relu', params=shared.params),
nn.Dense(10))
net.initialize()
#在构造第三隐藏层时通过params来指定它使用第二隐藏层的参数。因为模型参数里包含了 梯度, 所以在反向传播计算时, 第二隐藏层和第三隐藏层的梯度都会被累加在shared.params.grad()里
读写Gluon模型的参数
Gluon的Block类提供了save_parameters函数和load_parameters函数来读写模型参数。
class MLP(nn.Block):
def __init__(self, **kwargs):
super(MLP, self).__init__(**kwargs)
self.hidden = nn.Dense(256, activation='relu')
self.output = nn.Dense(10)
def forward(self, x):
return self.output(self.hidden(x))
net = MLP()
net.initialize()
X = nd.random.uniform(shape=(2, 20))
Y = net(X)
#把该模型的参数存成文件,文件名为mlp.params
filename = 'mlp.params' net.save_parameters(filename)
#再实例化一次定义好的多层感知机。与随机初始化模型参数不同,我们在这里直接 读取保存在文件里的参数
net2 = MLP()
net2.load_parameters(filename)
#因为这两个实例都有同样的模型参数,那么对同一个输入X的计算结果将会是一样的
Y2 = net2(X)
Y2 == Y