Pytorch模型参数的访问、初始化和共享

首先定义一个含单隐藏层的多层感知机,使用默认方法初始化它的参数,并做一次前向运算。

import torch
from torch import nn
from torch.nn import init

net=nn.Sequential(nn.Linear(4,3),nn.ReLU(),nn.Linear(3,1))
#此时Pytorch会进行默认初始化

print(net)
X=torch.rand(2,4)
Y=net(X).sum()

输出:

Sequential(
  (0): Linear(in_features=4, out_features=3, bias=True)
  (1): ReLU()
  (2): Linear(in_features=3, out_features=1, bias=True)
)

一、访问模型参数

对于Sequential示例中含模型参数的层,我们可以通过Module类的parameters()或者named_parameters()方法来访问所有参数(以迭代器的形式返回),后者除了返回参数Tensor外还会返回其名字。下面的代码访问上面net的所有参数:

for name,param in net.named_parameters():
	print(name,param.size())

输出:

0.weight torch.Size([3, 4])
0.bias torch.Size([3])
2.weight torch.Size([1, 3])
2.bias torch.Size([1])

可见返回的名字自动加上了层数的索引作为前缀。

接下来访问net中单层的参数。对于使用Sequential类构造的神经网络,我们可以通过方括号[]来访问网络的任一层。

for name,param in net[0].named_parameters():
	print(name,param.size(),type(param))

输出:

weight torch.Size([3, 4])
bias torch.Size([3])

因为这里是单维的因此没有层数索引的前缀。另外返回的param的类型为torch.nn.parameter.Parameter,其实这是Tensor的子类,和Tensor不同的是如果一个Tensor是Parameter,那么它会自动被添加到模型的参数列表里面。

因为Parameter是Tensor,即Tensor拥有的属性它都有,因此我们可以用data来访问参数值,用grad来访问参数梯度。

weight_0=list(net[0].parameters())[0]
print(weight_0.data)
#在没有反向传播前梯度为None
print(weight_0.grad)
Y.backward()
print(weight_0.grad)

输出:

tensor([[ 0.0285,  0.4555,  0.3370,  0.2170],
        [ 0.2281,  0.0616, -0.4615, -0.1053],
        [-0.2828, -0.4555, -0.4292,  0.4989]])
None
tensor([[0.1976, 0.3890, 0.3261, 0.5621],
        [0.0000, 0.0000, 0.0000, 0.0000],
        [0.0000, 0.0000, 0.0000, 0.0000]])

二、初始化模型参数

Pytorch中nn.Moudule中的模块参数都采取了较为合理的初始化策略(不同类型的layer具体采用的哪一种初始化方法可参考源代码)。但我们经常需要使用其他方法来初始化权重。Pytorch的init模块里提供了多种预设的初始化方法。

在下面的例子中,我们将权重初始化为均值为0、标准差为0.01的正态分布随机数,并将偏差参数清零。

for name,param in net.named_parameters():
	if 'weight' in name:
		torch.nn.init.normal_(param,mean=0,std=0.01)
		print(name,param.data)

输出:

0.weight tensor([[ 0.0098,  0.0141, -0.0097,  0.0053],
        [ 0.0224, -0.0045,  0.0074,  0.0173],
        [-0.0044,  0.0200,  0.0056, -0.0107]])
2.weight tensor([[ 0.0119, -0.0109, -0.0076]])

我们还可以使用常数来初始化权重参数:

#替换上面的初始化函数
torch.nn.init.constant_(param,val=0)

如果只想对某个特定参数进行初始化,我们可以调用Parameter类的initialize函数,它与Block类提供的initialize函数的使用方法一致。

三、自定义初始化方法

有时候我们需要的初始化方法并没有在init模块中提供。这时,可以实现一个初始化方法,从而能够像使用其他初始化方法那样使用它。

首先我们观察下Pytorch官方的初始化方法是如何实现的,以torch.nn.init.normal_为例

def normal_(tensor
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值