基本概念
结构化学习
机器学习中的任务不只包括Regression和Classification两大类,还有Structure Learning
,也就是函数的输出并不是一个标量或者一个类别,而是生成有结构的输出(比如图像、文本等)。
误差曲面
通过试不同的参数,然后计算对应情况下的loss,画出来的等高线图称为Error Surface
。
如上图所示,老师在课程中给的是线性模型假设下的例子。越偏红色系,代表计算出来的误差越大;越偏蓝色系,代表计算出来的误差越小。
神经网络训练不起来怎么办?
梯度下降算法面临的问题
梯度为0的点不全是local minima/maxima,还有saddle point
的情况,可以称为critical point
,在数学上也称为驻点(stationary point
)。因此,在提梯度下降法为什么有时会失效时,只说会陷入局部最优而无法到达全局最优并不严谨,因为还可能会陷入saddle point的情况。
例:\(y=x^3\),在 \(x=0\) 处梯度为0,但既不是极大值也不是极小值。
那么,如何区分局部最优点和鞍点?借助泰勒展开然后分情况讨论。
如果在优化过程中是停在了saddle point的位置,那么我们仍然可能通过Hessian矩阵来判断下一步更新的方向:找到负特征值对应的特征向量。
然而,实际应用中,几乎很难从Hessian矩阵来指导优化,因为二阶微分矩阵计算量非常大。
在高维情况下(参数量非常大),局部极值点很少,当然很可能存在鞍点,但至少有路是可以更新的,不至于stuck。
如何划分batch
通常情况下,一个epoch中,会将整个数据集切分为不同的batch,然后每个batch都执行一个update更新参数。
- 由于GPU并行加速的效果,所以大(一定范围内,不要太大)的batch一次update时间并不会增加,考虑到大的batch分的batch个数更小,因此大的batch一次epoch整体训练时间反而更小。
- 小batch的noisy效果有助于训练,更不容易stuck在梯度为0的情况。
- 不同batch大小在训练集上训练到接近的性能,但在测试集上的表现小batch更好。一篇论文的解释是存在很多个性能接近的局部极值点,小batch训练得到的可能是flat minima,而大batch训练得到的可能是sharp minima。
对于不同大小的batch对应的情况可以总结为如下表格:
Small | Large | |
---|---|---|
Speed for one update (no parallel) | Faster | Slower |
Speed for one update (with parallel) | Same | Same (not too large) |
Time for one epoch | Slower | Faster |
Gradient | Noisy | Stable |
Optimization | Better | Worse |
Generalization | Better | Worse |
momentum
可以理解成当前的前进方向是上次前进方向和当前负梯度方向的加和,也可以理解成之前所有负梯度方向的(加权)和。
因此,
-
critical points 梯度为0。
-
critical points 既可能是局部极值点,也可能是鞍点。
-
可以通过 Hessian 矩阵判断。
-
通过 Hessian 矩阵的负特征值对应的特征向量方向,可以走出鞍点。
-
局部极值点的情况在高维空间可能是罕见的。
-
-
小的 batch 和 momentum 有助于训练,避免陷于 critical point。
Learning Rate
Training stuck 的情况并不一定都是梯度为0(或者很小),可能和学习率的设置有关,然而固定的学习率又很难获得理想的结果,因此提出Adaptive Learning Rate
。
下图给的例子是说明在 w 和 b 两个参数方向上斜率差距很大,一个很大,一个很小,导致采用固定的学习率会使得在两个维度上的一个维度出现问题,或者变化非常陡峭,或者更新非常多也基本没有前进。
具体的优化方法有 AdaGrad,RMSProp,Adam 等使固定学习率除以一个和参数相关的量;另外还有 Learning Rate Decay/Scheduling 策略,也就是固定学习率也随着时间/epoch变化;最后还有Warm Up策略,简单而言是学习率先变大再变小,在BERT和Transformer中作为“黑科技”有用到。一种可能的解释是刚开始走的不太准,因此不要设置太大。
Batch Normalization
思考什么情况下会出现上图的问题呢,也就是两维的参数 w1 和 w2 梯度变化显著区别?答案是和输入的范围(粒度)有很大关系。李宏毅老师在下面给一个简单的例子,假设 x1 的值都比较小(1,2……)那么对 w1 加上一个变化量 Δw1,乘上 x1 之后变化也不大;但与此同时,x2 的值都很大(100,200……)那么对 w2 加上一个变化量 Δw2,再乘上 x2 之后变化就会很大。
如果 batch 大小为 1,那么就没有意义了。
因此,将特征的不同维度控制在同一个范围内是比较合理的,这就称为Feature Normalization
,而 Batch Normalization 是其中一项具体的技术,它不仅对输入 x 的不同维进行 normalization,而且神经网络前一层的输出也同样可以看作下一层的输入,因此在不同层之间也加上 normalization 层。
另外,在具体实现时,还会增加 β 和 γ 两个参数,它们的初始值往往是1和0,保证上面我们提到的不同维都变换到均值为0方差为1的分布上,但这样可能会对模型施加限制,因此要允许模型具有突破这个限制的能力。
还有一个问题,前面我们讲的都是训练上 batch normalization 是怎么工作的?但在 test 时,可能并没有 batch,不能说如果只来一个测试点我们还要等 batch 足够多时才能预测,PyTorch的做法是在训练时会记录每个 batch 的 \(\mu\) 和 σ,然后做移动平均 \(\bar{\mu}=\rho \bar{\mu} + (1-\rho)\mu_t\)。
最后,原始的 batch normalization 论文中提出 internal covariance shift 的概念,covariance shift 是之前就有的,但 internal covariance shift 可能是作者首次提出,他认为 batch normalization 可能解决了这个问题所以效果提升。但后续被《How Does Batch Normalization Help Optimization》大量的实验否定了这种观点,但支持“使 error surface不那么崎岖”的观点。此外,这篇论文的作者还提出其他很多方法都可以类似的功能,也具有甚至更好的效果,因此 batch normalization 的提出可能具有偶然性。
internal covariance shift
模型参数从A更新到A',B更新到B',但B的更新是根据a来的,也就是在还没有更新A->A'(也自然没有更新a->a')时,因此B更新到B'可能对原来的a好但不一定对a'好,而 batch normalization 可以使得a和a'分布接近,因此具有好的效果。大概也可以理解成参数更新顺序的问题,前层和后层的神经网络参数是一起更新的,那么后层参数更新时是根据前层还没有更新参数时所做的。