参数访问

目标参数:训练过程中需要优化的参数

几种访问方法

# 打印第3层的偏置
# tensor([0.0887], requires_grad=True)
# tensor([0.0887])
print(net[2].bias,net[2].bias.data)
 
# 打印第1层的参数名称和形状
# ('weight', torch.Size([8, 4])) ('bias', torch.Size([8]))
print(*[(name, param.shape) for name, param in net[0].named_parameters()])
 
# 通过名称打印参数
# tensor([0.0887])
print(net.state_dict()['2.bias'].data)
 
# 在分层嵌套中,可以用索引获取,第一大块的第2子块的第1层的偏置
# tensor([ 0.0887])
print(net[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)

自定义参数

均匀分布初始化后,绝对值小于5的设为零,常用于权重裁剪

def my_init(m):
    if type(m) == nn.Linear:
        nn.init.uniform_(m.weight, -10, 10)
        m.weight.data *= m.weight.data.abs() >= 5
net.apply(my_init)
 
# 直接设置参数
net[0].weight.data[:] += 1
net[0].weight.data[0, 0] = 42

参数绑定

在多个层之间共享参数

# 为共享参数的层定义名字
share = nn.Linear(64,32)
net = Sequential(nn.Linear(20,64),nn.ReLU(),
				 share,nn.ReLU(),
				 share,nn.ReLU(),
				 nn.Linear(32,10)
				)
# 当修改共享层的参数时,其他层的参数也会跟着改变
net[2].weight.data[0,0] = 100
 
print(net[2].weight.data==net[4].weight.data) # True

由于模型参数包含梯度信息,反向传播时,共享层的最终梯度是两个共享层的梯度之和,此时梯度下降步幅更大,收敛更快,必要时可以frozen任何一层的grad