在深度学习模型的训练中,权重的初始值极为重要。一个好的初始值,会使模型收敛速度提高,使模型准确率更精确, 本文介绍 Pytorch 的模型初始化 。
参考 深入浅出PyTorch ,系统补齐基础知识。
本节目录
- 常见的初始化函数
- 初始化函数的使用
torch.nn.init内容
通过访问torch.nn.init的官方文档链接 ,我们发现torch.nn.init
提供了以下初始化方法:
torch.nn.init.uniform_
(tensor, a=0.0, b=1.0)torch.nn.init.normal_
(tensor, mean=0.0, std=1.0)torch.nn.init.constant_
(tensor, val)torch.nn.init.ones_
(tensor)torch.nn.init.zeros_
(tensor)torch.nn.init.eye_
(tensor)torch.nn.init.dirac_
(tensor, groups=1)torch.nn.init.xavier_uniform_
(tensor, gain=1.0)torch.nn.init.xavier_normal_
(tensor, gain=1.0)torch.nn.init.kaiming_uniform_
(tensor, a=0, mode=‘fan__in’, nonlinearity=‘leaky_relu’) __torch.nn.init.kaiming_normal_
(tensor, a=0, mode=‘fan_in’, nonlinearity=‘leaky_relu’)torch.nn.init.orthogonal_
(tensor, gain=1)torch.nn.init.sparse_
(tensor, sparsity, std=0.01)torch.nn.init.calculate_gain
(nonlinearity, param=None) 关于计算增益如下表:
nonlinearity | gain |
---|---|
Linear/Identity | 1 |
Conv{1,2,3}D | 1 |
Sigmod | 1 |
Tanh | 5/3 |
ReLU | sqrt(2) |
Leaky Relu | sqrt(2/1 neg_slop^2) |
我们可以发现这些函数除了calculate_gain
,所有函数的后缀都带有下划线,意味着这些函数将会直接原地更改输入张量的值。
torch.nn.init使用
我们通常会根据实际模型来使用torch.nn.init
进行初始化,通常使用isinstance()
来进行判断模块(回顾3.4模型构建)属于什么类型。
12345678910 | import torchimport torch.nn as nnconv = nn.Conv2d(1,3,3)linear = nn.Linear(10,1)isinstance(conv,nn.Conv2d) # 判断conv是否是nn.Conv2d类型isinstance(linear,nn.Conv2d) # 判断linear是否是nn.Conv2d类型TrueFalse |
---|
对于不同的类型层,我们就可以设置不同的权值初始化的方法。
12345678910111213141516171819202122232425262728293031 | 查看随机初始化的conv参数conv.weight.data# 查看linear的参数linear.weight.datatensor([[[ 0.1174, 0.1071, 0.2977, -0.2634, -0.0583, -0.2465, 0.1726, -0.0452, -0.2354]], [[ 0.1382, 0.1853, -0.1515, 0.0561, 0.2798, -0.2488, -0.1288, 0.0031, 0.2826]], [[ 0.2655, 0.2566, -0.1276, 0.1905, -0.1308, 0.2933, 0.0557, -0.1880, 0.0669]]])tensor([-0.0089, 0.1186, 0.1213, -0.2569, 0.1381, 0.3125, 0.1118, -0.0063, -0.2330, 0.1956])# 对conv进行kaiming初始化torch.nn.init.kaiming_normal_(conv.weight.data)conv.weight.data# 对linear进行常数初始化torch.nn.init.constant_(linear.weight.data,0.3)linear.weight.datatensor([[[ 0.3249, -0.0500, 0.6703, -0.3561, 0.0946, 0.4380, -0.9426, 0.9116, 0.4374]], [[ 0.6727, 0.9885, 0.1635, 0.7218, -1.2841, -0.2970, -0.9128, -0.1134, -0.3846]], [[ 0.2018, 0.4668, -0.0937, -0.2701, -0.3073, 0.6686, -0.3269, -0.0094, 0.3246]]])tensor([0.3000, 0.3000, 0.3000, 0.3000, 0.3000, 0.3000, 0.3000, 0.3000, 0.3000,0.3000]) |
---|
初始化函数的封装
人们常常将各种初始化方法定义为一个initialize_weights()
的函数并在模型初始后进行使用。
123456789101112131415 | def initialize_weights(self): for m in self.modules(): # 判断是否属于Conv2d if isinstance(m, nn.Conv2d): torch.nn.init.xavier_normal_(m.weight.data) # 判断是否有偏置 if m.bias is not None: torch.nn.init.constant_(m.bias.data,0.3) elif isinstance(m, nn.Linear): torch.nn.init.normal_(m.weight.data, 0.1) if m.bias is not None: torch.nn.init.zeros_(m.bias.data) elif isinstance(m, nn.BatchNorm2d): m.weight.data.fill_(1) m.bias.data.zeros_() |
---|
这段代码流程是遍历当前模型的每一层,然后判断各层属于什么类型,然后根据不同类型层,设定不同的权值初始化方法。我们可以通过下面的例程进行一个简短的演示:
123456789101112131415161718192021222324252627282930313233343536373839404142 | 模型的定义class MLP(nn.Module): # 声明带有模型参数的层,这里声明了两个全连接层 def __init__(self, **kwargs): # 调用MLP父类Block的构造函数来进行必要的初始化。这样在构造实例时还可以指定其他函数 super(MLP, self).__init__(**kwargs) self.hidden = nn.Conv2d(1,1,3) self.act = nn.ReLU() self.output = nn.Linear(10,1) # 定义模型的前向计算,即如何根据输入x计算返回所需要的模型输出 def forward(self, x): o = self.act(self.hidden(x)) return self.output(o)mlp = MLP()print(list(mlp.parameters()))print("-------初始化-------")initialize_weights(mlp)print(list(mlp.parameters()))[Parameter containing:tensor([[[ 0.2103, -0.1679, 0.1757, -0.0647, -0.0136, -0.0410, 0.1371, -0.1738, -0.0850]]], requires_grad=True), Parameter containing:tensor(0.2507, requires_grad=True), Parameter containing:tensor([ 0.2790, -0.1247, 0.2762, 0.1149, -0.2121, -0.3022, -0.1859, 0.2983, -0.0757, -0.2868], requires_grad=True), Parameter containing:tensor(-0.0905, requires_grad=True)]"-------初始化-------"[Parameter containing: tensor([[[-0.3196, -0.0204, -0.5784, 0.2660, 0.2242, -0.4198, -0.0952, 0.6033, -0.8108]]], requires_grad=True), Parameter containing: tensor(0.3000, requires_grad=True), Parameter containing: tensor([ 0.7542, 0.5796, 2.2963, -0.1814, -0.9627, 1.9044, 0.4763, 1.2077, 0.8583, 1.9494], requires_grad=True), Parameter containing: tensor(0., requires_grad=True)] |
---|
参考资料
- https://datawhalechina.github.io/thorough-pytorch/第三章/3.5 模型初始化.html
文章链接: https://cloud.tencent.com/developer/article/2304595