深度学习模型中的权重初始化对模型的训练效果有很大的影响,对预训练模型的研究就是为了在大模型上先训练出较好的权重,然后再放到不同的小任务上微调。
对于不加载预训练的模型,仍然可以通过定义模型权重初始化的方式来使得模型获得较好的效果,以下介绍不同的权重初始化方法、适用场景及效果。
对于线性
nonlinearity | gain |
---|---|
Linear / Identity | 1 1 1 |
Conv{1,2,3}D | 1 1 1 |
Sigmoid | 1 1 1 |
Tanh | 5 3 \frac{5}{3} 35 |
ReLU | 2 \sqrt{2} 2 |
Leaky Relu | 2 1 + negative_slope 2 \sqrt{\frac{2}{1 + \text{negative\_slope}^2}} 1+negative_slope22 |
SELU | 3 4 \frac{3}{4} 43 |
torch.nn.init.constant_(tensor, val)
按照常数val初始化tensor。
特别的,val为0和1分别有torch.nn.init.zeros_(tensor)
和torch.nn.init.ones_(tensor)
。
torch.nn.init.uniform_(tensor, a=0.0, b=1.0)
按照 U ( a , b ) U(a,b) U(a,b)的均匀分布初始化tensor。
torch.nn.init.normal_(tensor, mean=0.0, std=1.0)
按照 N ( m e a n , s t d 2 ) N(mean,std^2) N(mean,std2)的均匀分布初始化tensor。
torch.nn.init.xavier_uniform_(tensor, gain=1.0)
按照 U ( − a , a ) U(-a,a) U(−a,a)的均匀分布初始化tensor,其中
a = g a i n × 6 f a n _ i n + f a n _ o u t a = gain \times \sqrt{\frac{6}{fan\_in + fan\_out}} a=gain×fan_in+fan_out6
torch.nn.init.xavier_normal_(tensor, gain=1.0)
按照 N ( 0 , s t d 2 ) N(0,std^2) N(0,std2)的均匀分布初始化tensor,其中
s t d = g a i n × 2 f a n _ i n + f a n _ o u t std = gain \times \sqrt{\frac{2}{fan\_in + fan\_out}} std=gain×fan_in+fan_out2
torch.nn.init.kaiming_uniform_(tensor, a=0, mode='fan_in', nonlinearity='leaky_relu')
按照 U ( − a , a ) U(-a,a) U(−a,a)的均匀分布初始化tensor,其中
a = g a i n × 3 f a n _ m o d e a = gain \times \sqrt{\frac{3}{fan\_mode}} a=gain×fan_mode3
torch.nn.init.kaiming_normal_(tensor, a=0, mode='fan_in', nonlinearity='leaky_relu')
按照 N ( 0 , s t d 2 ) N(0,std^2) N(0,std2)的均匀分布初始化tensor,其中
s t d = g a i n f a n _ m o d e std = \sqrt{\frac{gain}{fan\_mode}} std=fan_modegain
在pytorch中的torch.nn.init
模块中有多种初始化的方法,可以显式地定义,以下是一个例子:
def init_weights(self):
for m in self.modules():
if isinstance(m, GCNConv):
m.weight.data = init.xavier_uniform(
m.weight.data, gain=torch.nn.init.calculate_gain("relu")
)
if m.bias is not None:
m.bias.data = init.constant(m.bias.data, 0.0)
这个函数是模型类的成员函数,它表示的是检索这个类中的所有模块,如果有GCNConv
类的话,就将对应的weights
用xavier均匀分布的方法初始化,如果有bias
的话用常数来初始化bias
,在对象初始化的时候调用self.init_weights();
就可以了。
1. How to use torch.nn.init.calculate_gain?
2. How to Initialize Weights in PyTorch
3. Weight Initialization Techniques in Neural Networks
4. 网络权重初始化方法总结(上):梯度消失、梯度爆炸与不良的初始化
5. 网络权重初始化方法总结(下):Lecun、Xavier与He Kaiming
6.pytorch-nn.init模块文档