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) | 使用正交矩阵填充张量 |
下面我们用具体的示例介绍如何使用这些初始化方法,并对模型参数进行初始化。
二、参数初始化方法应用实例:
在本节我们介绍两种参数初始化的方法:第一种是针对某一层的权重进行初始化,第二种是针对一个网络的权重进行初始化。
首先导入需要使用的模块和库,代码如下:
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方法初始化,得到如下的直方图,说明生成的初始化数据符合正态分布。
在上面的代码中,我们初始化了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)
)
更多推荐
所有评论(0)