参数初始化
一、前言
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])
浙公网安备 33010602011771号