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
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])
# 参数访问
# 嵌套神经网络,参数获取
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)
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)
)

初始化参数

# 内置初始化函数
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]
(tensor([1., 1., 1., 1.]), tensor(0.))
# 某些层定制化初始化
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)
tensor([-0.1978,  0.5860, -0.2494, -0.5379])
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)
        # *元素相乘。注意广播机制
        # 保留weight绝对值大于等于5的元素值
        m.weight.data*=m.weight.data.abs()>=5

net.apply(my_init)
net[2].weight[:2]
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=)
# 直接操作神经网络层参数值
net[0].weight.data[:]+=1
net[0].weight.data[0,0]=42
net[0].weight.data[0]
tensor([42.0000,  1.0000,  1.0000, -6.7708])

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

# 某些层共享权重
# 构建了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])
tensor([True, True, True, True, True, True, True, True])
tensor([True, True, True, True, True, True, True, True])

你可能感兴趣的:(深度学习,深度学习,python,神经网络)