网络优化与正则化
1. 网络优化
1.1 网络结构多样性
1.2 高维变量的非凸优化
-
鞍点(Saddle Point)
-
局部最小值(Local Minima)
-
驻点(Stationary Point)
-
在高维空间中大部分驻点都是鞍点
-
-
平坦最小值(Flat Minima)
- 尖锐最小值(Sharp Minima)
-
局部最小解的等价性
1.3 神经网络优化的改善方法
2. 优化算法
2.1 小批量梯度下降
小批量梯度下降法(Mini-Batch Gradient Descent)
假设:
-
\(f(\boldsymbol{x}; \theta)\) 表示一个深度神经网络
-
\(\mathcal{L}(\cdot)\) 表示可微分的损失函数
-
\(\boldsymbol{\theta}\) 为网络参数
-
\(\alpha\) 为学习率(learning rate)
-
\(\mathcal{S}_t = \{ (\boldsymbol{x}^{k}, \boldsymbol{y}^{k}) \}_{k=1}^{K}\) 每一批次的训练样本集,
-
\(K\) 每一批次的样本个数,即批量大小(Batch Size)
-
第 \(t\) 次迭代(Iteration)时损失函数关于参数 \(\theta\) 的偏导数为:
- 第 \(t\) 次更新的梯度 \(\boldsymbol{g}_t\) 定义为:
使用梯度下降来更新参数
每次迭代时参数更新的差值 \(\Delta \boldsymbol{\theta}_t\) 定义为:
\(\Delta \boldsymbol{\theta}_t\) 和梯度 \(\boldsymbol{g}_{t}\) 并不需要完全一致:
-
\(\Delta \boldsymbol{\theta}_t\) 为每次迭代时参数的实际更新方向:\(\boldsymbol{\theta}_t = \boldsymbol{\theta}_{t-1} + \Delta \boldsymbol{\theta}_t\)
-
在标准的小批量梯度下降中:\(\Delta \boldsymbol{\theta}_t = - \alpha \, \boldsymbol{g}_t\)
影响小批量梯度下降法的主要因素有:
-
1)批量大小 \(K\)
-
2)学习率 \(\alpha\)
-
3)梯度估计
2.2 批量大小选择
批量大小(Batch Size)对网络优化的影响也非常大。
-
一般而言,批量大小不影响随机梯度的期望,但是会影响随机梯度的方差。
-
批量大小越大,随机梯度的方差越小,引入的噪声也越小,训练也越稳定,因此可
以设置较大的学习率。 -
而批量大小较小时,需要设置较小的学习率,否则模型会不收敛.
-
学习率通常要随着批量大小的增大而相应地增大
线性缩放规则(Linear Scaling Rule)(Goyal et al., 2017) :当批量大小增加 \(m\) 倍时,学习率也增加 \(m\) 倍。
- 线性缩放规则往往在批量大小比较小时适用,当批量大小非常大时,线性缩放会使得训练不稳定。
回合(Epoch)和迭代(Iteration)的关系
2.3 学习率调整
2.3.1 学习率衰减
过学习率衰减(Learning Rate Decay) 或学习率退火(Learning Rate Annealing)
- 学习率衰减是按每次迭代(Iteration)进行,也可以按每 𝑚 次迭代或每个回合(Epoch)进行。衰减率通常和总迭代次数相关。
假设:
-
\(\alpha_0\) 为初始(第 0 次迭代)的学习速率
-
\(\alpha_t\) 为第 \(t\) 次迭代的学习速率
-
\(\beta\) 为衰减率
-
\(T\) 为迭代总次数
分段常数衰减(Piecewise Constant Decay)也成为阶梯衰减(Step Decay):即每经过 \(T_1,T_2,\cdots,T_m\) 次迭代将学习率衰减为原来的 \(\beta_1,\beta_2,\cdots,\beta_m\) 倍,其中 \(T_m\) 和 \(\beta_m (\beta_m < 1)\) 为根据经验设置的超参数
逆时衰减(Inverse Time Decay)
指数衰减(Exponential Decay)
自然指数衰减(Natural Exponential Decay)
余弦衰减(Cosine Decay)
2.3.2 学习率预热
学习率预热(Learning Rate Warmup):为了提高训练稳定性,在最初几轮迭代时,采用比较小的学习率,等梯度下降到一定程度后再恢复到初始的学习率
是逐渐预热(Gradual Warmup)(Goyal et al.,2017):假设预热的迭代次数为 \(T'\),初始学习率为 \(\alpha_0\),在预热过程中,每次更新的学习率为
2.3.3 周期性学习率调整
周期性地增大学习率,可以使得梯度下降法能够逃离鞍点或尖锐最小值
-
当参数处于尖锐最小值附近时,增大学习率有助于逃离尖锐最小值
-
当参数处于平坦最小值附近时,增大学习率依然有可能在该平坦最小值的吸引域(Basin of Attraction)内
-
周期性地增大学习率虽然可能短期内损害优化过程,使得网络收敛的稳定性变差,但从长期来看有助于找到更好的局部最优解。
循环学习率(Cyclic Learning Rate)(Goyalet al., 2017):让学习率在一个区间内周期性地增大和缩小
- 三角循环学习率(Triangular Cyclic Learning Rate):以使用线性缩放来调整学习率
设:
-
每个循环周期的长度相等都为 \(2 \Delta T\),前 \(\Delta T\) 步为学习率线性增大阶段,后 \(\Delta T\) 步为学习率线性缩小阶段
-
\(m\) 表示循环周期数。在第 \(t\) 次迭代时,其所在的循环周期数 \(m\) 为:
\[m = \left\lfloor 1 + \frac{t}{2 \Delta T} \right\rfloor \]- 其中 \(\lfloor \cdot \rfloor\) 表示"向下取整"函数
-
\(\alpha_{\max}^m\) 和 \(\alpha_{\min}^m\) 分别为第 \(m\) 个周期中学习率的上界和下界,可以随着 \(m\) 的增大而逐渐降低
第 \(t\) 次迭代的学习率为:
- 其中 \(b \in [0, 1]\) 的计算为:
带热重启的随机梯度下降(Stochastic Gradient Descent with Warm Restarts, SGDR)(Loshchilov et al., 2017a)
-
学习率每间隔一定周期后重新初始化为某个预先设定值,然后逐渐衰减
-
每次重启后模型参数不是从头开始优化,而是从重启前的参数基础上继续优化
设:
-
\(M\) 为梯度下降过程中重启的次数
-
\(T_m\) 为重启周期
-
第 \(m\) 次重启在上次重启开始第 \(T_m\) 个回合(Epoch)后进行
-
\(T_m\) 可以随着重启次数逐渐增加,比如 \(T_m = T_m \times \kappa\),其中 \(\kappa \geq 1\) 为放大因子
-
-
\(T_{\text{cur}}\) 为从上次重启之后的回合(Epoch)数
- \(T_{\text{cur}}\) 可以取小数,如 0.1、0.2 等,这样可以在一个回合内部进行学习率衰减
-
\(\alpha_{\max}^m\) 和 \(\alpha_{\min}^m\) 同前
-
在第 \(m\) 次重启之前,采用余弦衰减来降低学习率.第 \(t\) 次迭代的学习率为
\[\alpha_{t} = \alpha_{\min }^{m} + \frac{1}{2} \left(\alpha_{\max }^{m}-\alpha_{\min }^{m} \right) \left[ 1 + \cos \left(\frac{T_{\text {cur }}}{T_{m}} \pi \right) \right] \]- 可以看出当 \(\alpha_{\max }^{m} = \alpha_0, \alpha_{\min }^{m} = 0\),则不会进行重启,退化为余弦衰减
2.3.4 AdaGrad 算法
在标准的梯度下降法中:
-
每个参数在每次迭代时都使用相同的学习率
-
由于每个参数的维度上收敛速度都不相同,因此根据不同参数的收敛情况分别设置学习率
AdaGrad算法(Adaptive Gradient Algorithm)(Duchi et al., 2011) 是借鉴 L2 正则化的思想,每次迭代时自适应地调整每个参数的学习率。
- 在第 \(t\) 次迭代时,先计算每个参数梯度平方的累计值\[\boldsymbol{G}_t = \sum_{\tau=1}^{t} \boldsymbol{g}_{\tau} \odot \boldsymbol{g}_{\tau} \]
- 其中 \(\odot\) 为按元素乘积(element-wise product),\(g_{\tau} \in \mathbb{R}^{|\theta|}\) 是第 \(\tau\) 次迭代时的梯度
AdaGrad 算法的参数更新差值为
-
其中 \(a\) 是初始的学习率
-
\(\epsilon\) 是为了保持数值稳定性而设置的非常小的常数,一般
取值 e−7 到 e−10. -
此外,这里的开平方、除、加运算都是按元素进行的操作.
在 AdaGrad 算法中:
-
如果某个参数的偏导数累积比较大,其学习率相对较小;
-
如果其偏导数累积较小,其学习率相对较大
-
但整体是随着迭代次数的增加,学习率逐渐缩小.
其缺点是:在经过一定次数的迭代依然没有找到最优点时,由于这时的学习率已经非常小,很难再继续找到最优点.
2.3.5 RMSprop 算法
RMSprop 算法 (Tieleman et al., 2012),可以在有些情况下避免 AdaGrad 算法中学习率不断单调下降以至于过早衰减的缺点
- 首先计算每次迭代梯度 \(\boldsymbol{g}_t\) 平方的指数衰减移动平均
-
RMSprop 算法的参数更新差值为
\[\Delta \boldsymbol{\theta}_{t}=-\frac{\alpha}{\sqrt{G_{t}+\epsilon}} \odot \boldsymbol{g}_{t} \]- 其中 \(\beta\) 为衰减率,一般取值为 0.9
在迭代过程中,每个参数的学习率并不是呈衰减趋势,既可以变小也可以变大
2.3.6 AdaDelta 算法
AdaDelta 算法(Zeiler, 2012)也是 AdaGrad 算法的一个改进。
-
通过梯度平方的指数衰减移动平均来调整学习率
-
还引入了每次参数更新差值 \(\Delta \theta\) 的平方的指数衰减权移动平均
第 \(t\) 次迭代时,参数更新差值 \(\Delta \theta\) 的平方的指数衰减权移动平均为
- 其中 \(\beta_1\) 为衰减率
AdaDelta 算法的参数更新差值为
- 其中,其中 \(\boldsymbol{G}_{t}\) 的计算方式和 RMSprop 算法一样
AdaDelta 算法将 RMSprop 算法中的初始学习率 \(\alpha\) 改为动态计算的 \(\sqrt{\Delta \boldsymbol{X}_{t-1}^2}\),在一定程度上平抑了学习率的波动。
2.4 梯度估计修正
梯度估计(Gradient Estimation)
-
在随机(小批量)梯度下降法中,如果每次选取样本数量比较小,损失会呈现振荡的方式下降
- 增加批量大小可以缓解梯度估计随机性
-
随机梯度下降方法中每次迭代的梯度估计和整个训练集上的最优梯度并不一致,具有一定的随机性
-
通过使用最近一段时间内的平均梯度来代替当前时刻的随机梯度来作为参数更新的方向,从而提高优化速度
2.4.1 动量法
动量(Momentum)
动量法(Momentum Method)是用之前积累动量来替代真正的梯度
- 每次迭代的梯度可以看作加速度.
在第 \(t\) 次迭代时,计算负梯度的"加权移动平均"作为参数的更新方向
- 其中:\(\rho\) 为动量因子,通常设为 \(0.9\),\(\alpha\) 为学习率
在动量法中,实际的参数更新方向 \(\Delta \boldsymbol{\theta}_t\) 为上一步的参数更新方向 \(\Delta \boldsymbol{\theta}_{t-1}\) 和当前梯度的反方向 \(-\boldsymbol{g}_t\) 的叠加。这样,\(\Delta \boldsymbol{\theta}_t\) 可以被拆分为两步进行:
-
先根据 \(\Delta \boldsymbol{\theta}_{t-1}\) 更新一次得到参数 \(\hat{\theta}\)
-
再用 \(-\boldsymbol{g}_t\) 进行更新:
- 其中,梯度 \(\boldsymbol{g}_{t}\) 为点 \(\boldsymbol{\theta}_{t-1}\) 上的梯度
2.4.2 Nesterov 加速梯度
Nesterov 加速梯度(Nesterov Accelerated Gradient,NAG)是一种对动量法的改进(Nesterov, 2013; Sutskever et al., 2013),也称为 Nesterov 动量法(Nesterov Momentum)
- 其中,\(g_{t}'\left(\theta_{t-1} +\rho \Delta \theta_{t-1}\right)\) 表示损失函数在点 \(\widehat{\boldsymbol{\theta}} = \boldsymbol{\theta}_{t-1} +\rho \, \Delta \boldsymbol{\theta}_{t}\) 上的偏导数
2.4.3 Adam 算法
Adam 算法(Adaptive Moment Estimation Algorithm)(Kingma et al., 2015) 可以看作动量法和 RMSprop 算法
的结合,不但使用动量作为参数更新方向,而且可以自适应调整学习率
Adam 算法:
- 一方面计算梯度平方 \(g_t^2\) 的指数加权平均(和 RMSprop 算法类似)
- 另一方面计算梯度 \(g_t\) 的指数加权平均(和动量法类似)
-
其中:\(\beta_1\) 和 \(\beta_2\) 分别为两个移动平均的衰减率,通常取值为 \(\beta_1 = 0.9, \beta_2 = 0.99\).
-
\(\boldsymbol{M}_{t}\) 和 \(\boldsymbol{G}_{t}\) 可以被看作梯度的均值(一阶矩)和未减去均值的方差(二阶矩)
假设 \(\boldsymbol{M}_{t} = \boldsymbol{0}, \boldsymbol{G}_{t} = \boldsymbol{0}\),那么在迭代初期 \(\boldsymbol{M}_{t}\) 和 \(\boldsymbol{G}_{t}\) 的值会比真实的均值和方差要小.特别是当 \(\beta_1\) 和 \(\beta_2\) 都接近于1 时,偏差会很大。因此,需要对偏差进行修正。
Adam 算法的参数更新差值为:
- 其中:\(\alpha\) 为学习率,通常设为 0.001;并且也可以进行衰减,如 \(\alpha_t = \alpha_0 / \sqrt{t}\).
Nadam 算法 (Dozat, 2016):在 Adam 算法中引入 Nesterov 加速梯度
2.4.4 梯度截断
梯度截断(Gradient Clipping)(Pascanu et al., 2013)
- 为了克服梯度爆炸的影响
按值截断:在第 \(t\) 次迭代时,梯度为 \(g_t\),给定一个区间 \([a, b]\),如果一个参数的梯度小于 \(a\) 时,就将其设为 \(a\);如果大于 \(b\) 时,就将其设为 \(b\)
按模截断 将梯度的模截断到一个给定的截断阈值 \(b\)
-
在训练循环神经网络时,按模截断是避免梯度爆炸问题的有效方法
-
截断阈值 \(b\) 是一个超参数,也可以根据一段时间内的平均梯度来自动调整
-
实验中发现,训练过程对阈值 \(b\) 并不十分敏感,通常一个小的阈值就可以得到很好的结果 (Pascanu et al., 2013)
2.5 优化算法小结
上文优化算法可以使用下面公式来统一描述概括:
-
其中:\(\boldsymbol{g}_t\) 是第 \(t\) 步的梯度
-
\(\alpha_t\) 是第 \(t\) 步的学习率,可以进行衰减,也可以不变
-
\(\psi(\cdot)\) 是学习率缩放函数,可以取 1 或历史梯度的模的移动平均
-
\(\phi(\cdot)\) 是优化后的参数更新方向,可以取当前的梯度 \(\boldsymbol{g}_{t}\) 或历史梯度的移动平均
2.6 PyToch 相关函数
2.6.1 torch.optim 模块:优化器模块
主要参数:
-
params: \(\boldsymbol{\theta}_0\) -
lr (float): learning rate, \(\alpha\) -
momentum (float, default = 0): momentum factor, \(\rho\) -
dampening (float, default = 0): dampening for momentum, \(\tau\) -
weight_decay (float, default = 0): weight decay (L2 penalty), \(\beta\) -
nesterov (bool, default = False): -
maximize (bool, default = False): IfTruemaximize theparamsbased on the objective
算法流程
2.6.2 torch.optim.lr_scheduler 模块:学习速率衰减
lr_scheduler 模块是按照 epoch 来调整学习速率的
参考资料:
2.6.3 梯度截断
torch.nn.utils.clip_grad_value_(parameters, clip_value)
torch.nn.utils.clip_grad_norm_(parameters, max_norm, norm_type=2.0, ...)
主要参数:
parameters (Iterable[Tensor] or Tensor):
实例:
from torch.nn.utils import clip_grad_value_
from torch.nn.utils import clip_grad_norm_
# 初始一个 tensor
param = torch.tensor([2., 2.], requires_grad=True)
param.grad = torch.tensor([2., 2.])
print(param.data, param.grad)
clip_grad_value_(param, 1.)
print(param.data, param.grad)
# tensor([2., 2.]) tensor([1., 1.])
clip_grad_norm_(param, max_norm=1.)
print(param.data, param.grad)
# tensor([2., 2.]) tensor([0.7071, 0.7071])
3. 参数初始化
当使用梯度下降法来进行优化网络参数时,参数初始值的选取十分关键,关系到网络的优化效率和泛化能力。
(1)预训练初始化(Pre-trained Initialization)
- 精调(Fine-Tuning)
(2)随机初始化(Random Initialization)
(3)固定值初始化
-
对于一些特殊的参数,根据经验用一个特殊的固定值来进行初始化
-
如:偏置(Bias)通常用 0 来初始化
-
在 LSTM 网络的遗忘门中,偏置通常初始化为 1 或 2,使得时序上的梯度变大
-
ReLU 的神经元,有时也可以将偏置设为 0.01,使得 ReLU 神经元在训练初期更容易激活,从而获得一定的梯度来进行误差反向传播
-
3.1 基于固定方差的参数初始化
(1)高斯分布初始化:使用一个高斯分布 \(\mathcal{N}(0, \sigma^2)\) 对每个参数进行随机初始化
(2)均匀分布初始化:在一个给定的区间 \([-r,r]\) 内采用均匀分布来初始化,其中
\(r = \sqrt{3 \sigma^2}\)
是如何设置方差 \(\sigma^2\):如果参数范围取的太小:
-
一是会导致神经元的输出过小,经过多层之后信号就慢慢消失了;
-
二是还会使得 Sigmoid 型激活函数丢失非线性的能力
为了降低固定方差对网络性能以及优化效率的影响,基于固定方差的随机初始化方法一般需要配合逐层归一化来使用.
3.2 基于方差缩放的参数初始化
一般而言,参数初始化的区间应该根据神经元的性质进行差异化的设置
- 如果一个神经元的输入连接很多,它的每个输入连接上的权重就应该小一些,以避免神经元的输出过大(当激活函数为 ReLU 时)或过饱和(当激活函数为Sigmoid函数时).
方差缩放(Variance Scaling):
-
为了缓解梯度消失或爆炸问题,应尽可能保持每个神经元的输入和输出的方差一致
-
根据神经元的连接数量来自适应地调整初始化分布的方差
3.2.1 Xavier 初始化
Xavier 初始化(或称为 Glorot 初始化)(Glorot et al., 2010)
3.2.2 He 初始化
He 初始化(或称为 Kaiming 初始化) (He et al., 2015)
Xavier 初始化和 He 初始化的具体设置情况
| 初始化方法 | 激活函数 | 均匀分布 \([-r,r]\) |
高斯分布 \(\mathcal{N}(0, \sigma^2)\) |
|---|---|---|---|
| Xavier | Logistic | \(r = 4 \sqrt{\frac{6}{M_{l-1} + M_l}}\) | \(\sigma^2 = 16 \times \frac{2}{M_{l-1} + M_l}\) |
| Xavier | Tanh | \(r = \sqrt{\frac{6}{M_{l-1} + M_l}}\) | \(\sigma^2 = \frac{2}{M_{l-1} + M_l}\) |
| He | ReLU | \(r = \sqrt{\frac{6}{M_{l-1}}}\) | \(\sigma^2 = \frac{2}{M_{l-1}}\) |
其中:
-
\(M_{l-1}\) 为接收前一层神经元的个数
-
\(M_{l}\) 为该层神经元的输出
-
激活函数表示该层的激活函数
3.3 正交初始化
正交初始化(Orthogonal Initialization)(Saxe et al., 2014):
- 期望:误差项在反向传播中具有范数保持性(Norm-Preserving)
假设:
- \(\mathbf{W}^{(l)} \in \mathbb{R}^{M \times M} (1 \leq l \leq L)\) 为神经网络的第 \(l\) 层权重矩阵
正交初始化(Orthogonal Initialization):将权重矩阵 \(\mathbf{W}^{(l)}\) 初始化为正交矩阵,即 \(\mathbf{W}^{(l)} \left( \mathbf{W}^{(l)} \right)^{\top} = \mathbf{I}\)
-
(1) 用均值为 0、方差为 1 的高斯分布初始化一个矩阵
-
(2) 将这个矩阵用奇异值分解得到两个正交矩阵,并使用其中之一作为权重矩阵
-
正交初始化通常用在循环神经网络中循环边上的权重矩阵上
-
当在非线性神经网络中应用正交初始化时,通常需要将正交矩阵乘以一个缩放系数 \(\rho\)
- 比如当激活函数为 ReLU 时,激活函数在 0 附近的平均梯度可以近似为 0.5。为了保持范数不变,缩放系数 \(\rho\) 可以设置为 \(\sqrt{2}\).
3.4 torch.nn.init 模块
-
参数含义和初始化计算公式见:site
-
直接在原 tensor 上处理(in-place algorithm)
-
主要的方法有:
# 固定值初始化
torch.nn.init.zeros_(tensor.data)
torch.nn.init.ones_(tensor.data)
torch.nn.init.constant_(tensor.data, val)
# 随机分布初始化
torch.nn.init.uniform_(tensor.data, a=0.0, b=1.0)
torch.nn.init.normal_(tensor.data, mean=0.0, std=1.0)
# xavier 初始化
torch.nn.init.xavier_uniform_(tensor.data, gain=1.0)
torch.nn.init.xavier_normal_(tensor.data, gain=1.0)
# kaiming 初始化
torch.nn.init.kaiming_uniform_(tensor.data, a=0, mode='fan_in', nonlinearity='leaky_relu')
torch.nn.init.kaiming_normal_(tensor.data, a=0, mode='fan_in', nonlinearity='leaky_relu')
# 正交初始化
torch.nn.init.orthogonal_(tensor.data, gain=1)
代码实例:
param = torch.tensor([[2., 2.], [2., 2.]], requires_grad=True)
param.grad = torch.tensor([[2., 2.], [2., 2.]])
print(param.data, param.grad)
# 固定值初始化
torch.nn.init.zeros_(param.data)
# 等价于,使用 .data 属性赋值
param.data = torch.tensor([[0., 0.], [0., 0.]])
print(param.data)
# xavier 初始化
torch.nn.init.xavier_uniform_(param.data)
print(param.data)
计算 fan in 和 fan out
fan_in, fan_out = torch.nn.init._calculate_fan_in_and_fan_out(tensor)
原始函数:
def _calculate_fan_in_and_fan_out(tensor):
dimensions = tensor.dim()
if dimensions < 2:
raise ValueError("Fan in and fan out can not be computed for tensor with fewer than 2 dimensions")
num_input_fmaps = tensor.size(1)
num_output_fmaps = tensor.size(0)
receptive_field_size = 1
if tensor.dim() > 2:
# math.prod is not always available, accumulate the product manually
# we could use functools.reduce but that is not supported by TorchScript
for s in tensor.shape[2:]:
receptive_field_size *= s
fan_in = num_input_fmaps * receptive_field_size
fan_out = num_output_fmaps * receptive_field_size
return fan_in, fan_out
代码实例:
from torch.nn.init import _calculate_fan_in_and_fan_out
tensor = torch.rand((3, 4))
# (4, 3)
tensor = torch.rand((3, 4, 5))
# (20, 15)
参考文献:
torch.nn.init模块 site
4. 数据预处理
归一化(Normalization)
最小最大值归一化(Min-Max Normalization):
-
通过缩放将每一个特征的取值范围归一到 \([0, 1]\) 或 \([−1, 1]\)。
-
假设有 \(N\) 个 \(D\) 维样本:\(\{\boldsymbol{x}_{n}\}_{n=1}^{N}\),$ \boldsymbol{x}_{n} \in \mathbb{R}^{D}$,对于每一维特征 \(x_n^{(d)}\),归一化后的特征为:
标准化(Standardization)或 Z 值归一化(Z-Score Normalization)
-
将每一个维特征都调整为均值为 0,方差为 1
-
对于每一维特征 \(x_{n}^{(d)}, n = 1, \cdots, N\),首先计算其均值 \(\mu_d\) 和方差 \(\sigma_d^2\):
- 再进行标准化
白化(Whitening):用于降低输入数据特征之间的冗余性。输入数据经过白化处理后,特征之间相关性较低,并且所有特征具有相同的方差。
- 白化的一个主要实现方式是使用主成分分析(Principal Component Analysis, PCA)方法去除掉各个成分之间的相关性.
5. 逐层归一化
逐层归一化(Layer-wise Normalization)是将传统机器学习中的数据归一化方法应用到深度神经网络中,对神经网络中隐藏层的输入进行归一化,从而使得网络更容易训练。
逐层归一化可以有效提高训练效率的原因有以下几个方面:
(1) 更好的尺度不变性
-
内部协变量偏移(Internal Covariate Shift)
-
尺度不变性
(2) 更平滑的优化地形
5.1 批量归一化 Batch Normalization
批量归一化(Batch Normalization,BN)(Ioffe et al., 2015) :批量归一化的提出动机是为了解决内部协方差偏移问题,但后来的研究者发现其主要优点是归一化会导致更平滑的优化地形(Santurkar et al., 2018)
在实践中:归一化操作一般应用在仿射变换(Affine Transformation) \(\boldsymbol{Wa}^{(l-1)} + \boldsymbol{b}\) 之后、激活函数之前.
对于一个深度神经网络:
-
令第 \(l\) 层的净输入为 \(\boldsymbol{z}^{(l)}\):
-
第 \(l\) 层神经元的输出为 \(\boldsymbol{a}^{(l)}\):
为了提高优化效率,就要使得净输入 \(\boldsymbol{z}^{(l)}\) 的分布一致,对 \(\boldsymbol{z}^{(l)}\) 进行归一化,相当于每一层都
进行一次数据预处理。
-
逐层归一化需要在中间层进行操作,要求效率比较高,因此,复杂度比较高的白化方法就不太合适
-
为了提高归一化效率,一般使用标准化将净输入 \(\boldsymbol{z}^{(l)}\) 的每一维都归一到标准正态分布
- 其中:\(\mathbb{E} \left[ \boldsymbol{z}^{(l)} \right]\) 和 \(\text{var}\left[ \boldsymbol{z}^{(l)} \right]\) 是指当前参数下,\(\boldsymbol{z}^{(l)}\) 的每一维在整个训练集上的期望和方差
在基于小批量的随机梯度下降法重,准确计算 \(\boldsymbol{z}^{(l)}\) 的期望和方差是不可行的
- 其通常用当前小批量样本集的均值和方差近似估计.
用小批量样本集的均值和方差的近似估计:假设:
-
给定一个包含 \(K\) 个样本的小批量样本集合
-
第 \(l\) 层神经元的净输入 \(\boldsymbol{z}^{(1,l)}, \boldsymbol{z}^{(1,l)}, \cdots, \boldsymbol{z}^{(K,l)}\) 的均值和方差为
对净输入 \(\boldsymbol{z}^{(l)}\) 的标准归一化会使得其取值集中到 0 附近
-
如果使用 Sigmoid 型激活函数时,这个取值区间刚好是接近线性变换的区间,减弱了神经网络的非线性性质.
-
因此,为了使得归一化不对网络的表示能力造成负面影响,可以通过一个附加的缩放和平移变换改变取值区间.
-
其中:其中 \(\boldsymbol{\gamma}\) 和 \(\boldsymbol{beta}\) 分别代表缩放和平移的参数向量
-
从最保守的角度考虑,可以通过标准归一化的逆变换来使得归一化后的变量可以被还原为原来的值
综上:批量归一化操作可以看作一个特殊的神经层,加在每一层非线性激活函数之前,即:
- 其中:因为批量归一化本身具有平移变换,所以仿射变换 \(\boldsymbol{W} \boldsymbol{a}^{(l-1)}\) 不再需要偏置参数.
缺点:批量归一化是对一个中间层的单个神经元进行归一化操作,因此要求小批量样本的数量不能太小,否则难以计算单个神经元的统计信息。
- 此外,如果一个神经元的净输入的分布在神经网络中是动态变化的,如循环神经网络,那么就无法应用批量归一化操作。
5.2 层归一化 Layer Normalization
层归一化(Layer Normalization) (Ba et al., 2016) 对一个中间层的所有神经元进行归一化
对于一个深度神经网络:
-
第 \(l\) 层的净输入为 \(\boldsymbol{z}^{(l)}\):
-
第 \(l\) 层神经元的数量为 \(M_l\)
则其均值和方差为
层归一化定义为:
- 其中 \(\boldsymbol{\gamma}\) 和 \(\boldsymbol{\beta}\) 分别代表缩放和平移的参数向量,和 \(\boldsymbol{z}^{(l)}\) 维数相同.
5.2.1 循环神经网络中的层归一化
在循环神经网络中,对循环神经层进行归一化操作。假设:
-
\(t\) 时刻的循环神经网络的隐藏层为 \(\boldsymbol{h}_t\)
-
\(t\) 时刻的输入为 \(\boldsymbol{x}_t\)
-
\(\boldsymbol{U}\) 和 \(\boldsymbol{W}\) 为网络参数
其层归一化的更新:
在标准循环神经网络中,循环神经层的净输入一般会随着时间慢慢变大或变小,从而导致梯度爆炸或消失。而层归一化的循环神经网络可以有效地缓解这种状况.
层归一化 V.S. 批量归一化
-
整体上是十分类似的,差别在于归一化的方法不同
-
对于 \(K\) 个样本的一个小批量集合 \(\mathbf{Z}^{(l)} = \left[ \boldsymbol{z}^{(1,l)} ; \cdots ; \boldsymbol{z}^{(K,l)} \right] \in \mathbb{R}^{K \times M_l}\),
-
层归一化是对矩阵 \(\mathbf{Z}^{(l)}\) 的每一列进行归一化,
-
批量归一化是对每一行进行归一化.
-
-
一般而言,批量归一化是一种更好的选择。
- 当小批量样本数量比较小时,可以选择层归一化.
5.3 权重归一化
权重归一化(Weight Normalization) (Salimans et al., 2016) 是对神经网络的连接权重进行归一化,通过再参数化(Reparameterization)方法,将连接权重分解为长度和方向两种参数。假设:
-
第 \(l\) 层神经元 \(\boldsymbol{a}^{(l)} = f \left( \boldsymbol{z}^{(l)} \right) = f \left( \boldsymbol{W} \boldsymbol{a}^{(l-1)} + \boldsymbol{b} \right)\)
-
\(\boldsymbol{W}\) 再参数化为:
-
其中:\(\boldsymbol{W}_{i,:}\) 表示权重 \(\boldsymbol{W}\) 的第 \(i\) 行
-
\(M_l\) 为神经元数量
-
\(g_i\) 是一个标量,为新引入的参数
-
\(\boldsymbol{v}_{i}\) 和 \(\boldsymbol{a}^{(l-1)}\) 维数相同。
由于在神经网络中权重经常是共享的,权重数量往往比神经元数量要少,因此权重归一化的开销会比较小。
5.4 局部响应归一化
局部响应归一化(Local Response Normalization,LRN) (Krizhevsky et al., 2012):通常用在基于卷积的图像处理上。
假设:
-
假设一个卷积层的输出特征映射 \(\boldsymbol{Y} \in \mathbb{R}^{M' \times N' \times P}\) 为三维张量
-
每个切片矩阵 \(\boldsymbol{Y}^p \in \mathbb{R}^{M' \times N'}\) 为一个输出特征映射,\(1 \leq p \leq P\)
-
\(P\) 为通道总数
-
局部响应归一化是对邻近的特征映射进行局部归一化
-
其中:除运算和幂运算都是按元素运算
-
\(n,k,\alpha,\beta\) 为超参数;\(n\) 为局部归一化的特征窗口大小
- 在 AlexNet 中,这些超参的取值为 \(n=5, k=2, \alpha = 10 e^{-4}, \beta = 0.75\)
局部响应归一化和层归一化都是对同层的神经元进行归一化。
-
不同的是,局部响应归一化应用在激活函数之后,只是对邻近的神经元进行局部归一化,并且不减去均值
-
局部响应归一化和生物神经元中的侧抑制(lateral inhibition)现象比较类似,即活跃神经元对相邻神经元具有抑制作用。
-
当使用ReLU作为激活函数时,神经元的活性值是没有限制的,局部响应归一化可以起到平衡和约束作用
-
如果一个神经元的活性值非常大,那么和它邻近的神经元就近似地归一化为 0,从而起到抑制作用,增强模型的泛化能力
最大汇聚也具有侧抑制作用:
-
最大汇聚是对同一个特征映射中的邻近位置中的神经元进行抑制
-
局部响应归一化是对同一个位置的邻近特征映射中的神经元进行抑制
5.5 PyTorch
PyTorch 中,主要的 Normalization 层有:官方文档
import pytorch.nn as nn
nn.BatchNorm1d()
nn.BatchNorm2d()
nn.BatchNorm3d()
nn.LazyBatchNorm1d()
nn.LazyBatchNorm2d()
nn.LazyBatchNorm3d()
nn.LayerNorm()
nn.LocalResponseNorm()
权重归一化函数:site
nn.utils.weight_norm(module, name='weight', dim=0)
LSTM with Layer Normalization and Dropout 的变体:github
代码实例:batch norm 和 layer norm
import pytorch
import pytorch.nn as nn
def batch_norm1d_(input):
eps = 1e-5
mean = input.mean(dim=0)
var = input.var(dim=0, unbiased=False)
output = (input - mean) / (var + eps).sqrt()
return output
def layer_norm_(input):
eps = 1e-5
mean = input.mean(dim=1).unsqueeze(1)
var = input.var(dim=1, unbiased=False).unsqueeze(1)
output = (input - mean) / (var + eps).sqrt()
return output
N, D = 10, 3
input = torch.torch.randn((N, D), dtype=torch.float) * 100
print('Size of input:', input.size())
# Batch Norm
bn = nn.BatchNorm1d(num_features = D)
print('Parameters of BN: ', list([p.detach().numpy() for p in bn.parameters()]))
out_1 = bn(input).detach().numpy()
out_2 = batch_norm1d_(input).numpy()
print(np.abs(out_1 - out_2).sum())
# Layer Norm
ln = nn.LayerNorm(normalized_shape = D)
print('Parameters of LN: ', list([p.detach().numpy() for p in bn.parameters()]))
out_1 = ln(input).detach().numpy()
out_2 = layer_norm_(input).numpy()
print(np.abs(out_1 - out_2).sum())
6. 超参数优化
常见的超参数有以下三类:
(1) 网络结构,包括神经元之间的连接关系、层数、每层的神经元数量、激活函数的类型等
(2) 优化参数,包括优化方法、学习率、小批量的样本数量等
(3) 正则化系数
6.1 网格搜索
网格搜索(Grid Search) (Bergstra et al., 2012)
6.2 随机搜索
超参数优化(Hyperparameter Optimization)
6.3 贝叶斯优化
贝叶斯优化(Bayesian optimization)(Bergstra et al., 2011; Snoek et al.,2012)
- 贝叶斯优化(Bayesian optimization)(Bergstra et al., 2011; Snoek et al., 2012)
7. 网络正则化
7.1 L1 和 L2 正则化
7.2 权重衰减
权重衰减(Weight Decay)是一种有效的正则化方法(Hanson et al., 1989),在每次参数更新时,引入一个衰减系数。
-
其中:\(\boldsymbol{g}_t\) 为第 \(t\) 步更新时的梯度
-
\(\alpha \ (0< \alpha < 1)\) 为学习率
-
\(\beta \ (0< \beta < 1)\) 为权重衰减系数,一般取值比较小,比如 0.0005
可以看作以下两步的结合(PyTorch 中):
在标准的随机梯度下降中,权重衰减正则化和 L2 正则化的效果相同(见习题7-9)。
-
权重衰减在一些深度学习框架中通过 L2 正则化来实现
-
但是,在较为复杂的优化方法(比如 Adam)中,权重衰减正则化和 L2 正则化并不等价 (Loshchilov et al., 2017b)
7.3 提前停止 Early Stop
提前停止(Early Stop)对于深度神经网络来说是一种简单有效的正则化方法
7.4 丢弃法 Dropout
7.4.1 循环神经网络上的丢弃法
7.5 数据增强 Data Augmentation
图像数据的增强方法:
-
(1)旋转(Rotation)
-
(2)翻转(Flip)
-
(3)缩放(Zoom In / Out)
-
(4)平移(Shift)
-
(5)加噪声(Noise)
7.6 标签平滑 Label Smoothing
标签平滑(Label Smoothing):在输出标签中添加噪声来避免模型过拟合 (Szegedy et al., 2016)
-
一个样本 \(\boldsymbol{x}\) 的标签可以用 one-hot 向量表示,即 \([0, \cdots, 0, 1, 0 \cdots, 0]^{\top}\),这种标签可以看作硬目标(Hard Target)
-
如果使用 Softmax 分类器并使用交叉熵损失函数,最小化损失函数会使得正确类和其他类的权重差异变得很大
-
Softmax 函数的性质可知,如果要使得某一类的输出概率接近于 1,其未归一化的得分需要远大于其他类的得分,可能会导致其权重越来越大,并导致过拟合
-
如果样本标签是错误的,会导致更严重的过拟合现象
引入一个噪声对标签进行平滑,即假设样本以 \(\epsilon\) 的概率为其他类。平滑后的标签被称作软目标(Soft Target):
-
其中 \(K\) 为标签数量
-
标签平滑可以避免模型的输出过拟合到硬目标上,并且通常不会损害其分类能力
一种更好的做法是按照类别相关性来赋予其他标签不同的概率。比如先训练另外一个更复杂(一般为多个网络的集成)的教师网络(Teacher Network),并使用大网络的输出作为软目标来训练学生网络(Student Network)。这种方法也称为知识蒸馏(Knowledge Distillation)(Hinton et al., 2015)
参考文献
邱锡鹏,"第 7 章 网络优化与正则化" in 神经网络与深度学习,机械工业出版社,https://nndl.github.io/, 2020.

浙公网安备 33010602011771号