学习提示
这周的知识点也十分分散,主要包含四项内容:调参、批归一化、多分类任务、编程框架。
通过在之前的编程项目里调整学习率,我们能够体会到超参数对模型效果的重要影响。实际上,选择超参数不是一个撞运气的过程。我们应该有一套系统的方法来快速找到合适的超参数。
两周前,我们学习了输入归一化。类似地,如果对网络的每一层都使用归一化,也能提升网络的整体表现。这样一种常用的归一化方法叫做批归一化。
之前,我们一直都在讨论二分类问题。而只要稍微修改一下网络结构和激活函数,我们就能把二分类问题的算法拓展到多分类问题上。
为了提升编程的效率,从这周开始,我们要学习深度学习编程框架。编程框架往往能够帮助我们完成求导的功能,我们可以把精力集中在编写模型的正向传播上。
课堂笔记
调参
调参的英文动词叫做tune,这个单词作动词时大部分情况下是指调音。这样一看,把调参叫做“调整参数”或“调试参数”都显得很“粗鲁”。理想情况下,调参应该是一个系统性的过程,就像你去给乐器调音一样。乱调可是行不通的。
超参数优先级
回顾一下,我们接触过的超参数有:
- 学习率 α \alpha α
- momentum β \beta β
- adam β 1 , β 2 , ϵ \beta_1, \beta_2, \epsilon β1,β2,ϵ
- 隐藏层神经元数
- 层数
- 学习率递减率
- mini-batch size
其中,优先级最高的是学习率。吴恩达老师建议大家调完学习率后,再去调 β \beta β、隐藏层神经元数、mini-batch size。如果使用adam,则它的三个参数基本不用调。
超参数采样策略
在尝试各种超参数时,不要按“网格”选参数(如下图左半所示),最好随机选参数(如下图右半所示):
如果用网格采样法的话,你可能试了25组参数,每个参数只试了5个不同的值。而实际上,你试的两个参数中只有一个参数对结果的影响较大,另一个参数几乎不影响结果。最终,你尝试的25次中只有5次是有效的。
而采用随机采样法试参数的话,你能保证每个参数在每次尝试时都取不同值。这样试参数的效率会更高一点。
另外,调参时还有一个“由粗至精”的过程。如下图所示:
当我们发现某几个参数的结果比较优秀时,我们可以缩小搜索范围,仅在这几个参数附近进行搜索。
超参数搜索尺度
搜索参数时,要注意搜索的尺度。如果搜索的尺度不够恰当,我们大部分的调参尝试可能都是无用功。
比如当搜索学习率时,我们应该按0.0001, 0.001, 0.01, 0.1, 1
这样指数增长的方式去搜索,而不应该按0.2, 0.4, 0.6, 0.8, 1
这种均匀采样的方式搜索。这是因为学习率是以乘法形式参与计算,取0.4, 0.6, 0.8
得到的结果可能差不多,按这种方式采样的话,大部分的尝试都是浪费的。而以0.001, 0.01, 0.1
这种方式取学习率的话,每次的运行结果就会差距较大,每次尝试都是有意义的。
除了搜索学习率时用到的指数采样,还有其他的采样方式。让我们看调整momentum项 β \beta β的情况。回忆一下, β \beta β取0.9,表示近10项的平均数; β \beta β取0.99,表示近100项的平均数。也就是说, β \beta β表示 1 1 − β \frac{1}{1-\beta} 1−β1项的平均数。我们可以对 1 1 − β \frac{1}{1-\beta} 1−β1进行指数均匀采样。
当然,有些参数是可以均匀采样的。比如隐藏层的个数,我们可以从[2, 3, 4]里面挑一个;比如每个隐藏层的神经元数,我们也可以直接均匀采样。
总结一下,我们在搜索超参数的时候,应该从超参数所产生的影响出发,考虑应该在哪个指标上均匀采样,再反推超参数的采样公式,而不一定要对超参数本身均匀采样。
当然了,如果我们不确定应该从哪个尺度对超参数采样,可以先默认使用均匀采样。因为我们会遵循由粗至精的搜索原则,尝试几轮后我们就能够观察出超参数的取值规律,从而在正确的尺度上对超参数进行搜索。
批归一化(Batch Normalization)
在第五篇笔记中,我们曾学习了输入归一化。其计算公式如下:
μ = 1 m Σ i = 1 m x ( i ) x : = ( x − μ ) σ 2 = 1 m Σ i = 1 m ( x ( i ) ) 2 x : = x / σ \begin{aligned} \mu&=\frac{1}{m}\Sigma_{i=1}^{m}x^{(i)} \\ x &:= (x - \mu) \\ \sigma^2&=\frac{1}{m}\Sigma_{i=1}^{m}(x^{(i)})^2 \\ x &:= x / \sigma \end{aligned} μxσ2x=m1Σi=1mx(i):=(x−μ)=m1Σi=1m(x(i))2:=x/σ
通过归一化,神经网络第一层的输入更加规整,模型的训练速度能得到有效提升。
我们知道,神经网络的输入可以看成是第零层(输入层)的激活输出。一个很自然的想法是:我们能不能把神经网络每一个隐藏层的激活输出也进行归一化,让神经网络更深的隐藏层也能享受到归一化的加速?
批归一化(Batch Normalization)就是这样一种归一化神经网络每一个隐藏层输出的算法。准确来说,我们归一化的对象不是每一层的激活输出 a [ l ] a^{[l]} a[l],而是激活前的计算结果 z [ l ] z^{[l]} z[l]。让我们看看对于某一层的激活前输出 z = z [ l ] z=z^{[l]} z=z[l],我们该怎么进行批归一化。
首先,还是先获取符合标准正态分布的归一化结果 z n o r m ( i ) z^{(i)}_{norm} znorm(i):
I n p u t z ( 1 ) , z ( 2 ) , . . . z ( m ) μ = 1 m Σ i m z ( i ) σ 2 = 1 m Σ i m ( z ( i ) − μ ) 2 z n o r m ( i ) = z ( i ) − μ σ