往期汇总:
- PyTorch 折桂 1:张量的性质
- PyTorch 折桂 2:张量的运算 1
- PyTorch 折桂 3:张量的运算 2
- PyTorch 折桂 4:torch.autograph
- PyTorch 折桂 5:PyTorch 模块总览 & torch.utils.data
- PyTorch 折桂 6:torch.nn 总览 & torch.nn.Module
- PyTorch 折桂 7:nn.Linear & 常用激活函数
1. torch.nn.init 概述
因为神经网络的训练过程其实是寻找最优解的过程,所以神经元的初始值非常重要。如果初始值恰好在最优解附近,神经网络的训练会非常简单。而当神经网络的层数增加以后,一个突出的问题就是梯度消失和梯度爆炸。前者指的是由于梯度接近 0,导致神经元无法进行更新;后者指的是误差梯度在更新中累积得到一个非常大的梯度,这样的梯度会大幅度更新网络参数,进而导致网络不稳定[1]。
torch.nn.init
模块提供了合理初始化初始值的方法。它一共提供了四类初始化方法:
- Xavier 分布初始化;
- Kaiming 分布初始化;
- 均匀分布、正态分布、常数分布初始化;
- 其它初始化。
有梯度边界的激活函数如 sigmoid
、tanh
和 softmax
等被称为饱和函数,没有梯度边界的激活函数如 relu
被称为不饱和函数,它们对应的初始化方法不同。
2. 梯度消失和梯度爆炸
假设我们有一个 3 层的全连接网络:对倒数第二层神经元的权重进行反向传播的公式为:
而 ,所以
即 ,即上一层的神经元的输出值,决定了 的大小。如果 太大或太小,即梯度消失或梯度爆炸,将导致神经网络无法训练。对于 sigmoid
和 tanh
等梯度绝对值小于 1 的激活函数来说,神经元的值会越来越小;对于其它情况,假设我们构建了一个 100 层的全连接网络:
class MLP(nn.Module):
def __init__(self, neural_num, layers):
super(MLP, self).__init__()
self.linears = nn.ModuleList([nn.Linear(neural_num, neural_num, bias=False) for _ in range(layers)])