参数初始化

一、前言

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])

  

 

posted @ 2021-08-02 15:53  小秦同学在上学  阅读(631)  评论(0编辑  收藏  举报