本周涉及数据集划分、偏差-方差、正则化、dropout、归一化输入、梯度消失与爆炸、权重初始化、梯度检验等内容。
1.1 train / dev / test 训练集、验证集、测试集
训练集 training set:是用来训练模型的
验证集 development set \ dev set:是用来选出哪个模型在dev set上表现最好
测试集 test set:用来对验证选出的模型进行无偏估计
对于小数据量的机器学习(10k左右样本量),常用且有效的分法为:训练集、测试集70%-30%划分,训练集、验证集、测试集60%-20%-20%划分。
对于大数据量的机器学习(百万以上样本量),验证集和测试集的比例就会小很多,如训练集、验证集、测试集98%-2%-2%划分,当数据量更大时为99.5%-0.25%-0.25%、99.5%-0.4%-0.1%
由于深度学习需要的数据量很大,数据的来源也很广泛,因此,很多数据源自不同的分布,但有一条经验法则是:必须保证验证集数据和测试集数据的分布相同。
另外,当不需要无偏估计时,我们可以不要测试集,此时只有训练集和验证集。
1.2 bias / variance 偏差、方差
在深度学习误差中,有关bias-variance trade-off 的讨论越来越少,总是分别考虑bias和variance。具体如下:
high bias –> underfitting
high variance –> overfitting
当样本只有两维特征时,我们尚能通过画出决策面来判断偏差和方差,但当样本维数很高时,要判断模型的bias和variance就要借助其他指标了。理解bias和variance的两个关键数据是train set error与dev set error,通过查看这两个数据来判断算法的偏差和方差情况。以下表数据为例,假设最优误差(贝叶斯误差)很小(接近为0)并且训练集和验证集来自同一分布。表中给出了四种情况下的训练集误差和验证集误差,以及它们的偏差和方差情况。我们首先通过查看train set error与最优误差之间的差异来判断算法的bias,如果train set error与最优误差差异很小,则算法为low bias;如果train set error与最优误差差异差异较大,则算法为high bias。然后再通过比较train set error与dev set error的差异来判断算法的variance,如果dev set error与train set error差异很小,则算法为low variance;如果dev set error与train set error差异较大,则算法为high variance。
train set error | dev set error | 结论 |
---|---|---|
1% | 11% | high variance |
15% | 16% | high bias |
15% | 30% | high bias, high variance |
0.5% | 1% | low bias, low variance |
按照之前的理解,高偏差意味着模型的复杂度不够、数据拟合度低,高方差意味着模型的复杂度过高、数据过拟合。那么,针对上表中第三种情况,一个模型同时具有高偏差和高方差意味着什么呢?想象一下在样本空间中,模型对样本空间中的部分数据拟合程度过低,但又对空间中的其他部分数据拟合程度过高,这样,该模型就同时具有高偏差和高方差。
1.3 basic “recipe” for machine learning 机器学习基础
Andrew Ng 在训练神经网络时会用到的基本方法:初始模型训练完成后,首先通过查看train set error来判断算法的bias高不高,如果算法是high bias,那么尝试有更多hidden layers或hidden units 的更大的网络(通常有用)、花更多的时间来训练网络(不一定有用)、尝试新的神经网络架构(不一定有用),直至偏差降低至可接受的数值。然后,通过查看dev set error来判断算法的variance有没有问题,如果算法是high variance,最好的方法就是采用更多的数据,当无法获得更多数据的时候,可以使用regularization,或者可以尝试其他的神经网络架构。这样不断尝试,直到找到一个low bias、low variance的算法。
1.4 regularization 正则化
当你怀疑模型存在overfitting,那么最应该尝试的方法可能是正则化。另一个解决高方差的方法是准备更多的数据,这也是非常可靠的办法,不过因为种种原因,我们无法获得更多的数据。但是,regularization常有助于防止过拟合。正则化,即在代价函数中加入了正则化项,常见的有
L1
正则化项和
L2
正则化项:
如果使用 L1 正则化,则 w 会变得稀疏。现在在训练神经网络时,越来越多的人学会选择使用
如何在神经网络中实现 L2 正则化呢?
其中,
展开可写为:
此时, dW[l]=(frombackprop)+λmW[l] ,所以 W[l] 在参数更新时,可表示为
因此, L2 norm正则化项又称为 权重衰减(weight decay)。
最后说明一下,在计算正则项时,一般都忽略偏置b的正则项,因为它只是众多参数中的一个,影响很小,当然也可以计算,只是对结果的影响可忽略。
1.5 why regularization reduce overfitting
解释一:
对于包括有正则化项的代价函数
J
我们的目的是让代价函数 J 最小化。考虑一种极端的情况,正则化参数
解释二:
假设激活函数 g(z)=tanh(z) ,当 |z| 取值很小的时候,可认为 g(z) 所对应的部分是线性的。对于含有正则化项的代价函数,当 λ 变大时, W 会变得相对较小,又因为
one implementational tip:
当给代价函数加上正则化项后,画出的代价函数曲线就是随着迭代次数的增加单调递减的。如果画出的代价函数没有正则项,只有第一项,那么画出的代价函数可能不是在所有范围内都单调递减。
1.6 Dropout regularization
除了
L2
正则化外,还有一个非常有用的正则化方法称为dropout(随机失活)。dropout会遍历网络中的每一层,并设置网络中各节点被消除的概率,根据概率消除一些神经元,得到一个神经元更少、规模更小的网络,然后使用back-prop训练模型。对于不同的样本,设置每层中各神经元被消除的概率,消除一些神经元。这样,对于每个样本,都采用一个神经元减少后的网络进行训练。
如何实现dropout呢?
目前最常用的时inverted dropout(反向随机失活)。以神经网络中的第3层来说明如何在某一层神经网络中实现dropout。首先,定义向量
d
,那么
若 keep-prop=0.8 ,则表示消除任意隐藏单元的概率是0.2。因此, d3 的作用就是生成一个随机矩阵。对应的 a3 为
在做上式计算时,python会把true和false翻译为1和0,过滤掉要消除的神经元。最后,还要对 a3 进行 尺度还原
上式被称为inverted dropout technique。为什么要进行上式的操作呢?假设第3层上有50个神经元,因此 a3 是50*1或50*m维的,如果保留和消除神经元的概率分别是80%和20%。此时,再来考虑 z[4] , z[4]=W[4]a[3]+b[4] ,当 a[3] 中有20%的元素置0,即 a[3] 减少了20%,为了不减少 z[4] 的期望值,我们需要用 a[3] 除以0.8来修正消除的20%,这样 a[3] 的期望值就不会改变。inverted dropout的功能就是,无论keep-prop的值是多少, inverted dropout方法通过除以keep-prop,确保 a[3] 的期望值保持不变。
而在测试阶段,我们不需要显式地使用dropout。即,我们只在训练阶段使用dropout。
1.7 understanding dropout
由于dropout会随机消除网络中的一些节点,这样每次迭代时,网络都看起来更小了,而这一效果就和使用了正则化的效果一样。
另外,从单一神经元来看,当使用dropout时,该单元的输入被随机消除,也就是说,该神经元不依赖于任何输入,因为任何输入都有可能被随机消除。这样,与每个输入相关联的权重都比较小,即达到了收缩权重平方范数的效果,与
L2
正则化相似。因此,实现dropout的效果是它能收缩权重,并达到防止过拟合的效果。实现dropout的另一个细节是要设置keep-prob这个超参数的值,它代表每一层上保留单元的比例,因此,keep-prob也可以随着神经层的不同而不同。当担心某一层会出现overfitting时(权重矩阵比较大),就把这一层的keep-prob设置的低一点;当某一层不大可能出现overfitting(权重比重比较小)时,就把keep-prob设置的高一点;当keep-prob设置为1时,该层所有的神经元都会保留,也相当于没有使用dropout。
从技术上讲,我们也可以对输入层使用dropout,这样可以移除一些特征,但通常并不这么做,将keep-prob设置为1是最常用的值,或者设为一个较大的值,如0.9,但是消除一半的特征时不太可能的。
本节课总结:如果担心某些层比较容易发生过拟合,那么就将这一层的keep-prob设置的比较低,这样做的缺点就是,在交叉验证时,超参数的搜索范围比较大,要搜索更多的超参数。另一种可选方法是,在有些层上使用dropout,在有些层上不使用,使用dropout的层只有一个超参数,那就是keep-prob。
dropout在计算机视觉中使用的很多,几乎成了默认的选择。dropout是一种正则化方法,它有助于防止过拟合,因此,除非算法过拟合,不然Ng是不会使用dropout的,所以dropout在其他领域应用很少,主要存在于计算机视觉领域,因为我们没有足够的数据。
dropout的一大缺点就是代价函数
J
不再被很好的定义。每次迭代,都会随机消除一些节点,当我们检查梯度下降的性能时,实际上会发现很困难。而当代价函数被很好定义时,会发现每一次迭代,误差都在降低。这样,我们就失去了调试的工具,画不出代价曲线。这种情况下,Ng通常会先关闭dropout函数,将keep-prob设置为1,运行代码,确保代价函数单调递减,然后再打开dropout函数,这样可以确保在dropout时代码没有引入bug。
1.8 Other regularization methods
- data augmentation 数据扩增
常见于计算机视觉,对图像进行截取、水平翻转、形变等变换操作。 - early stopping
在训练模型时,我们希望模型的训练集误差(train set error),即代价函数J 不断下降,同时,我们还可以得到模型的验证集误差(dev set error)。通常,验证集误差会先下降,然后上升。early stopping的作用就是找到验证集误差最小时所对应的参数 W ,认为这时的W 是模型的最佳参数。
但early stopping还有一个缺点,就是无法独立地处理代价函数优化和过拟合问题。因为提前停止梯度下降,也就是停止了优化代价函数 J (这一点理解的不是太透)。
1.9 normalizing input
归一化输入是能够加速训练网络的一种技巧,需要两步:
(1) 0-均值化
这样,将数据集移动到均值为0的地方。
(2) 归一化方差
这样,数据集就成了0均值、方差为1的分布。
tips:标准化验证集和测试集的 μ 、 σ 与标准化训练集的 μ 、 σ 必须相同。
为什么要归一化输入数据呢?,如下图所示,如果输入X在不同的维度上取值范围不一样,比如 x1 是1-1000, x2 是0-1,那么它们对应的权重尺度也是不同的,这样,没有归一化的代价函数曲面就像一个很扁的碗,在这样一个函数曲面上做梯度下降,会导致在一些权重维度上步长较大,而在另一些权重维度上步长较小,导致梯度下降时来回震荡,学习速度慢等问题。但是,若进行了输入归一化后,代价函数曲面就像一个比较圆的碗,在这样的曲面上进行梯度下降可以保证使算法快速到达最优值附近。
1.10 vanishing/exploding gradients
当深度神经网络很深的时候(即
L
较大时),每层的
1.11 weight initialization for deep networks
1.10说明了什么是梯度消失和梯度爆炸。有一个能部分解决梯度消失/爆炸的方法就是谨慎选择神经网络的随机初始化参数。
首先考虑对一个单一的神经元:
当 n 越大的时候,我们希望
若是relu激活函数:
若是tanh激活函数(Xavier初始化):
或者:
如果想添加其他的方差,那么这个 方差将作为需要调节的另一个超参数。这样就可训练出一个权重或梯度不会过快增长或消失的神经网络。这也是一个加快训练的技巧。
1.12 numerical approximation of gradients
在实施backprop时,有一个测试叫梯度检验,它可以确保backprop的实现是正确的。为了实现梯度检验,首先要了解梯度的数值检验。即,双边差分的精度比单边差分的精度高。所以,在梯度检验时,我们使用双边差分。
1.13 gradient checking
-
神经网络的梯度检验:
将参数
W1
,
b1
,
W2
,
b2
…
WL
,
bL
reshape成一个大的向量
θ
,这样,代价函数
J(W,b)
就变成了
J(θ)
。同样的将
dW1
,
db1
,
dW2
,
db2
…
dWL
,
dbL
以相同的方式reshape成一个大的向量
dθ
。
实施梯度检验:
for each
i
:
dθapprox[i]=J(θ1,θ2,...,θi+ε,...)−J(θ1,θ2,...,θi−ε,...)2ϵ≈dθi 最后判断 dθapprox 与 dθ 是否相近。即,计算下式||dθapprox−dθ||2||dθapprox||2+||dθ||2如果 ε=10−7 :- 当上式比值约为 10−7 或更小,那么这个结果就很好
- 当上式比值在 10−5 以内,这时候就要仔细检查一下
- 当上式比值在 10−3 以内,就会担心有bug。
1.14 gradient checking implementation notes
- 不要再训练时使用梯度检验,它只用于调试
- 如果算法梯度检验失败,要检查所有的成分来确定bug,即,找出是哪一个 dθapprox[i] 与 dθ[i] 相差太大
- 如果使用了正则化,不要忘记正则项
- 梯度检验不能与dropout同时使用。因为在每次迭代时,dropout会随机让隐藏层的神经元消失,这样就难以计算dropout在梯度下降时的代价函数。所以,通常在梯度检验时不进行dropout,即设置keep-prob=1。在确保算法没问题的时候再打开dropout。
- 在随机初始化的过程中,运行梯度检验,然后训练一会儿后,再运行梯度检验。