本周将学习如何有效运作神经网络,内容涉及超参数调优,如何构建数据,以及如何确保优化算法快速运行,从而使学习算法在合理时间内完成自我学习。
一、训练,验证,测试集
假设这是训练数据,用一个长方形表示,我们通常会将这些数据划分成几部分,一部分作为训练集,一部分作为简单交叉验证集,有时也称之为验证集,方便起见,就叫它验证集(dev set),其实都是同一个概念,最后一部分则作为测试集。接下来,我们开始对训练执行算法,通过验证集或简单交叉验证集选择最好的模型,经过充分验证,我们选定了最终模型,然后就可以在测试集上进行评估了,为了无偏评估算法的运行状况。在机器学习发展的小数据量时代,常见做法是将所有数据三七分,就是人们常说的 70%验证集,30%测试集,如果没有明确设置验证集,也可以按照 60%训练,20%验证和 20%测试集来划分。这是前几年机器学习领域普遍认可的最好的实践法。
但是在大数据时代,我们现在的数据量可能是百万级别,那么验证集和测试集占数据总量的比例会趋向于变得更小。因为验证集的目的就是验证不同的算法,检验哪种算法更有效,因此,验证集要足够大才能评估,比如 2 个甚至 10 个不同算法,并迅速判断出哪种算法更有效。我们可能不需要拿出 20%的数据作为验证集。比如我们有 100 万条数据,那么取 1 万条数据便足以进行评估,找出其中表现最好的1-2 种算法。同样地,根据最终选择的分类器,测试集的主要目的是正确评估分类器的性能,所以,如果拥有百万数据,我们只需要 1000 条数据,便足以评估单个分类器,并且准确评估该分类器的性能。假设我们有 100 万条数据,其中 1 万条作为验证集,1 万条作为测试集,100 万里取 1 万,比例是 1%,即:训练集占 98%,验证集和测试集各占 1%。对于数据量过百万的应用,训练集可以占到 99.5%,验证和测试集各占 0.25%,或者验证集占0.4%,测试集占 0.1%。
最后一点,就算没有测试集也不要紧,测试集的目的是对最终所选定的神经网络系统做出无偏估计,如果不需要无偏估计,也可以不设置测试集。所以如果只有验证集,没有测试集,我们要做的就是,在训练集上训练,尝试不同的模型框架,在验证集上评估这些模型,然后迭代并选出适用的模型。
二、偏差和方差
左图为高偏差,我们称之为 欠拟合,中间为适度拟合,右边为高方差,我们称之为 过拟合。
判断方法:通过通过分析在训练集上训练算法产生的误差和验证集上验证算法产生的误差来诊断算法是否存在高偏差和高方差:1.如果训练集的误差很小,但验证集的误差较大,则为过拟合,即高方差。2.如果训练集和验证集的误差相差不大,若都有些高则为高偏差;若误差都比较小则为适度。3.若训练集的误差较高,验证集的误差更高,则为方差偏差都较高。
如图所示为偏差和方差 都高的样子。
三、机器学习的基础
初始模型训练完成后,首先要知道算法的偏差高不高。
解决偏差较高的方法:
选择一个新的网络,比如含有更多隐藏层或者隐藏单元的网络,或者花费更多时间来训练网络,或者尝试更先进的优化算法。训练学习算法时,不断尝试这些方法,直到解决掉偏差问题,这是最低标准,反复尝试,直到可以拟合数据为止,至少能够拟合训练集。
当偏差降低到可以接受的数值 ,就可以用验证集训练看方差。
解决方差较高的方法:
1.最好的解决办法就是采用更多数据。
2.正则化
(1)L2正则化
作用原理:在逻辑回归函数中加入正则化,只需添加参数 λ,也就是正则化参数
如图所示,𝜆/2𝑚乘以𝑤范数的平方,𝑤欧几里德范数的平方等于𝑤𝑗(𝑗 值从 1 到𝑛𝑥)平方的和,也
可表示为𝑤𝑇𝑤,也就是向量参数𝑤 的欧几里德范数(2 范数)的平方,此方法称为𝐿2正则化。因为这里用了欧几里德法线,被称为向量参数𝑤的𝐿2范数。
注意:为了方便写代码,在 Python 编程语言中,𝜆是一个保留字段,编写代码时,我们删掉
𝑎,写成𝑙𝑎𝑚𝑏𝑑,以免与 Python 中的保留字段冲突
如何使用该范数实现梯度下降:既然已经增加了这个正则项,现在我们要做的就是给𝑑𝑊加上这一项 𝜆/𝑚×𝑊[𝑙],然后计算这个更新项,使用新定义的𝑑𝑊[𝑙] ,它的定义含有相关参数代价函数导数和,以及最后添加的额外正则项,这也是𝐿2正则化有时被称为“权重衰减”的原因。
为什么正则化有利于预防过拟合 :
1.直觉上理解:如果正则化𝜆设置得足够大,权重矩阵𝑊被设置为接近于 0 的值,直观理解就是把多隐藏单元的权重设为 0,于是基本上消除了这些隐藏单元的许多影响,使这个神经网络变简单了。神经网络变简单了,直觉上来看就不容易发生过拟合。
2.直观上感受:
假设用如图所示的函数做激活函数,如果正则化参数 λ 很大,𝑊就会很小,𝑧也会很小 ,如果𝑧的值在图中红线的范围内,𝑔(𝑧)大致呈线性,每层几乎都是线性的,和线性回归函数一样。而线性函数非常简单,并不是一个极复杂的高度非线性函数,不会发生过拟合。
(2)dropout (随机失活)正则化
1.工作原理
设置消除神经网络中节点的概率,设置完节点概率,我们会消除一些节点,然后删除掉从该节点进出的连线,最后得到一个节点更少,规模更小的网络,然后用 backprop 方法进行训练。如下图:
2.操作步骤
d3 = np.random.rand(a3.shape[0],a3.shape[1])<keep-prob
a3 =np.multiply(a3,d3)(这里是指的元素相乘)
𝑎3/= 𝑘𝑒𝑒𝑝 − 𝑝𝑟𝑜𝑏
为什么要除以𝑘𝑒𝑒𝑝 − 𝑝𝑟𝑜𝑏呢:a3在经过dropout 处理后期望值会改变,改变后的期望值为:k*a3+(1-k)*0=k*a3,其中k为𝑘𝑒𝑒𝑝 − 𝑝𝑟𝑜𝑏。为了保证期望值不变,需要除以𝑘𝑒𝑒𝑝 − 𝑝𝑟𝑜𝑏。那为什么要保证期望值不变呢,因为期望值一致才能保证模型在训练和测试是一致的。
3.为什么dropout能防止过拟合:
每个单元的输入都随时可能被清除,相当于缩减了权重,和𝐿2正则化类似。
注意:dropout 主要应用于计算机视觉领域。
(3)其他
1.数据扩增
假设数据集是一些图片,可以通过翻转,裁剪,缩放图片来增加数据集。
对于光学字符识别,我们还可以通过添加数字,随意旋转或扭曲数字来扩增数据。
2.early stopping
early stopping 要做就是在中间点停止迭代过程,我们得到一个𝑤值中等大小的弗罗贝尼乌斯范数,与𝐿2正则化相似,选择参数𝑤范数较小的神经网络。
四、归一化输入
步骤:
1.零均值(下图左边方程)
2.归一化方差(右边方程)
注意:不论是训练数据还是测试数据,都是通过相同 μ 和𝜎2定义的相同数据转换,其中𝜇和𝜎2是由训练集数据计算得来的。
为什么归一化
归一化使代价函数的图像从细长狭窄变得匀称,这样梯度下降法不论从哪个位置开始都能够更直接地找到最小值 ,而且还可以使用更大的步长,使得代价函数𝐽优化起来更简单快速。
五、梯度消失/梯度爆炸(Vanishing / Exploding gradients)
概念解释
假设你正在训练如下图这样一个极深的神经网络,为了简单起见,假设我们使用激活函数𝑔(𝑧) = 𝑧,也就是线性激活函数,我们忽略𝑏,假设𝑏[𝑙]=0,如果那样的话,输出:𝑦 = 𝑊[𝑙]𝑊[𝐿−1]𝑊[𝐿−2] ... 𝑊[3]𝑊[2]𝑊[1]𝑥
,则
y^也就是等于1.5(𝐿−1)𝑥 ,如果对于一个深度神经网络来说𝐿值较大,那么𝑦^的值也会非常大,实际上它呈指数级增长的,因此对于一个深度神经网络,𝑦的值将爆炸式增长,即梯度爆炸。
相反,如果权重是 0.5,y的值将指数递减,即梯度消失。
解决方案
神经网络的权重初始化:
𝑤[𝑙] = 𝑛𝑝. 𝑟𝑎𝑛𝑑𝑜𝑚. 𝑟𝑎𝑛𝑑𝑛(shape) ∗ np. sqrt( 1/𝑛[𝑙−1])
Relu 激活函数:使用np. sqrt( 2/𝑛[𝑙−1])
tanh 激活函数:使用np. sqrt( 1/𝑛[𝑙−1])
六、梯度检验
作用
确保 backprop 正确实施
步骤
注意事项
1.不要在训练中使用梯度检验,它只用于调试。
2.如果算法的梯度检验失败,要检查所有项,检查每一项,并试着找出 bug。
3.在实施梯度检验时,如果使用正则化,请注意正则项。
4.梯度检验不能与 dropout 同时使用。