参数访问
目标参数:训练过程中需要优化的参数
几种访问方法
# 打印第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