《动手学深度学习》-学习笔记-4.2. 模型参数的访问、初始化和共享 search Search 快速搜索

《动手学深度学习》-学习笔记-4.2. 模型参数的访问、初始化和共享 search Search 快速搜索

课后练习1

问题:
查阅有关init模块的MXNet文档,了解不同的参数初始化方法。

解答:
http://mxnet.apache.org/api/python/optimization/optimization.html#module-mxnet.initializer
在这里有介绍 mxnet.initializer 的各种参数初始化方法。

课后练习2

问题:
尝试在net.initialize()后、net(X)前访问模型参数,观察模型参数的形状。

解答:
模型参数的形状有一个维度为 0。
因为不知道输入数据的维度,无法为参数开辟空间。延迟初始化。

课后练习3

问题:
构造一个含共享参数层的多层感知机并训练。在训练过程中,观察每一层的模型参数和梯度。

解答:
如果第一层 和 第三层 共享参数w,对w求导,类似于求全导数。
假设不共享的时候,第一层参数w1的导数为w1_grad,第二层参数w2的导数为w2_grad。
参数共享之后,w1和w2变为同一个自变量,这个自变量的导数为“w1_grad + w2_grad”。
编程验证方法:
建立两个网络,net1 和 net2.
net1 和 net2 的结构相同,参数初始值相同,loss相同,输入的x相同。
唯一不同的是:
(1)net1 每一层参数都是独立的。
第一层参数为w1,第三层参数为w3。w1 和 w3 数值相等,但是分别占用不同的存储空间。
(2)net2的 第一层 和 第三层 共享参数。
第一层参数 和 第三层参数 都是为w。并且设置 w = w1 = w3。
对两个网络定义相同的loss,然后采用相同的输入x,进行 前向传播 和 后向传播。
然后查看各个参数的grad。
预期结果:w.grad == w1.grad +w2.grad。
下面这段程序打印的结果验证了上述猜测是正确的。

from mxnet import autograd, nd
from mxnet.gluon import loss as gloss

# 生成测试数据
X = nd.random.uniform(shape=(2, 20))
y = nd.random.uniform(shape=(2, 10))

# 创建共享参数的网络
# 第二隐藏层(shared变量)和第三隐藏层共享模型参数
net_shared = nn.Sequential()
shared = nn.Dense(8, activation='relu')
net_shared.add(nn.Dense(8, activation='relu'),
               shared,
               nn.Dense(8, activation='relu', params=shared.params),
               nn.Dense(10))

# 创建普与参数共享网络结构相同的普通网络
net_woShared = nn.Sequential()
net_woShared.add(nn.Dense(8, activation='relu'),
                 nn.Dense(8, activation='relu'),
                 nn.Dense(8, activation='relu'),
                 nn.Dense(10))

# 初始化网络,并进行前向传播
net_shared.initialize()
y_shared_hat = net_shared(X)

net_woShared.initialize()
y_woShared_hat = net_woShared(X)

# 两个网络参数不同,所以前向传播的结果不相同。
print('y_woShared_hat == y_shared_hat')
print(y_woShared_hat == y_shared_hat)


# 修改普通网络的参数,使其与 共享参数网络 中的参数相同。
net_woShared[0].weight.set_data(net_shared[0].weight.data())
net_woShared[0].bias.set_data(net_shared[0].bias.data())
net_woShared[1].weight.set_data(net_shared[1].weight.data())
net_woShared[1].bias.set_data(net_shared[1].bias.data())
net_woShared[2].weight.set_data(net_shared[2].weight.data())
net_woShared[2].bias.set_data(net_shared[2].bias.data())
net_woShared[3].weight.set_data(net_shared[3].weight.data())
net_woShared[3].bias.set_data(net_shared[3].bias.data())

# 修改参数之后,再一次前向传播
y_woShared_hat = net_woShared(X)

# 两个网络的参数相同,所以前向传播的结果相同。
y_woShared_hat == y_shared_hat
print('y_woShared_hat == y_shared_hat')
print(y_woShared_hat == y_shared_hat)


# 定义损失函数
loss = gloss.L2Loss()

# 先进行前向传播,然后后向传播计算梯度
with autograd.record():
    l = loss(net_woShared(X), y)
l.backward()

# 先进行前向传播,然后后向传播计算梯度
with autograd.record():
    l = loss(net_shared(X), y)
l.backward()

# 参数共享网络第二隐藏层的梯度 等于 非参数共享网络中 第二隐藏层和第三隐藏层的梯度 相加
net_shared[1].weight.grad() == net_woShared[1].weight.grad()  + net_woShared[2].weight.grad() 
print('net_shared[1].weight.grad() == net_woShared[1].weight.grad()  + net_woShared[2].weight.grad() ')
print(net_shared[1].weight.grad() == net_woShared[1].weight.grad()  + net_woShared[2].weight.grad() )

《动手学深度学习》-学习笔记-4.2. 模型参数的访问、初始化和共享 search Search 快速搜索_第1张图片

你可能感兴趣的:(《动手学深度学习》-学习笔记-4.2. 模型参数的访问、初始化和共享 search Search 快速搜索)