目录
4)Why regularization reduces overfitting(理解)
7)Other regularization methods(了解)
9) Vanishing and Exploding gradients
10)Weight Initialization for Deep Networks(重点)
11)Numerical approximation of gradients
13)Gradient Checking Implementation Notes
以下笔记是吴恩达老师深度学习课程第二门课第一周的的学习笔记:Practical aspects of Deep Learning。笔记参考了黄海广博士的内容,在此表示感谢。
1)Train/Dev/Test sets
今天我们可能已经知道:应用深度学习是一个典型的迭代过程。 在建立训练模型的过程中,数据集会被划分为以下几个部分:
- 训练集(train set):用训练集对算法或模型进行训练;
- 验证集(development set):利用验证集(又称为交叉验证集)进行交叉验证,选择出最好的模型;
- 测试集(test set):最后利用测试集对模型进行测试,获取模型运行的无偏估计。
在数据量比较少的时候,如 100、1000、10000 的数据量大小,可以将数据集按照以下比例进行划分:
- 无验证集的情况:70% / 30%;
- 有验证集的情况:60% / 20% / 20%;
而在如今的大数据时代,对于一个问题,我们拥有的数据集的规模可能是百万级别的,所以验证集和测试集所占的比重会趋向于变得更小。验证集的目的是为了验证不同的算法哪种更加有效,所以验证集只要足够大到能够验证大约 10 种算法哪种更好时,就不需要使用 20% 的数据作为验证集。在百万数据中抽取 1 万的数据作为验证集就可以了。
测试集的主要目的是评估模型的效果,如在单个分类器中,往往在百万级别的数据中,我们选择其中 1000 条数据足以评估单个模型的效果。
100 万数据量:98% / 1% / 1%;
超百万数据量:99.5% / 0.25% / 0.25%(或者99.5% / 0.4% / 0.1%)
吴恩达老师在视频中补充到:建议验证集要和训练集来自于同一个分布(数据来源一致),可以使得机器学习算法训练得更快并获得更好的效果。如果不需要用无偏估计来评估模型的性能,则可以不需要测试集。
2)Bias/Variance
偏差(Bias)和方差(Variance)是机器学习领域非常重要的两个概念和需要解决的问题。在传统的机器学习算法中,Bias和Variance是对立的,分别对应着欠拟合和过拟合,我们常常需要在Bias和Variance之间进行权衡。而在深度学习中,我们可以同时减小Bias和Variance,构建最佳神经网络模型。
在欠拟合(underfitting)的情况下,即出现高偏差(high bias)的情况,不能很好地对数据进行分类。
当模型设置的太复杂时,使得模型出现过拟合(overfitting)的情况,在验证集上出现高方差(high variance)现象。
当训练出一个模型以后,如果:
- 训练集的错误率较小,而验证集的错误率却较大,说明模型存在较大方差,可能出现了过拟合;
- 训练集和开发集的错误率都较大,且两者相当,说明模型存在较大偏差,可能出现了欠拟合;
- 训练集错误率较大,且开发集的错误率远较训练集大,说明方差和偏差都较大,模型很差;
- 训练集和开发集的错误率都较小,且两者的相差也较小,说明方差和偏差都较小,这个模型效果比较好。
吴恩达老师在视频中针对偏差和方差问题给出了一些建议:
对于高偏差问题:
- 扩大神经网络规模,如添加隐藏层或隐藏单元数目;
- 寻找合适的网络架构,使用更大的 NN 结构;
- 花费更长时间训练。
对于高方差问题:
- 获取更多的数据;
- 正则化(regularization);
- 寻找更合适的网络结构。
3)Regularization(重点)
正则化是在cost函数中加入一个正则化项,惩罚模型。正则化可以用于解决高方差的问题。
我们先回顾一下之前介绍的Logistic Regression。我们采用的是L2正则化,加入正则化后的cost函数为:
这里我们只对参数进行了正则化处理而不对
处理。因为
为一个常数,相对来说
的维度很大,对模型泛化能力的影响很大。
除了L2正则化之外,还有另一张正则化方法,L1正则化,表达式为:
由于 L1 正则化最后得到 w 向量中将存在大量的 0,使模型变得稀疏化,因此 L2 正则化更加常用 。注意,lambda
在 Python 中属于保留字,所以在编程的时候,用lambd
代替这里的正则化因子。
在深度学习模型中,L2正则化的表达式为:
被称为弗罗贝尼乌斯范数(Frobenius Norm),所以神经网络中的正则化项被称为弗罗贝尼乌斯范数矩阵。
加入正则化之后,我们的梯度下降计算变为:
加入正则化之后新的梯度下降公式变为:
可以看见,权重衰减,所以L2正则化项也被称为权重衰减。
4)Why regularization reduces overfitting(理解)
我们都知道正则化可以有效避免过拟合,但为什么可以避免过拟合呢?我们举例来说明:下面是欠拟合、刚好拟合和过拟合的情况。
假如我们选择了非常复杂的神经网络模型,如上图左上角所示。在未使用正则化的情况下,我们得到的分类超平面可能是类似上图右侧的过拟合。但是,如果使用L2 正则化,当λ很大时,w[l]≈0。w[l]近似为零,意味着该神经网络模型中的某些神经元实际的作用很小,可以忽略。从效果上来看,其实是将某些神经元给忽略掉了。这样原本过于复杂的神经网络模型就变得不那么复杂了,而变得非常简单化了。如下图所示,整个简化的神经网络模型变成了一个逻辑回归模型。问题就从high variance变成了high bias了。
因此,选择合适大小的λ值,就能够同时避免high bias和high variance,得到最佳模型。
数学解释:
假设神经元中使用的激活函数为tanh函数。
在加入正则化项后,当 λ 增大,导致 减小,
便会减小。由上图可知,在 z 较小(接近于 0)的区域里,
tanh(z)
函数近似线性,所以每层的函数就近似线性函数,整个网络就成为一个简单的近似线性的网络,因此不会发生过拟合。
5)Dropout Regularization(重点)
除了L2正则化,还有一种防止过拟合的有效方法:Dropout。dropout(随机失活)是在神经网络的隐藏层为每个神经元结点设置一个随机消失的概率,保留下来的神经元形成一个结点较少、规模较小的网络用于训练。dropout 正则化较多地被使用在计算机视觉(Computer Vision)领域。下图为概率为0.5的Dropout的正则化例子。
Dropout有不同的实现方法,接下来介绍一种常用的方法:Inverted dropout。假设对于第ll层神经元,设定保留神经元比例概率keep_prob=0.8,即该层有20%的神经元停止工作。dl为dropout向量,设置dl为随机vector,其中80%的元素为1,20%的元素为0。在python中可以使用如下语句生成dropout vector:
keep_prob = 0.8 # 设置神经元保留概率
dl = np.random.rand(al.shape[0], al.shape[1]) < keep_prob
al = np.multiply(al, dl)
al /= keep_prob
最后一步al /= keep_prob
是因为 中的一部分元素失活(相当于被归零),为了在下一层计算时不影响
的期望值,因此除以一个
keep_prob
。注意,在测试阶段不要使用 dropout,因为那样会使得预测结果变得随机。
6)Understanding Dropout
Dropout通过每次迭代训练时,随机选择不同的神经元,相当于每次都在不同的神经网络上进行训练,类似机器学习中Bagging的方法,能够防止过拟合。
对于单个神经元,其接收输入特征并输出。但是加入了 dropout 后,输入的特征都存在被随机消失的可能,所以该神经元不会再特别依赖于任何一个输入特征,即不会给任何一个输入特征设置太大的权重。 因此,通过传播过程,dropout 将产生和 L2 正则化相同的收缩权重的效果。
对于不同的层,设置的keep_prob
也不同。一般来说,神经元较少的层,会设keep_prob
为 1.0,而神经元多的层则会设置比较小的keep_prob
。
dropout 的一大缺点是成本函数无法被明确定义。因为每次迭代都会随机消除一些神经元结点的影响,因此无法确保成本函数单调递减。因此,使用 dropout 时,先将keep_prob
全部设置为 1.0 后运行代码,确保 函数单调递减,再打开 dropout。
7)Other regularization methods(了解)
除了L2 正则化和dropout 正则化之外,还有其它减少过拟合的方法。
一种方法是增加训练样本数量。但是通常成本较高,难以获得额外的训练样本。但是,我们可以对已有的训练样本进行一些处理来“制造”出更多的样本,称为data augmentation。例如图片识别问题中,可以对已有的图片进行水平翻转、垂直翻转、任意角度旋转、缩放或扩大等等。如下图所示,这些处理都能“制造”出新的训练样本。虽然这些是基于原有样本的,但是对增大训练样本数量还是有很有帮助的,不需要增加额外成本,却能起到防止过拟合的效果。
还有另外一种防止过拟合的方法:early stopping。将训练集和验证集进行梯度下降时的成本变化曲线画在同一个坐标轴内,当训练集误差降低但验证集误差升高,两者开始发生较大偏差时及时停止迭代,并返回具有最小验证集误差的连接权和阈值,以避免过拟合。这种方法的缺点是无法同时达成偏差和方差的最优。
8)Normalizing inputs
在训练神经网络时,标准化输入可以提高训练的速度。标准化输入就是对训练数据集进行归一化的操作,即将原始数据减去其均值μ后,再除以其方差:
为什么使用标准化输入呢?我们来看下面这幅图:
有图可知,使用标准化输入前后,成本函数的形状有较大改变。
在不使用标准化的成本函数中,如果设置一个较小的学习率,可能需要很多次迭代才能到达全局最优解;而如果使用了标准化,那么无论从哪个位置开始迭代,都能以相对较少的迭代次数找到全局最优解。
9) Vanishing and Exploding gradients
在神经网络尤其是深度神经网络中存在这样一个问题:梯度消失和梯度爆炸。意思是当训练一个层数非常多的神经网络时,计算得到的梯度可能非常小或非常大,甚至是指数级别的减小或增大。这样会让训练过程变得非常困难。假设存在下面这个每层包含两个神经元的深度神经网络:
假定 ,对于目标输出有:
- 对于
的值>1 的情况,激活函数的值将以指数级递增;
- 对于
的值< 1 的情况,激活函数的值将以指数级递减。
对于梯度计算同样。因此,在计算梯度时,根据不同情况梯度函数会以指数级递增或递减,导致训练梯度难度上升,梯度下降算法的步长会变得非常小,需要训练的时间将会非常长。
10)Weight Initialization for Deep Networks(重点)
下面介绍如何改善梯度消失和梯度爆炸这类问题,方法是对权重进行一些初始化处理。、
深度神经网络模型中,以单个神经元为例,该层的输入个数为
,其输出为:
可知,当输入的数量 n 较大时,我们希望每个 的值都小一些,这样它们的和得到的
也较小。
一种方法是在初始化w时,令其方差为
。相应的python伪代码为:
w[l] = np.random.randn(n[l],n[l-1])*np.sqrt(1/n[l-1])
如果激活函数是tanh,一般选择上面的初始化方法。
如果激活函数是ReLU,权重的初始化一般令其方差为
:
w[l] = np.random.randn(n[l],n[l-1])*np.sqrt(2/n[l-1])
至于选择哪种初始化方法因人而异,可以根据不同的激活函数选择不同方法。另外,我们可以对这些初始化方法中设置某些参数,作为超参数,通过验证集进行验证,得到最优参数,来优化神经网络。
11)Numerical approximation of gradients
Back Propagation神经网络有一项重要的测试是梯度检查(gradient checking)。其目的是检查验证反向传播过程中梯度下降算法是否正确。
双边误差求导(即导数的定义):
当 ε 越小时,结果越接近真实的导数,也就是梯度值。可以使用这种方法来判断反向传播进行梯度下降时,是否出现了错误。
12)Gradient checking
介绍完如何近似求出梯度值后,我们将介绍如何进行梯度检查,来验证训练过程中是否出现bugs。
梯度检查首先要做的是分别将全部连接起来,构成一个一维向量
。 这样成本函数就成为
。
同时,对 执行同样的操作得到一维向量
,它和
有同样的维度。
接着利用对每个
计算近似梯度,其值与反向传播算法得到的
相比较,检查是否一致。例如,对于第i个元素,近似梯度为:
计算完所有的近似梯度后,计算
和
的欧氏距离,公式如下:
一般来说,如果欧氏距离越小,例如,甚至更小,则表明反向梯度计算是正确的,没有bugs。
如果欧氏距离较大,例如,则表明梯度计算可能出现问题,需要再次检查是否有bugs存在。
如果欧氏距离很大,例如,甚至更大,则表明梯度下降计算过程有bugs,需要仔细检查。
13)Gradient Checking Implementation Notes
在进行梯度检查的过程中有几点需要注意的地方:
- 不要在训练中使用梯度检验,它只用于debug;
- 如果算法的梯度检验失败,要检查所有项,并试着找出 bug;
- 当成本函数包含正则项时,也需要带上正则项进行检验;
- 梯度检验不能与 dropout 同时使用。因为每次迭代过程中,dropout 会随机消除隐藏层单元的不同子集,难以计算 dropout 在梯度下降上的成本函数 J。建议关闭 dropout,用梯度检验进行双重检查,确定在没有 dropout 的情况下算法正确,然后打开 dropout;
14)Summary
本节课主要介绍了深度学习的实践层面。
首先我们讲了如何配置训练集,验证集和测试集,并如何分析偏差、方差,如何处理欠拟合或过拟合问题;
然后我们介绍了如何在深度神经网络模型中应用不同形式的正则化,如L2正则化和dropout正则化;
最后我们介绍了归一化输入,这可以加快神经网络的训练速度,以及梯度检验。