pytorch入门|pytorch学习笔记——3.5Pytorch中网络参数的初始化方法

摘要:
对于搭建的网络,一般情况下我们使用默认的参数初始化就可以获得比较稳定的结果,但我们如果了解常用的参数初始化方法并加以使用,在某些情况下可以提高模型的精度。
一、常用的参数初始化方法: 下面我们列出nn模块中的init模块下常用的参数初始化类,功能如下:

常用的参数初始化方法的功能
方法(类) 功能
torch.nn.init.uniform_(tensor, a=0, b=1) 从均匀分布U(a, b)中采样,填充输入的张量或变量
torch.nn.init.normal_(tensor, mean=0.0, std=1.0)  从给定的均值和标准差的正态分布 中生成值,初始化张量
torch.nn.init.constant_(tensor, val) 用常数 val 的值填充输入的张量或变量
 torch.nn.init.eye_(tensor) 将二维张量初始化为单位矩阵
torch.nn.init.xavier_normal_(tensor, gain=1.0) 使用Glorot 初始化方法正态分布生成值,生成随机数填充张量
torch.nn.init,dirac(tensor) 使用Dirac data函数来填充{3,4,5}维输入张量或变量,在卷积层尽可能多的保存输入通道特性
torch.nn.init.xavier_uniform_(tensor, gain=1.0) 使用Glorat初始化方法均匀分布生成值,生成随机数填充张量
torch.nn.init.kaiming_uniform_(tensor, a=0, mode='fan_in', nonlinearity='leaky_relu') 使用HE初始化方法均匀分布生成值,生成随机数填充张量
torch.nn.init.kaiming_normal_(tensor, a=0, mode='fan_in', nonlinearity='leaky_relu') 使用HE初始化方法正态分布生成值,生成随机数填充张量
torch.nn.init.orthogonal_(tensor, gain=1) 使用正交矩阵填充张量
【pytorch入门|pytorch学习笔记——3.5Pytorch中网络参数的初始化方法】下面我们用具体的示例介绍如何使用这些初始化方法,并对模型参数进行初始化。
二、参数初始化方法应用实例: 在本节我们介绍两种参数初始化的方法:第一种是针对某一层的权重进行初始化,第二种是针对一个网络的权重进行初始化。
首先导入需要使用的模块和库,代码如下:
import torch import torch.nn as nn import matplotlib.pyplot as plt import os os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"

1.针对某一层的权重进行初始化
以一个卷积层为例,我们首先使用Conv2d()函数定义一个从3个特征映射到16个特征映射的卷积层,并且卷积核大小为3*3,然后使用标准正态分布的随机数进行初始化,代码如下:
#以一个卷积层为例,先定义一个从3个特征映射到16个特征映射的卷积层,(3*3卷积核)然后使用标准正态分布的随机数进行初始化#针对一个层进行权重初始化 conv1 = torch.nn.Conv2d(3,16,(3*3)) #使用标准正态分布初始化权重 torch.manual_seed(1)#随机数初始化种子 torch.nn.init.normal_(conv1.weight,mean=0,std=1)#表示生成的随机数用来替换蟑螂conv1.weight的原始数据#使用直方图可视化conv1.weight的分布情况 plt.figure(figsize=(8,6)) plt.hist(conv1.weight.data.numpy().reshape((-1,1)),bins=30) plt.show()

在上面的代码中,我们使用conv1.weight获得了conv1卷积层初始的权重参数,在使用torch.nn.init.normal_()函数时,第一个参数conv1.weight表示表示生成的随机数用来替换conv1.weight的原始数据,参数mean=0,std=1表示均值为0,标准差为1。
在将conv1.weight初始化后,我们将其中的权重参数分布使用plt方法初始化,得到如下的直方图,说明生成的初始化数据符合正态分布。
pytorch入门|pytorch学习笔记——3.5Pytorch中网络参数的初始化方法
文章图片

在上面的代码中,我们初始化了conv1的卷积核的权重,通过conv1.bias可以获取该层的偏置参数,代码如下:
conv1.bias#获取该层的偏置参数

结果如下,可见初始偏置参数:
Parameter containing: tensor([ 0.0597, -0.0097,0.0147,0.0448,0.0054,0.0041,0.0205, -0.0350, 0.0092,0.0280, -0.0312, -0.0527, -0.0417, -0.0563, -0.0028,0.0337], requires_grad=True)

下面我们通过torch.nn.init.constant()函数使用常量0.1来进行偏置的初始化,代码如下:
#使用指定const值初始化偏置torch.nn.init.constant_(conv1.bias,val=0.1)

结果如下,说明conv1偏置参数的每个元素都已经初始化为0.1:
Parameter containing: tensor([0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000], requires_grad=True)

2.针对一个网络的权重进行初始化
首先,我们定义一个简单的测试网络TestNet()网络类,代码如下:
#首先建立一个测试网络 class TestNet(nn.Module): def __init__(self): super(TestNet,self).__init__() self.conv1 = nn.Conv2d(3,16,3) self.hidden = nn.Sequential( nn.Linear(100,100), nn.ReLU(), nn.Linear(100,50), nn.ReLU(),) self.cla = nn.Linear(50,10) #定义网络的前向传播路径 def forward(self,x): x = self.conv1(x) x = x.view(x.shape[0],-1) x = self.hidden(x) output = self.cla(x) return output #输出网络结构 testnet = TestNet() print(testnet)

结果为(网络结构):
TestNet( (conv1): Conv2d(3, 16, kernel_size=(3, 3), stride=(1, 1)) (hidden): Sequential( (0): Linear(in_features=100, out_features=100, bias=True) (1): ReLU() (2): Linear(in_features=100, out_features=50, bias=True) (3): ReLU() ) (cla): Linear(in_features=50, out_features=10, bias=True) )

在上述定义的网络结构中,一共有4个包含参数的层,分别是1个卷积层和3个全连接层。
下面我们尝试对不同类型层的参数使用不同的方法进行参数初始化,方法是定义一个函数,对不同类型的层使用不同的初始化方法,下面我们就定义一个init_weights()函数来实现这个功能,代码如下:(若是卷积层,使用正态分布初始化;若是全连接层没使用均匀分布初始化)
#针对不同类型的层使用不同的初始化方法 def init_weights(m): #如果是卷积层 if type(m) == nn.Conv2d: torch.nn.init.normal_(m.weight,mean=0,std=0.5) #如果是全连接层 if type(m) == nn.Linear: torch.nn.init.uniform_(m.weight,a=-0.1,b=0.1) m.bias.data.fill_(0.01)

最后,我们在网络TestNet中,对定义好的函数使用apply方法即可,testnet的参数初始化代码如下:
#使用网络的apply方法进行权重初始化 torch.manual_seed(1) testnet.apply(init_weights)

结果为:
TestNet( (conv1): Conv2d(3, 16, kernel_size=(3, 3), stride=(1, 1)) (hidden): Sequential( (0): Linear(in_features=100, out_features=100, bias=True) (1): ReLU() (2): Linear(in_features=100, out_features=50, bias=True) (3): ReLU() ) (cla): Linear(in_features=50, out_features=10, bias=True) )




    推荐阅读