东莞高埗网站建设,广东计算机网页制作,足球比赛统计数据,管理网站怎么做模型参数的初始化与访问操作
学习 如何初始化以及访问模型参数#xff0c;以及如何在多层之间共享模型参数 首先定义一个含有单个隐藏层的多层感知机#xff0c;使用默认方式初始化该模型的参数#xff0c;并且进行一次前向计算#xff1a;
import torch
from torch impo…模型参数的初始化与访问操作
学习 如何初始化以及访问模型参数以及如何在多层之间共享模型参数 首先定义一个含有单个隐藏层的多层感知机使用默认方式初始化该模型的参数并且进行一次前向计算
import torch
from torch import nn
from torch.nn import initnet 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_features4, out_features3, biasTrue)(1): ReLU()(2): Linear(in_features3, out_features1, biasTrue)
)接着尝试访问模型参数 由于Sequentail类与Module类的继承关系可以通过Module类的parameters()函数或者named_parameters()来访问所有的参数
print(type(net.named_parameters()))
for name, param in net.named_parameters():print(name, param.size())输出 named_parameters()返回参数的名称以及其该参数值tensor变量
class generator
0.weight torch.Size([3, 4])
0.bias torch.Size([3])
2.weight torch.Size([1, 3])
2.bias torch.Size([1])其中“0“、”2“为层数索引我们可以通过下面的方法访问网络的任意一层
for name, param in net[0].named_parameters():print(name, param.size(), type(param))输出结果
weight torch.Size([3, 4]) class torch.nn.parameter.Parameter
bias torch.Size([3]) class torch.nn.parameter.Parameter由于我们采用了下标索引访问网络的某一层所以结果中没有了层数索引返回的参数类型为“torch.nn.parameter.Parameter”这是Tensor的子类需要注意的是如果一个Tensor是Parameter他就会自动被添加到模型的参数列表中。 我们可以用下面的例子来理解
class MyModel(nn.Module):def __init__(self, **kwargs):super(MyModel, self).__init__(**kwargs)self.weight1 nn.Parameter(torch.rand(20, 20))self.weight2 torch.rand(20, 20)def forward(self, x):passn MyModel()
for name, param in n.named_parameters():print(name)输出
weight1发现只输出了参数weight1但是没有输出参数weight2这说明参数weight1在参数列表中而参数weight2不在参数列表中
初始化模型参数
将权重参数初始化成均值为0、标准差为0.01的正态分布随机数并依然将偏差参数清零
for name, param in net.named_parameters():if weight in name:init.normal_(param, mean0, std0.01)print(name, param.data)for name, param in net.named_parameters():if bias in name:init.constant_(param, val0)print(name, param.data)我们查看torch.nn.init.normal_函数观察torch默认初始化的方式
def normal_(tensor, mean0, std1):with torch.no_grad():return tensor.normal_(mean, std)这里使用一个inplace改变Tensor的值这个过程不记录梯度 根据相同的实现方式我们来实现一个自定义的初始化方法。在下面的例子里我们令权重有一半概率初始化为0有另一半概率初始化为[−10,−5][-10,-5][−10,−5]和[5,10][5,10][5,10]两个区间里均匀分布的随机数。
def init_weight_(tensor):with torch.no_grad():tensor.uniform_(-10, 10)tensor * (tensor.abs() 5).float()for name, param in net.named_parameters():if weight in name:init_weight_(param)我们还可以使用在之前的blog中提到的改变Parameter的data属性来改写模型参数的同时不改变参数的梯度
for name, param in net.named_parameters():if bias in name:param.data 1print(name, param.data)这里通过param.data改变模型参数但是不会影响param的梯度。
共享模型的参数
如何实现在多层之间共享模型的参数 1对Sequential中传入同一个Module实例这两个层的参数是共享的
linear nn.Linear(1, 1, biasFalse)
net nn.Sequential(linear, linear)
print(net)
for name, param in net.named_parameters():init.constant_(param, val3)print(name, param.data)输出
Sequential((0): Linear(in_features1, out_features1, biasFalse)(1): Linear(in_features1, out_features1, biasFalse)
)
0.weight tensor([[3.]])根据输出结果可以发现网络有两层但是weight参数只有一个这时候这两个层共享参数。
因为模型参数包含了梯度所以在反向传播计算时这些共享参数的梯度是累加的
x torch.ones(1, 1)
y net(x).sum()
print(y)
y.backward()
print(net[0].weight.grad) # 单次梯度是3两次所以就是6weight的值在上面输出了是3输出
tensor(9., grad_fnSumBackward0)
tensor([[6.]])