Improving Deep Neural Networks

在实际应用中如何使得神经网络高效工作包括数据准备、超参调整、优化算法等。

初步建立机器学习模型

(一)数据准备:Train / Dev / Test sets

目前应用机器学习是高度迭代的过程,而恰当地将机器学习任务的数据划分为训练集、开发集和测试集能有效提高迭代效率。其中:

  • Training set:训练模型,尝试不同的模型结构
  • Dev set or hold-out cross validation set:选出不同训练模型中效果最好的
  • Test set:对效果最好的训练模型进行无偏评估,也就是对你最终所选取的模型给出可信度比较高的评价
Previous ML era

对于100/1000/10000级小规模样本时,被广泛认可的分割比例是7/3(未指定开发集)或6/2/2(指定开发集)。

Big data era

对于100万级大规模样本时,开发集和测试集只需1万个就足够进行训练模型的选择和评估,这时分割比例可能就是98/1/1或99.5/0.25/0.25或99.5/0.4/0.1了。

另外,Ng还讲到当前深度学习的一个趋势是越来越多任务的训练集和开发/测试集不匹配。假设说你在构建一个应用,允许用户上传大量图片,你的目标是找出猫的图片再展示给用户。这时一边是你的训练集——可能有很多从网上爬取的图片 ,另一边是开发集和测试集——用户上传的图片。会发现许多网页上的图片都是高分辨率 、专业制作过 、构图也很漂亮的猫的图片; 而用户上传的图则相对比较模糊 、分辨率低 、用手机在更加随意的情况下拍摄的 ,所以这可能就造成两种不同的分布 。 在这种情况下,Ng建议的经验法则是确保开发集和测试集中的数据分布相同。

还有需要注意的是,不需要无偏估计的话,没有测试集也没有问题。

所以当你只有开发集而没有测试集的时候,你所做的就是用训练集尝试不同的模型结构,然后用开发集去评估它们,根据结果进一步迭代并尝试得到一个好的模型 。因为你的模型拟合了开发集中的数据,所以开发集不能给你无偏的估计,但如果你不需要无偏估计的话也许也完全无妨。
在机器学习的世界中如果只有训练集和开发集,而没有单独的测试集的话, 大多数人会将训练集就称为训练集,而把开发集称为测试集。这种提法对术语的使用可能并不完全准确,因为测试集上会发生过拟合现象。

总结: 建立好训练、开发、测试集,模型会迭代得更快,而且还能更高效地测量算法存在的偏差和方差,然后就能选用适当的方法来改进算法。

(二)Bias / Variance

  • 对于如下所示数据的分类:
    在这里插入图片描述
    图中最左边的高偏差 (high bias)分类器导致了数据的欠拟合 (underfitting);图中最右边的高方差 (high variance)分类器导致了数据的过拟合 (overfitting)。而中间的分类器则是恰到好处。
    在上述的2d示例中,只有两个特征 x 1 x_1 x1 x 2 x_2 x2,因此可以直观地绘制数据并可视化方差和偏差。而在高维数据中,无法绘制数据并可视化分割边界,但可以根据训练集误差和开发集误差来帮助理解方差和偏差。

  • 对于如下猫狗图片分类器,假设训练集误差和开发集误差的不同情况:
    在这里插入图片描述
    以上分析是基于人类水平会得到接近 0% 的误差的假设,或者更一般地说,最佳误差 (optimal error), 有时也称为贝叶斯误差(Bayes error)。 如果最佳误差是15%,那上述15%的Train set error和16%的Dev set error则是完全合理的情况。因此,通过查看Train set error,可以告诉你是否有bias问题;再通过从Train set error到Dev set error可以告诉你是否有variance问题;以上都是假设最佳误差相当小,并且训练集和开发集都遵循相同的分布。如果违反了这些假设 ,则要进行更复杂的分析。

什么是贝叶斯误差?可参考知乎链接
简而言之,Bayes error是理论极限达到的最小错误,由于人非常擅长处理图像、音频之类的非结构化数据处理,其处理性能已逼近理论极限,故而常用人在这类事务上处理的error当做是理论上能达到的最小error,这也往往是训练模型力求达到的目标。

  • 高偏差和高方差的情况
    本节第一张图片的最左边和最右边分别展示了高偏差和高方差的情况,下图中的紫色线绘制的分类器则同时具有高偏差和高方差。它具有高偏差的地方主要是线性的,具有高方差的地方则是那些弯折的曲线。

同时高偏差、高方差的情况似乎难以想象。但在高维空间中很容易出现某些区域存在高偏差,某些区域存在高方差的情况。

在这里插入图片描述
总结: 通过查看训练集误差和开发集误差可以诊断它是否存在高偏差或高方差的问题,或者两者都有,或者两者都没有。然后根据机器学习基本准则系统化地提升算法。

(三)Basic Recipe for Machine Learning

当训练好了最初的神经网络时,

  1. 首先是否高偏差 (training data performance)?
    要判断是否存在高偏差,实际上就是要看模型在训练集数据上的表现。如果说模型有高偏差,也就是模型甚至连训练集都不能很好拟合。可尝试如下解决方法:
  • 增加隐藏层或隐藏单元(几乎总是有效)
  • 延长训练时间,让梯度下降运行更长时间或换用一些更高级的优化算法(虽然并不总是有效但也不会造成什么坏处)
  • 找到一种更加适合当前问题的结构 (可能有效可能无效,需要亲自尝试)
  1. 通过迭代将偏差减小到可接受范围后,然后是否存在高方差 (dev set performance )?
    要判断是否存在高偏差,实际上就是要看模型在开发集数据上的表现。看模型是否具备泛化能力,如在训练集上性能良好,当泛化到开发集上时是否仍然性能较好。解决高方差的方法是:
  • 获取更多数据(首选,当然前提是你能获取得到)
  • 正则化(在正则化中存在一点点偏差与方差间的权衡,它可能会使偏差增加一点点,但在你的网络足够巨大时增加得通常不会很多 )
  • 找到更合适的神经网络结构
    在这里插入图片描述
    总结: 在深度学习之前的时代,有许多关于偏差和方差之间取舍的讨论,是因为没有太多那种能够单独减小偏差或单独减小方差而不顾此失彼的工具。但在当前这个深度学习和大数据的时代,则有如以上方法那样可以只减少偏差或只减少方差而不会过多影响另一方。事实上当你有了一个良好的正则化的网络时,训练一个更大的网络几乎从来没有坏处。当训练的神经网络太大时主要的代价只是计算时间只要采取正则化就行。

矫正模型表现

(一)Regularization

正则化通常有助于防止过拟合并降低网络的误差。下面我们来看看正则化是如何实现的。

  1. 逻辑回归:
    回顾逻辑回归训练过程中需要最小化代价函数J,即 m i n w , b J ( w , b ) min_{w,b}J(w,b) minw,bJ(w,b) 。该代价函数定义为每个训练样本的预测损失之和,即 J ( w , b ) = m i n 1 m ∑ i m L ( y ^ ( i ) , y ( i ) ) J(w,b)= min \frac{1}{m} \sum_{i}^{m}L(\hat{y}^{(i)},y^{(i)}) J(w,b)=minm1imL(y^(i),y(i)) w w w b b b是逻辑回归的参数,其中 w ∈ R n x w\in R^{n_x} wRnx w ∈ R w\in R wR。下图为加入 L 2 L2 L2正则化项过程,其中分子 λ \lambda λ为正则化参数,分母 2 m 2m 2m只是一个缩放常量, ∣ ∣ w ∣ ∣ 2 2 ||w||_2^2 w22 L 2 L2 L2范数, ∣ w ∣ 1 |w|_1 w1 L 1 L1 L1范数。
    在这里插入图片描述

问题1: 为什么只对参数 w w w进行正则化呢?为什么不把 b b b的相关项也加进去呢?
答:Ng给出的解释是实际上可以这么做,但是通常会省略掉。因为 w w w往往是一个非常高维的参数矢量,尤其在发生高方差问题的情况下,而 b b b只是单个数字,几乎所有的参数都集中在 w w w上而不是 b b b。所以即使加了 b b b实际上也不会起到太大作用,那在实践中也不会费力气去包含 b b b了,但想加上的话也可以。

问题2:使用 L 1 L1 L1范数还是 L 2 L2 L2范数?
答: L 1 L1 L1正则化会使得 w w w最后会变得稀疏,这意味着w矢量中有很多0。但Ng认为 L 1 L1 L1在压缩模型的作用上不大,在训练模型上 L 2 L2 L2正则化使用得频繁得多。

问题3:如何确定超参 λ \lambda λ
答:通常使用开发集来配置这个参数,通过尝试一系列的值找出最好的那个。即在训练集上得到较好的结果和保持参数的L2范数较小以避免过拟合 之间进行取舍。

  1. 神经网络:
    在这里插入图片描述

∣ ∣ w [ l ] ∣ ∣ 2 为 ||w^{[l]}||^2为 w[l]2称为矩阵的Frobenius范数,而不叫矩阵的 L 2 L2 L2范数,表示矩阵中元素的平方和(具体原因没必要了解)。
神经网络中的 L 2 L2 L2正则化有时也被成为权重衰减 (weight decay)。

(二)Why regularization reduces overfitting

直观上来说, λ \lambda λ设置的足够大的话,为了使代价函数最小,权重参数 w w w就要设置的尽可能小,(接近于简单线性函数),相当于降低了很多神经元的影响,减少过拟合。
数学上来说,这里Ng举了 t a n h tanh tanh的例子。

在这里插入图片描述
由上图所示, λ \lambda λ变大, w w w变小, z z z变小,即 z z z只能在小范围内取值, t a n h ( z ) tanh(z) tanh(z)函数就近似线性,所以整个神经网络就成为一个简单的近似线性网络,而不能计算相对复杂的非线性函数,这样就不太容易过拟合了。

(三)Dropout Regularization

除了 L 2 L2 L2正则化,另一种非常强大的正则化技术是随机失活正则化 (dropout regularization)。首先对网络每一层中的每个节点置一个概率值,决定消除哪些节点。然后清除那些节点上所有正在进行的运算。最后再在这个被简化了很多的网络上进行反向传播训练。上述步骤可以应用于每一个训练样例
下面介绍最常用的dropout实现算法

  • Inverted dropout(反向随机失活)
keep_prob = 0.8
d3 = np.random.rand(a3.shape[0],a3.shape[1]) <keep_prob
a3 /= keep_prob

这里解释下为什么要有最后一步:“a3 /= keep_prob”
如上例中keep_prob = 0.8,那么有20%的神经元被删除了,也就是说a3中有20%的单元被清零了,在下一层计算中z4 = w4a3+b4,为了不影响z4的期望值,所以需要在w4a3的部分除以一个keep_prob。
反向随机失活通过“a3 /= keep_prob”来保证无论keep_prob设置为多少,都不会对z4的期望值产生影响。
注意:不在测试阶段使用dropout,因为在测试阶段做预测的时候 你并不想让你的输出也是随机的。理论上来说可以做的一件事是——用不同的随机失活的神经网络进行多次预测取并平均值,但是这个方法运算效率不高而且会得到几乎相同的预测结果。刚才提到过,反向随机失活有做除以keep.prob的运算,它的作用是保证如果测试过程如果没有针对随机失活算法进行缩放(scaling) ,那么激活函数的期望输出也不会改变。

可以看下:https://blog.csdn.net/andyL_05/article/details/103690560

那为什么dropout可以减缓过拟合呢?

在这里插入图片描述
一方面,每一次迭代都会在一个更小的神经网络中计算 而使用更小的神经网络就好像具有正则化效果;另一方面,从单一神经元的角度来看,它的每一个输入都可能随机失活,所以在特定的时候,就不愿把所有的赌注只放在这一个输入神经元上。因此这个神经元将会更积极的使用这种方式,对于每个输入都给一个比较小的权重,而泛化这些权值将有利于压缩这些权重的平方范数和L2正则化类似,使用dropout有助于收缩权值以及防止过拟合;
在实际使用过程中,一般输入层keep_prob设为1,如果你觉得某一层比其他层更容易发生过拟合,就可以给这一层设置更低的留存率,这样的缺点是在交叉验证 (网格) 搜索时,会有更多的超参数 (运行会更费时) 。另一个选择就是对一些层使用dropout (留存率相同) 而另一些不使用,这样的话就只有一个超参数了。

dropout的一个缺点是让代价函数J 变得不那么明确。因为每一次迭代 都有一些神经元随机失活,所以当你去检验梯度下降算法表现的时候,你会发现很难确定代价函数是否已经定义的足够好 (随着迭代 值不断变小) 这是因为你对代价函数J 的定义不明确或者难以计算。因此就不能用绘图的方法去调试错误了。

(四)Other regularization methods

  • 数据集扩增(data augmentation)
    可以作为一种正则化技术,准确地说是接近正则化。在cv中比如可以图像进行水平翻转、放大和扭曲。
  • 早终止法(early stopping)
    即提前停止模型的训练过程,选取这个(最小)开发集误差所对应的值。但Ng很少用,因为完全可以用正交化(orthogonalization) (指同一时间只考虑一个任务)来分别优化成本函数和避免过拟合。

early stopping的主要缺点就是:它把这两个任务结合了,所以你无法分开解决这两个问题。因为提早停止了梯度下降意味着打断了优化成本函数J的过程。因为现在在降低成本函数J这件事上,你做得就不够好了。同时你又想做到避免过拟合,所以你没有用不同方法来解决这两个问题而是用一个工具解决两个问题,这就意味着你要做的事情考虑起来更复杂了。

如果不用early stopping 可以替代的选择是L2正则化,那么你可以尽可能久的训练神经网络。这样可以让超参数的搜索空间更易分解,也因此更易搜索。但这么做的缺点是,你可能必须尝试大量的正则化参数λ的值,这使得搜索这么多λ值的计算代价很高 。

early stopping的主要优点就是:只要运行一次梯度下降过程,你需要尝试小w值、中等w值和大w值,而不用尝试L2正则化中超参数λ的一大堆值。

加速模型训练的trick

(一)输入归一化

对输入进行归一化是一种加速训练过程的方法。

(二)Vanishing / Exploding gradients

深层的网络会受制于梯度逐渐消失或爆炸的问题,对于权重系数W, 如果只比1大一点点, 或只比单位矩阵大一点点, 那在一个非常深的网络,激活函数就会爆炸。另外如果W只比单位矩阵小一点点,有可能是0.9, 0.9,而你有一个很深的网络, 激活函数就会指数级的减少。 如下所示。在这里插入图片描述
在深层神经网络里, 如果激活函数或梯度作为L的函数指数级的增加或减少,这些值会变得非常大或非常小,这会让训练变得非常困难, 尤其是如果梯度比L要小指数级别, 梯度下降会很用很小很小步的走。 梯度下降会用很长的时间才能学习到。
缓解办法
通过使用适合的方法去初始化权重。下面以单个神经元的例子开始再到深层网络中。
在这里插入图片描述
对于单个神经元,为了不让z项太大或者太小 ,当输入的特征数n比较大,就需要 w i w_i wi的值越小。一个方法就是设置 V a r ( w i ) = 1 n Var(w_i) = \frac{1}{n} Var(wi)=n1(Xavier initialization)。这样,如果激活函数的输入x近似设置均值为0,标准方差是1,输出z也会调整到相似的范围内,虽然这样不能完全解决问题,但它降低了梯度消失和梯度爆炸问题的程度。因为这种做法通过设置权重矩阵W,使得W不会比1大很多,也不会比1小很多。因此梯度不会过快地膨胀或者消失。

常用激活函数的Xavier initialization:
relu: 1 n [ l − 1 ] \sqrt\frac{1}{n^[l-1]} n[l1]1
tanh: 2 n [ l − 1 ] ∗ n [ l ] \sqrt\frac{2}{n^[l-1]*n^[l]} n[l1]n[l]2

(三)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值