参数初始化
一、前言
1、深度学习框架提供默认随机初始化
2、深度学习框架提供了最常用的规则,也允许创建自定义初始化方法
3、默认情况下,Pytorch会根据一个范围均匀地初始化权重和偏置矩阵,这个范围是根据输入和输出维度计算出来的
二、内置初始化
1、下面代码将所有权重参数初始化为标准差为0.01的正态分布,且将偏置参数设置为0
# 内置的初始化器 # m就是一个module def init_normal(m): if type(m) == nn.Linear: # 给权重赋值-将所有权重参数初始化为标准差为0.01的正态分布 nn.init.normal_(m.weight, mean=0, std=0.01) # 给偏置赋值-将偏置设为0 nn.init.zeros_(m.bias) # 将net里面所以层遍历一遍 net.apply(init_normal) net[0].weight.data[0], net[0].bias.data[0] # 输出结果 (tensor([-0.0210, -0.0141, -0.0058, 0.0037]), tensor(0.))
2、将所有参数初始化为给定的常数
# 将参数初始化为给定的常数 def init_constant(m): if type(m) == nn.Linear: ''' torch.nn.init.constant_(tensor, val)[source] 用值val填充向量tensor ''' nn.init.constant_(m.weight, 1) nn.init.zeros_(m.bias) net.apply(init_constant) net[0].weight.data[0], net[0].bias.data[0] #输出结果 (tensor([1., 1., 1., 1.]), tensor(0.))
3、对不同的块应用不同的初始化方法
# 对不同的块用不同的初始化方法 def xavier(m): if type(m) == nn.Linear: # 均匀分布 nn.init.xavier_uniform_(m.weight) def init_42(m): if type(m) == nn.Linear: # 常数赋值 nn.init.constant_(m.weight, 42) net[0].apply(xavier) net[2].apply(init_42) print(net[0].weight.data[0]) print(net[2].weight.data) #输出结果 tensor([ 0.1352, -0.2794, 0.1592, 0.3462]) tensor([[42., 42., 42., 42., 42., 42., 42., 42.]])
三、自定义初始化
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.abs() >= 5 net.apply(my_init) net[0].weight[:2] #输出结果 Init weight torch.Size([8, 4]) Init weight torch.Size([1, 8]) tensor([[ 0.0000, 5.1760, 0.0000, -7.1530], [ 0.0000, 0.0000, 0.0000, -0.0000]], grad_fn=<SliceBackward>)
我们可以直接设置参数,先直接定位到参数再给其赋值
net[0].weight.data[:] += 1 net[0].weight.data[0, 0] = 42 net[0].weight.data[0] #输出结果 tensor([42.0000, 6.1760, 1.0000, -6.1530])
四、参数绑定
1、在多个层间共享参数。我们可以定义一个稠密层,然后使用他的参数来设置另一个层的参数
2、列子表明,第二层和第三层是绑定的。他们不仅值相等,而且由相同的张量表示。因此,如果改变其中一个参数,另一个参数也会相应改变
# 在多个层间共享参数 # 我们需要给共享层一个名称,以便可以引用它的参数。 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]中的值,net[4]也会改变。说明使用的其实是一个对象 net[2].weight.data[0, 0] = 100 print(net[2].weight.data[0,0]) print(net[4].weight.data[0,0]) # 确保它们实际上是同一个对象,而不只是有相同的值。 print(net[2].weight.data[0] == net[4].weight.data[0]) # 输出结果 tensor([True, True, True, True, True, True, True, True]) tensor(100.) tensor(100.) tensor([True, True, True, True, True, True, True, True])