作者: 大树先生
博客: http://blog.csdn.net/koala_tree
知乎:https://www.zhihu.com/people/dashuxiansheng
GitHub:https://github.com/KoalaTree
2017 年 09 月 28 日
以下为在Coursera上吴恩达老师的DeepLearning.ai课程项目中,第二部分《改善深层神经网络:超参数调试、正则化以及优化》第一周课程“深度学习的实践方面”关键点的笔记。因为这节课每一节的知识点都很重要,所以本次笔记几乎涵盖了全部小视频课程的记录。同时在阅读以下笔记的同时,强烈建议学习吴恩达老师的视频课程,视频请至 Coursera 或者 网易云课堂。
同时我在知乎上开设了关于机器学习深度学习的专栏收录下面的笔记,方便在移动端的学习。欢迎关注我的知乎:大树先生。一起学习一起进步呀!^_^
对于一个需要解决的问题的样本数据,在建立模型的过程中,我们会将问题的data划分为以下几个部分:
训练集(train set):用训练集对算法或模型进行训练过程;
验证集(development set):利用验证集或者又称为简单交叉验证集(hold-out cross validation set)进行交叉验证,选择出最好的模型;
测试集(test set):最后利用测试集对模型进行测试,获取模型运行的无偏估计。
在小数据量的时代,如:100、1000、10000的数据量大小,可以将data做以下划分:
通常在小数据量时代,以上比例的划分是非常合理的。
但是在如今的大数据时代,对于一个问题,我们拥有的data的数量可能是百万级别的,所以验证集和测试集所占的比重会趋向于变得更小。
验证集的目的是为了验证不同的算法哪种更加有效,所以验证集只要足够大能够验证大约2-10种算法哪种更好就足够了,不需要使用20%的数据作为验证集。如百万数据中抽取1万的数据作为验证集就可以了。
测试集的主要目的是评估模型的效果,如在单个分类器中,往往在百万级别的数据中,我们选择其中1000条数据足以评估单个模型的效果。
对于下图中两个类别分类边界的分割:
从图中我们可以看出,在欠拟合(underfitting)的情况下,出现高偏差(high bias)的情况;在过拟合(overfitting)的情况下,出现高方差(high variance)的情况。
在bias-variance tradeoff 的角度来讲,我们利用训练集对模型进行训练就是为了使得模型在train集上使 bias 最小化,避免出现underfitting的情况;
但是如果模型设置的太复杂,虽然在train集上 bias 的值非常小,模型甚至可以将所有的数据点正确分类,但是当将训练好的模型应用在dev 集上的时候,却出现了较高的错误率。这是因为模型设置的太复杂则没有排除一些train集数据中的噪声,使得模型出现overfitting的情况,在dev 集上出现高 variance 的现象。
所以对于bias和variance的权衡问题,对于模型来说是一个十分重要的问题。
几种不同的情况:
以上为在人眼判别误差在0%的情况下,该最优误差通常也称为“贝叶斯误差”,如果“贝叶斯误差”大约为15%,那么图中第二种情况就是一种比较好的情况。
High bias and high variance的情况
上图中第三种bias和variance的情况出现的可能如下:
没有找到边界线,但却在部分数据点上出现了过拟合,则会导致这种高偏差和高方差的情况。
虽然在这里二维的情况下可能看起来较为奇怪,出现的可能性比较低;但是在高维的情况下,出现这种情况就成为可能。
在训练机器学习模型的过程中,解决High bias 和High variance 的过程:
在大数据时代,深度学习对监督式学习大有裨益,使得我们不用像以前一样太过关注如何平衡偏差和方差的权衡问题,通过以上方法可以使得再不增加另一方的情况下减少一方的值。
利用正则化来解决High variance 的问题,正则化是在 Cost function 中加入一项正则化项,惩罚模型的复杂度。
加入正则化项的代价函数:
其中 λ 为正则化因子。
注意:lambda
在python中属于保留字,所以在编程的时候,用“lambd”代表这里的正则化因子 λ 。
加入正则化项的代价函数:
其中 ||w[l]||2F=∑i=1n[l−1]∑j=1n[l](w[l]ij)2 ,因为 w 的大小为 (n[l−1],n[l]) ,该矩阵范数被称为“Frobenius norm”
Weight decay
在加入正则化项后,梯度变为:
则梯度更新公式变为:
代入可得:
假设下图的神经网络结构属于过拟合状态:
对于神经网络的Cost function:
加入正则化项,直观上理解,正则化因子 λ 设置的足够大的情况下,为了使代价函数最小化,权重矩阵 W 就会被设置为接近于0的值。则相当于消除了很多神经元的影响,那么图中的大的神经网络就会变成一个较小的网络。
当然上面这种解释是一种直观上的理解,但是实际上隐藏层的神经元依然存在,但是他们的影响变小了,便不会导致过拟合。
数学解释:
假设神经元中使用的激活函数为 g(z)=tanh(z) ,在加入正则化项后:
当 λ 增大,导致 W[l] 减小, Z[l]=W[l]a[l−1]+b[l] 便会减小,由上图可知,在 z 较小的区域里, tanh(z) 函数近似线性,所以每层的函数就近似线性函数,整个网络就成为一个简单的近似线性的网络,从而不会发生过拟合。
Dropout(随机失活)就是在神经网络的Dropout层,为每个神经元结点设置一个随机消除的概率,对于保留下来的神经元,我们得到一个节点较少,规模较小的网络进行训练。
首先假设对 layer 3 进行dropout:
keep_prob = 0.8 # 设置神经元保留概率
d3 = np.random.rand(a3.shape[0], a3.shape[1]) < keep_prob
a3 = np.multiply(a3, d3)
a3 /= keep_prob
这里解释下为什么要有最后一步:a3 /= keep_prob
依照例子中的keep_prob = 0.8 ,那么就有大约20%的神经元被删除了,也就是说 a[3] 中有20%的元素被归零了,在下一层的计算中有 Z[4]=W[4]⋅a[3]+b[4] ,所以为了不影响 Z[4] 的期望值,所以需要 W[4]⋅a[3] 的部分除以一个keep_prob。
Inverted dropout通过对“a3 /= keep_prob”,则保证无论keep_prob设置为多少,都不会对 Z[4] 的期望值产生影响。
Notation:在测试阶段不要用dropout,因为那样会使得预测结果变得随机。
另外一种对于Dropout的理解。
这里我们以单个神经元入手,单个神经元的工作就是接收输入,并产生一些有意义的输出,但是加入了Dropout以后,输入的特征都是有可能会被随机清除的,所以该神经元不会再特别依赖于任何一个输入特征,也就是说不会给任何一个输入设置太大的权重。
所以通过传播过程,dropout将产生和L2范数相同的收缩权重的效果。
对于不同的层,设置的keep_prob
也不同,一般来说神经元较少的层,会设keep_prob
=1.0,神经元多的层,则会将keep_prob设置的较小。
缺点:
dropout的一大缺点就是其使得 Cost function不能再被明确的定义,以为每次迭代都会随机消除一些神经元结点,所以我们无法绘制出每次迭代 J(W,b) 下降的图,如下:
使用Dropout:
对数据集特征 x1,x2 归一化的过程:
由图可以看出不使用归一化和使用归一化前后Cost function 的函数形状会有很大的区别。
在不使用归一化的代价函数中,如果我们设置一个较小的学习率,那么很可能我们需要很多次迭代才能到达代价函数全局最优解;如果使用了归一化,那么无论从哪个位置开始迭代,我们都能以相对很少的迭代次数找到全局最优解。
如下图所示的神经网络结构,以两个输入为例:
这里我们首先假定 g(z)=z,b[l]=0 ,所以对于目标输出有:
上面的情况对于导数也是同样的道理,所以在计算梯度时,根据情况的不同,梯度函数会以指数级递增或者递减,导致训练导数难度上升,梯度下降算法的步长会变得非常非常小,需要训练的时间将会非常长。
在梯度函数上出现的以指数级递增或者递减的情况就分别称为梯度爆炸或者梯度消失。
以一个单个神经元为例子:
由上图可知,当输入的数量 n 较大时,我们希望每个 wi 的值都小一些,这样它们的和得到的 z 也较小。
这里为了得到较小的 wi ,设置 Var(wi)=1n ,这里称为Xavier initialization。
对参数进行初始化:
WL = np.random.randn(WL.shape[0],WL.shape[1])* np.sqrt(1/n)
这么做是因为,如果激活函数的输入 x 近似设置成均值为0,标准方差1的情况,输出 z 也会调整到相似的范围内。虽然没有解决梯度消失和爆炸的问题,但其在一定程度上确实减缓了梯度消失和爆炸的速度。
不同激活函数的 Xavier initialization:
其中n是输入的神经元个数,也就是 n[l−1] 。
使用双边误差的方法去逼近导数:
由图可以看出,双边误差逼近的误差是0.0001,先比单边逼近的误差0.03,其精度要高了很多。
涉及的公式:
下面用前面一节的方法来进行梯度检验。
因为我们的神经网络中含有大量的参数: W[1],b[1],⋯,W[L],b[L] ,为了做梯度检验,需要将这些参数全部连接起来,reshape成一个大的向量 θ 。
同时对 dW[1],db[1],⋯,dW[L],db[L] 执行同样的操作。
进行如下图的梯度检验:
判断 dθapprox≈dθ 是否接近。
判断公式:
本周(Week4)的课后编程题请参见:
吴恩达Coursera深度学习课程 DeepLearning.ai 编程作业(2-1)