• 20李沐动手学深度学习v2/参数管理


    参数访问

    # 单隐藏层MLP,参数获取
    import torch
    from torch import nn
    
    net=nn.Sequential(nn.Linear(4,8),nn.ReLU(),nn.Linear(8,1))
    X=torch.rand(size=(2,4))
    net(X)
    
    # 访问指定层所有参数
    # net[2]拿到0,1,2。拿到nn.Linear(8,1)
    # nn.Sequential(nn.Linear(4,8),nn.ReLU(),nn.Linear(8,1))
    # state?权重从自动机角度来看就是状态机
    # OrderedDict?有weight和bias
    print(net[2].state_dict())
    
    # 访问指定层的指定参数
    # torch.nn.parameter.Parameter定义的是可以优化的参数
    print(type(net[2].bias))
    # 访问参数
    print(net[2].bias)
    # 访问参数的数据
    print(net[2].bias.data)
    
    # 访问参数的梯度
    # 还没有做反向传播,所以=None
    net[2].weight.grad==None
    
    print("============")
    # 访问神经网络中的所有参数
    # named_parameters含有name和parameter
    print(*[(name,param.shape) for name,param in net[0].named_parameters()])
    print(*[(name,param.shape) for name,param in net.named_parameters()])
    
    # 网络的所有参数的第3层的偏置的数据
    # !神经元+输出算作1层(神经元和突起),激活函数算作1层
    net.state_dict()['2.bias'].data
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    OrderedDict([('weight', tensor([[-0.1736,  0.0939,  0.1715, -0.2786,  0.0999,  0.1209,  0.1512, -0.1243]])), ('bias', tensor([-0.0326]))])
    
    Parameter containing:
    tensor([-0.0326], requires_grad=True)
    tensor([-0.0326])
    ============
    ('weight', torch.Size([8, 4])) ('bias', torch.Size([8]))
    ('0.weight', torch.Size([8, 4])) ('0.bias', torch.Size([8])) ('2.weight', torch.Size([1, 8])) ('2.bias', torch.Size([1]))
    
    
    
    
    
    tensor([-0.0326])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    # 参数访问
    # 嵌套神经网络,参数获取
    def block1():
        return nn.Sequential(nn.Linear(4,8),nn.ReLU(),nn.Linear(8,4),nn.ReLU())
    
    def block2():
        net=nn.Sequential()
        for i in range(4):
            # 嵌套4次block1, 给每个module1个名字
            net.add_module(f'block {i}',block1())
        return net
    # rgnet共有5层
    rgnet=nn.Sequential(block2(),nn.Linear(4,1))
    rgnet(X)
    # 通过print打印神经网络结构
    print(rgnet)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    Sequential(
      (0): Sequential(
        (block 0): Sequential(
          (0): Linear(in_features=4, out_features=8, bias=True)
          (1): ReLU()
          (2): Linear(in_features=8, out_features=4, bias=True)
          (3): ReLU()
        )
        (block 1): Sequential(
          (0): Linear(in_features=4, out_features=8, bias=True)
          (1): ReLU()
          (2): Linear(in_features=8, out_features=4, bias=True)
          (3): ReLU()
        )
        (block 2): Sequential(
          (0): Linear(in_features=4, out_features=8, bias=True)
          (1): ReLU()
          (2): Linear(in_features=8, out_features=4, bias=True)
          (3): ReLU()
        )
        (block 3): Sequential(
          (0): Linear(in_features=4, out_features=8, bias=True)
          (1): ReLU()
          (2): Linear(in_features=8, out_features=4, bias=True)
          (3): ReLU()
        )
      )
      (1): Linear(in_features=4, out_features=1, bias=True)
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    初始化参数

    # 内置初始化函数
    def init_normal(m):
        '''
        :param m nn.Module类型
        '''
        if type(m)==nn.Linear:
            # 正态分布
            # !替换函数,normal_后下划线的写法表示这个函数是替换函数,替换m.weight
            # !所有替换函数都在initModule里面
            nn.init.normal_(m.weight,mean=0,std=0.01)
            nn.init.zeros_(m.bias)
    
    # net中所有的层都应用这个初始化函数
    net.apply(init_normal)        
    net[0].weight.data[0],net[0].bias.data[0]
    
    # 内置初始化函数
    def init_constant(m):
        '''
        :param m nn.Module类型
        '''
        if type(m)==nn.Linear:
            # 正态分布
            # !替换函数,normal_后下划线的写法表示这个函数是替换函数,替换m.weight
            # !所有替换函数都在initModule里面
            nn.init.constant_(m.weight,1)
            nn.init.zeros_(m.bias)
    
    # net中所有的层都应用这个初始化函数
    net.apply(init_constant)        
    net[0].weight.data[0],net[0].bias.data[0]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    (tensor([1., 1., 1., 1.]), tensor(0.))
    
    • 1
    # 某些层定制化初始化
    def xavier(m):
        '''
        xavier权重初始化方法
        xavier可以保证数值稳定性,进而防止梯度消失或爆炸
        Xavier是常用的权重初始化方法,它表示权重和梯度期望=0,权重和梯度的方差由第t层输入和输出的神经元数量决定
        '''
        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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    tensor([-0.1978,  0.5860, -0.2494, -0.5379])
    tensor([[42., 42., 42., 42., 42., 42., 42., 42.]])
    
    • 1
    • 2
    # 自定义初始化
    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)
            # *元素相乘。注意广播机制
            # 保留weight绝对值大于等于5的元素值
            m.weight.data*=m.weight.data.abs()>=5
    
    net.apply(my_init)
    net[2].weight[:2]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    Init weight torch.Size([8, 4])
    Init weight torch.Size([1, 8])
    
    
    
    
    
    tensor([[-0.0000, -9.1786, -0.0000, -6.5656, -7.9464,  9.2016,  0.0000, -0.0000]],
           grad_fn=)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    # 直接操作神经网络层参数值
    net[0].weight.data[:]+=1
    net[0].weight.data[0,0]=42
    net[0].weight.data[0]
    
    • 1
    • 2
    • 3
    • 4
    tensor([42.0000,  1.0000,  1.0000, -6.7708])
    
    • 1

    参数绑定,某些层共享权重

    # 某些层共享权重
    # 构建了shared层
    shared=nn.Linear(8,8)
    # net[2]和net[4]都是shared层
    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].weight.data[0,0]=100
    print(net[2].weight.data[0]==net[4].weight.data[0])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    tensor([True, True, True, True, True, True, True, True])
    tensor([True, True, True, True, True, True, True, True])
    
    • 1
    • 2
  • 相关阅读:
    【Redis】基础数据结构-skiplist跳跃表
    boost-asio-1-定时器使用
    redis进阶:集群模式原理及搭建
    Windows和Mac命令窗快速打开文件夹
    Java EE企业级开发学习 -- day1
    日常学习收获之----react的ref和wrappedComponentRef的区别
    Android11系统桌面隐藏指定APP图标
    子2023
    【重温基础算法】内部排序之计数排序法
    Linux入门教程:P15->软件包管理
  • 原文地址:https://blog.csdn.net/baidu_35805755/article/details/126800670