文章目录
- 训练、开发和测试集
- 偏差 bias 和方差 variance
- 机器学习基础
- 正则化
- 为什么正则化可以减少过拟合
- Dropout 正则化
- 理解 Dropout
- 其他正则化方法
- 归一化输入
- 梯度消失与梯度爆炸 & 神经网络的权重初始化
- 梯度的数值逼近
- 梯度检验
- 关于梯度检验实现的注记
- Mini-batch 梯度下降法
- 理解 mini-batch 梯度下降法
- 指数加权平均
- 理解指数加权平均
- 指数加权平均的偏差修正
- 动量梯度下降法 momentum gradient descent
- RMSprop root mean square prop
- Adam 优化算法 adaptive momentum estimation
- 学习率衰减
- 局部最优的问题
- 调试处理
- 为超参数选择合适的范围
- 超参数训练的实践
- 正则化网络的激活函数
- 将 BatchNorm 拟合进神经网络
- BatchNorm 为什么奏效
- 测试时的 Batch Norm
- Softmax 回归
- 训练一个 softmax 分类器
- 深度学习框架
- Tensorflow
Deep Learning 笔记(2):提升和优化网络的良药
训练、开发和测试集
如何搭建一个神经网络模型?需要考虑一共几层 layer、多少 hidden units、learning rate 是多少、激活函数用什么。但是这些其实不需要一开始就确认,整个过程是高度迭代的,可以修改调整。Idea -> Code -> Experiment 往复循环。
训练集 train、验证集 dev、测试集 test:三者的比例,需要看数据集整体有多大。验证集主要用来调整和确定超参数,要适当大一点,不能特别小,上万条就差不多够了。测试集主要用来测试模型的性能,上万条的数据量也可以了。三个子集中的数据分布应该基本保持一致。如果不严格按照 3 个子集来划分,2 个也是足够的,剩下两个应该是训练和验证(因为超参数的选择过程不可避免,但是却可以缺失无偏估计,因为验证集也可以用来做无偏估计),但是人们喜欢在那个时候叫训练和测试(只是个称呼罢了)。
偏差 bias 和方差 variance
深度学习总是习惯分开来考虑这两者,而不去考虑这两者之间的权衡。下图依次是 high bias、just right、high variance。如果既是 high bias 又是 high variance,对应的情况可能是部分区域 high bias,部分区域 high variance,这在高维空间中还挺容易出现的。
机器学习基础
- 首先要解决的是模型欠拟合的问题:如果发现 high bias 欠拟合,可以选择新的模型结构,多一点隐藏层层数或者单元,训练更长的时间,更换更好的优化算法。
- 接着判断是不是 high variance 过拟合,多一点数据,或者正则化。
综上,神经网络中可以针对 high bias 和 high variance 有不同的应对方法且不干扰另一项指标。理论上来讲,只要正则做的好,完全可以用大一号的网络来解决欠拟合。所以神经网络很少把 bias 和 variance 之间的权衡拿来讨论,因为它不需要。
正则化
L1 正则相比 L2 来说,能够让模型稀疏(有更多的 0),直接实现了特征选择,选择原特征空间的子集(因为某些特征直接 乘以 0 消失了呀)。但是这个操作,并不会减小模型尺寸。
至于如何理解 L1 正则化更容易让模型稀疏,借助周志华老师的西瓜书中插图来说明。在误差更新的过程中,其与 L1 和 L2 相交的位置点不一样。虽然都是会让 W 绝对值相对更小,但是和 L1 相交点多落在坐标轴上,而和 L2 相交的点多落在象限中。
为什么正则化可以减少过拟合
在回答这个问题前,应该先解释过拟合意味着什么。过拟合意味着相对训练数据而言,模型的表达能力太强了,也就是模型太过于复杂了,太闲了,以至于有精力纠结很多细枝末节而不是样本中的“好特征”。所以我们要让一个太过于复杂的模型,变得简单一点。
怎么算简单一点呢?如果不通过直接修改模型结构来简化模型的话,我可以想办法“阉割”掉一些神经元。那我们已经知道了,神经元真正复杂的地方在于“非线性”而不是“线性”。因为完全线性的话,就直接退化到逻辑回归了(这个有点偏执了,我们本意不是这个意思,只是为了举例)。所以也就是降低一些神经元的“非线性”操作。
那怎么降低神经元的“非线性”操作呢?尽量让激活函数更多地在相对线性的区域实现激活,而不是大量地去非线性区域激活。而 L1 L2 正则化这里,不就是在“惩罚”过大的权重吗,就是说权重一旦过大去非线性激活区域了,模型就会更复杂表达能力更强,我就惩罚它。当然这里的惩罚是逐步的,不会因噎废食,而且参数也还可以调整。总之,直观来讲,正则能够让模型变得更简单(非线性表达能力降低一些)。
Dropout 正则化
随机失活,其实不也是让模型中的单元随机地“偷懒”一下,也相当于让模型变得更简单一点了。随机失活也能让特征的组合和变化更泛化一些,保留“好特征”,而不过度关注“冗余特征”。而且 dropout 相当于用两倍(如果 keepprob 为 0.5 的话)的时间,拿到了集成学习的效果。
理解 Dropout
不能依赖特定的任何特征,因为每个都有可能会被失活。每层的 keep prob 可以是不一样的。在视觉任务上,dropout 用得很多,因为输入的是像素点嘛,太多太细节了。
dropout 的缺点是 cost function 不再明确地定义,所以画不出来逐渐递减的 cost function 函数变化曲线。可以先不设置 dropout 检查曲线,然后再打开 dropout。
其他正则化方法
扩增数据;
提前停止 early stopping,但是你也就没办法继续降低 cost functio 优化模型了。
归一化输入
能够让各个特征之间的尺度一致,对应的 cost function 也更接近“圆”而不是狭长的“椭圆”(很容易震荡),会让学习变得更简单有效。
梯度消失与梯度爆炸 & 神经网络的权重初始化
权重过大或者过小,经过逐层累乘之后,就会很快爆炸或者消失,还没来得及学到任何东西。
随机初始化权重,可以一定程度上避免梯度问题。 因为在最开始的时候,你可以设定每层的权重的分布,让每层的权重接近 1 ,既不要太大也不要太小,这样让权重变化得不要那么快,从而保证足够的时间去学习。同理,好的初始化也能加速学习。
梯度的数值逼近
检查梯度,通过 f ( θ + ϵ ) − f ( θ − ϵ ) 2 ϵ ≈ g ( θ ) \frac{f(\theta + \epsilon) - f(\theta - \epsilon)}{2\epsilon} \approx g(\theta) 2ϵf(θ+ϵ)−f(θ−ϵ)≈g(θ) 来估计 θ \theta θ 处的导数(逼近值)
梯度检验
经验值,差异应该在 e-7,如果有 e-3 甚至以上,就要怀疑有 bug。
关于梯度检验实现的注记
- 梯度检验只在 debug 时使用,训练过程不需要(耗时);
- 如果检验失败了,同时检查检验代码以及网络 bug 哈哈哈;
- 记得添加正则化项;
- 不要和 dropout 一起;
- 几率很小:梯度仅在参数较小时正确,后面就出现错误……所以就后面再检验一次。
Mini-batch 梯度下降法
batch gradient descent 指的是整个训练集全部一起处理,然后进行一次权重更新, 一个 epoch 只更新一次;
mini-batch gradient descent 指的是切分成很多小子集,一次只算一个小子集,就进行一次权重更新,一个 epoch 更新多次。
理解 mini-batch 梯度下降法
mini-batch size 的大小:
- 过大,更新得很慢;
- 过小,震荡很厉害,可能在最优值附近却很难接近;
- 适中,很好的向量化加速 + cost function 下降噪声小一点。
指数加权平均
关于指数加权平均这里,主要是为了后面介绍优化算法做铺垫。虽然我们现在知道随机梯度下降就可以帮助模型进行学习和优化,但是它还是不够“快”。此处的“快”更应该说成是“有效”,也就是进行更有效的学习,比如同样的 100 step,不同的优化算法能达成的效果是不一样的。
随机梯度下降(指 mini-batch 版本)主要存在的问题是,我们每次随机选择的 mini-batch 内数据的分布具有一定随机性,所以每个 mini-batch 对模型参数的更新也是有随机性的。这种更新方向的随机性,使得模型参数更新在“垂直”于梯度的方向也有分量,这样你就只能比较小心地使用学习率。因为一旦把学习率设置得过大,参数更新都“飞出去”了(如下图)。那么此时最优的情况,就是它以较小的学习率“达到终点”(那就不错了)。
好了,铺垫就到此为止,来看下基础指数加权平均。
理解指数加权平均
指数加权平均的偏差修正
动量梯度下降法 momentum gradient descent
到这里,刚刚所说的指数加权平均就可以用上了。其实前面也提到了,我们用 mini-batch 应用梯度下降法的时候,每个 mini-batch 计算的梯度都是有一定随机性的,就像每天的气温一样,即使有大的季节走势,但是仍然有随机性。这种随机性使得学习率的设置范围非常的狭窄,一旦过大,将会恶性震荡无法继续优化。学习率一旦降低,自然训练过程就会变长。有没有什么办法能消除 mini-batch 之间的随机性(噪声)呢?就像消除几天气温之间的“噪声”一样,那就是前面说的指数加权平均。
平均之后,mini-batch 之间的随机性降低了,就可以取到多个 mini-batch 的统一共性,也就是向着预期方向去更新。这个时候,每次更细都会相对“乖”一点,因此也就可以把步子迈的大一点,就可以更快地到达目的了。
总结来讲,就是将指数加权平均应用到 mini-batch 的梯度上,用加权平均后的梯度来更新权重,学习过程会更“稳重”,学习率得以设置得更大,从而进行更快的学习。
之前的 w 和 b 的更新可以写作:
w
:
=
w
−
α
∗
d
w
w := w - \alpha * dw
w:=w−α∗dw 和
b
:
=
b
−
α
∗
d
b
b := b - \alpha * db
b:=b−α∗db;
而在 w 和 b 的梯度上应用指数加权平均有:
v
d
w
=
β
∗
v
d
w
+
(
1
−
β
)
∗
d
w
v_{dw} = \beta * v_{dw} + (1 - \beta) * dw
vdw=β∗vdw+(1−β)∗dw 和
v
d
b
=
β
∗
v
d
b
+
(
1
−
β
)
∗
d
b
v_{db} = \beta * v_{db} + (1 - \beta) * db
vdb=β∗vdb+(1−β)∗db。
那么现在 w 和b 的更新可以写作:
w
:
=
w
−
α
∗
v
d
w
w := w - \alpha * v_{dw}
w:=w−α∗vdw 和
b
:
=
b
−
α
∗
v
d
b
b := b - \alpha * v_{db}
b:=b−α∗vdb。
单纯地对梯度进行指数加权平均不会训练变快,但是平均后为学习率提供了增长空间,因此可以更快。
这里也一般不用偏差修正,因为也就前面初期会偏离一点,后面自己就好了。一般超参数
β
=
0.9
\beta = 0.9
β=0.9。
从类比物理概念上,可以认为
d
w
dw
dw 微分项提供了加速度,所以会越走越快;而
v
d
w
v_{dw}
vdw 可以类比为速度,
β
\beta
β 是摩擦力。所以会越走越快,但却不会完全失控。
RMSprop root mean square prop
仅仅拿 w 和 b 举例而已,实际可能是高维空间的众多参数之间的关系。假设我们希望更新的方向是 w,这个方向比较慢,我们希望它更快一点;而“垂直”方向是 b(在震荡),我们希望它“安静”一点,慢一点。那么 d w dw dw 相对较小, d b db db 相对较大(此处的相对并不一定是 w 和 b 相比,而是实际和我们预期的相比)。
仍然沿用指数加权平均的思想,但是不再针对
d
w
dw
dw 而是微分项的平方
d
w
2
dw^2
dw2。
s
d
w
=
β
∗
s
d
w
+
(
1
−
β
)
∗
d
w
2
s_{dw} = \beta * s_{dw} + (1 - \beta) * dw^2
sdw=β∗sdw+(1−β)∗dw2
s
d
b
=
β
∗
s
d
b
+
(
1
−
β
)
∗
d
b
2
s_{db} = \beta * s_{db} + (1 - \beta) * db^2
sdb=β∗sdb+(1−β)∗db2
w
:
=
w
−
α
d
w
s
d
w
w := w - \alpha \frac{dw}{\sqrt{s_{dw}}}
w:=w−αsdwdw(除以较小项的开方,得到更大的更新)
b
:
=
b
−
α
d
b
s
d
b
b := b - \alpha \frac{db}{\sqrt{s_{db}}}
b:=b−αsdbdb (除以较大项的开方,得到更小的更新)
应用 RMSprop 前后的区别,如下图所示(从蓝色变成绿色,其实就是在压制纵轴,增长横轴):
但是效果是类似的,同样是能够让整体的步伐更“稳定”,这样就能增加学习率。(跟动量法相比,这里应该是提高了每个 step 的效率)
Adam 优化算法 adaptive momentum estimation
动量法有点去噪的意思,RMSprop 有点拖拽的意思,而 Adam 是两者的结合。
学习率衰减
α
=
1
1
+
d
e
c
a
y
r
a
t
e
∗
e
p
o
c
h
∗
α
0
\alpha = \frac{1}{1 + decayrate * epoch} * \alpha_0
α=1+decayrate∗epoch1∗α0,比如 decay rate 可以设置成 1,学习率会越来越小。
一般来说,学习率衰减不是首要解决或者考虑的问题,一般都是先选好学习率之后,在后面的模型参数更新过程中,看效果和情况再考虑增加学习率衰减。
局部最优的问题
马要跳出来了哈哈哈。
由于维度的问题,一般神经网络所说的局部最优解(右图鞍点)其实不是我们平时说的局部最优解(左图局部最小值)。
调试处理
- 学习率
- momentum 中的 β \beta β 、hidden units、mini-batch size
- layers、learning rate decay
- 不要用方格,用随机,因为很多时候你不知道哪个更重要,所以随机可以提供更“大”的搜索空间,整体遵从由粗到细。
为超参数选择合适的范围
当你明确了你要探索的参数范围之后,不同的超参数,step 是不一样的,有些超参数自带指数或者对数属性。比如 学习率 0.001 到 1,不能均匀分布,否则的话 90% 探索 0.1 到 1 之间。
超参数训练的实践
算力不足 vs 算力充沛
正则化网络的激活函数
将 BatchNorm 拟合进神经网络
BatchNorm 为什么奏效
测试时的 Batch Norm
这部分有更详细的记录在BatchNorm:本意只是来加速训练的,而正则化是一顺手的事儿。