层归一化前置和梯度累计
层归一化前置和梯度累计是两个提升模型训练速度和收敛稳定性的训练技巧.
层归一化前置
BatchNormalization的出现无疑是广大AI调参侠的福音,将大家从繁琐的权重初始化、学习率调节中释放出来。它不仅能够大大加快收敛速度,还自带正则化功能,是Google 2015年提出的。
归一化层在计算机视觉领域常以BN层形式出现,在自然语言处理领域常以LN层的形式出现,两者的目的是一样的,都是使用Batch Size的样本的均值和方差近似整体样本的均值和方差,独立地规范每一个维度的输入数据。
- 对Batch Size非常敏感。BatchNormalization的一个重要出发点是保持每层输入的数据同分布。回想下开始那个独立同分布的假设。假如取的batch_size很小,那显然有些Mini-Batch的数据分布就很可能与整个数据集的分布不一致了,又出现了那个问题,数据分布不一致,这就等于说没起到同分布的作用了,或者说同分布得不充分。实验也证明,Batch Size取得大一点, 数据shuffle的好一点,BatchNormalization的效果就越好。
- 不能很方便地用于RNN。这其实是第一个问题的引申。我们再来看一下上图中的均值和方差的计算公式。对所有样本求均值。对于图片这类等长的输入来说,这很容易操作,在每个维度加加除除就可以了,因为维度总是一致的。而对于不等长的文本来说,RNN中的每个time step共享了同一组权重。在应用BatchNormalization时,这就要求对每个time step的Batch Size个输入计算一个均值和方差。那么问题就来了,假如有一个句子S非常长,那就意味着对S而言,总会有个time_step的Batch Size为1,均值方差没意义,这就导致了BatchNormalization在RNN上无用武之地了
LayerNormalization的主要变化在于:
- 不再对Mini-Batch中的N的样本在各个维度做归一化,而是针对同一层的所有神经元做归一化。归一化公式为:μ 1 = 1 H ∑ H 1 α i 1 \mu ^1 = \frac {1}{H} \sum _{H} ^{1}{\alpha _i ^1}μ1=H1∑H1αi1
σ 1 = 1 H ∑ H 1 ( α i 1 − μ i 1 ) \sigma ^1 = \sqrt{\frac {1} {H} { \sum _{H} ^{1} (\alpha _i ^1 - \mu _i ^1)}}σ1=H1∑H1(αi1−μi1)
其中,H指的是一层神经网络的神经元个数。我们再回想下BatchNormalization,其实它是在每个神经元上对batch_size个数据做归一化,每个神经元的均值和方差均不相同。而LayerNormalization则是对所有神经元做一个归一化,这就跟batch_size无关了。哪怕batch_size为1,这里的均值和方差只和神经元的个数有关系 - 测试的时候可以直接利用LN,所以训练时不用保存均值和方差,这节省了内存空间
- 梯度累积
- 近年,随着深度学习的发展,模型的参数量越来越多,收敛难度越来越大,而硬件能力的提升远不如参数量的提升快。在一定范围内,Batch Size越大,根据局部数据求得的梯度方向越接近全局的梯度优化方向,因此,为了让模型在训练过程中的梯度方向更稳定,采用一个较大的Batch Size 是非常有必要的。令人尴尬的是,现有的GPU加载一个深度模型后,剩余的显存无法容纳很多的训练数据,即硬件不支持较大的Batch Size。最直接的改善方法是使用分布式训练,通过增加硬件资源来变相增大Batch Size。而通过一个时间换空间的措施——将多个Batch训练数据的梯度进行累积,也能达到一个较大Batch Size的效果。
- ref:https://blog.csdn.net/weixin_42486623/article/details/118917786