15参数管理
import torch
from torch import nn
net = nn.Sequential(nn.Linear(4,8), nn.ReLU(), nn.Linear(8,1))
X = torch.rand(2,4)
print(net(X))
"""
tensor([[-0.4613],
[-0.2691]], grad_fn=<AddmmBackward>)
"""
print(net[2].state_dict())
"""
OrderedDict([('weight', tensor([[-0.0274, -0.1189, 0.2617, -0.1651,
-0.2382, -0.2734, -0.0991, 0.1985]])), ('bias', tensor([-0.1222]))])
首先,这个全连接层包含两个参数,分别是该层的权重和偏置。
两者都存储为单精度浮点数float32。
注意: 参数名称允许唯一标识每个参数,即使在包含数百个层的网络中也是如此
"""
print(type(net[2].bias))
print(net[2].bias)
print(net[2].bias.data)
"""
<class 'torch.nn.parameter.Parameter'>
Parameter containing:
tensor([-0.1222], requires_grad=True)
tensor([-0.1222)
"""
print(net[2].weight.grad == None)
print(*[(name, param.shape) for name, param in net.named_parameters()])
print(*[(name, param.shape) for name, param in net[0].named_parameters()])
"""
('0.weight', torch.Size([8, 4])) ('0.bias', torch.Size([8])) ('2.weight', torch.Size([1, 8])) ('2.bias', torch.Size([1]))
('weight', torch.Size([8, 4])) ('bias', torch.Size([8]))
"""
print(net.state_dict()['2.bias'].data)
def block1():
return nn.Sequential(nn.Linear(4, 8), nn.ReLU(),
nn.Linear(8, 4), nn.ReLU())
def block2():
net = nn.Sequential()
for i in range(2):
net.add_module(f'block {i}', block1())
return net
rgnet = nn.Sequential(block2(), nn.Linear(4, 1))
print(rgnet)
"""
Sequential(
(0): Sequential(
(block 0): Sequential(
(0): Linear(in_features=4, out_features=8, bias=True)
(1): ReLU()
(2): Linear(in_features=8, out_features=4, bias=True)
(3): ReLU()
)
(block 1): Sequential(
(0): Linear(in_features=4, out_features=8, bias=True)
(1): ReLU()
(2): Linear(in_features=8, out_features=4, bias=True)
(3): ReLU()
)
)
(1): Linear(in_features=4, out_features=1, bias=True)
)
"""
print(rgnet[0][1][0].bias.data)
def init_normal(m):
if type(m) == nn.Linear:
nn.init.normal_(m.weight, mean=0, std=0.01)
nn.init.zeros_(m.bias)
net.apply(init_normal)
print(net[0].weight.data[0])
print(net[0].bias.data[0])
"""
tensor([-0.0055, 0.0028, -0.0095, -0.0059])
tensor(0.)
打印了模型net第一个全连接层的第一行权重和第一个偏置的值。
这里net[0]指的是net中的第一个子模块,也就是第一个全连接层nn.Linear(4, 8)。
通过.weight.data[0]访问权重的第一行,通过.bias.data[0]访问偏置的第一个元素。
"""
def my_init(m):
if type(m) == nn.Linear:
print("Init", *[(name, param.shape)
for name , param in m.named_parameters()][0])
nn.init.uniform_(m.weight, -10, 10)
m.weight.data = m.weight.data * ( m.weight.data.abs() >= 5)
net.apply(my_init)
print(net[0].weight[:2])
"""
tensor([[ 6.7495, -0.0000, 0.0000, 0.0000],
[-0.0000, -7.6540, -0.0000, 0.0000]], grad_fn=<SliceBackward>)
"""
net[0].weight.data[:] += 1
print(net[0].weight.data[:])
"""
tensor([[ 7.7495, 1.0000, 1.0000, 1.0000],
[ 1.0000, -6.6540, 1.0000, 1.0000],
[10.3503, 1.0000, 9.9864, 1.0000],
[ 6.7700, 1.0000, 8.1017, -4.6532],
[-4.0572, 1.0000, 1.0000, 1.0000],
[ 1.0000, 1.0000, 1.0000, 10.8596],
[ 1.0000, 10.9898, 7.0317, -4.4541],
[-5.0554, 1.0000, 1.0000, 1.0000]])
"""
net[0].weight.data[0, 0] = 42
print(net[0].weight.data[0])
shared = nn.Linear(8, 8)
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(),
shared, nn.ReLU(),
shared, nn.ReLU(),
nn.Linear(8, 1))
net(X)
print(net[2].weight.data[0] == net[4].weight.data[0])
net[2].weight.data[0, 0] = 100
print(net[2].weight.data[0] == net[4].weight.data[0])
"""
表明第三个和第五个神经网络层的参数是绑定的。 它们不仅值相等,而且由相同的张量表示。
因此,如果我们改变其中一个参数,另一个参数也会改变。
这里有一个问题:当参数绑定时,梯度会发生什么情况?
答案是由于模型参数包含梯度,因此在反向传播期间第二个隐藏层 (即第三个神经网络层)
和第三个隐藏层(即第五个神经网络层)的梯度会加在一起。
"""