Improving Deep Neural Networks: Hyperparameter tuning, Regularization and Optimization
目录
Improving Deep Neural Networks: Hyperparameter tuning, Regularization and Optimization
setting up your Machine Learning Application
Regularizing your neural network
setting up your optimization problem
这是deeplearning.ai专题的第二个模块的笔记。
在第一部分,吴恩达老师讲解了如何构建一个神经网络,这部分是从实际应用的角度出来怎么提高神经网络的效率。从超参数调优,正则化,数据准备到怎么优化算法让运行速度变快。这些技巧可以确保正确的实现神经网络。
setting up your Machine Learning Application
在训练神经网络的时候要考虑很多的因素:
- 神经网络将有多少层
- 每一层有多少神经元
- 学习率设置
- 等等
作为一个萌新,我一开始可能思考不过来这些问题,对于我来说最直接有效的方式就是根据自己的要解决的问题(比如说是分类、分割、定位识别等)寻找有效的解决方式,我现在接触的是tensorflow,(还有很多流行的深度学习框架)所以就去官网的modelzoo上寻找符合自己目标的预训练模型,跑一下自己的数据集,并在次基础上做finetune。这是我觉着最有效的了解解决问题的方式。
所以最开始要准备一个数据集,有了数据集才可以开始后续工作,数据集又要划分成training set(训练集)、testingset(测试集)、holding-on cross validation set(交叉验证集)/developing set等。简称为train/dev/test sets。
划分数据集后就是用训练集训练我们的算法,用我们的交叉验证集来验证哪个模型表现在验证集上表现的最好,找到这个最好的模型之后既可以在测试集上进行评估这个模型。可以保证在评估模型时不引入偏差。
那么一般是怎么划分数据集的呢?
- 从小数据到大数据转变后划分比例的变化
在传统的机器学习时代,通常的比例为训练集和数据集分别占整体数据的70%和30%。如果设定了交叉验证集,与测试集和训练集的比例为20%、20%、60%。当数据集的样本数为100、1000、10000时这些比例都是合适的。在大数据时代,这个会稍有变化,我们要处理的数据集可能有100万个训练样本,devset和testset只要有一万个样本就够了。也就是当数据集的样本数非常大的时候,devset和testset在总体数据的比例就变小了。devset的目的就是能够评估哪种模型最好就够了,测试集的作用是对训练好的分类器的性能给出可信度较高的评估。所以当样本数非常大的时候,比例为98/1/1。样本数多于100万时分割比率可能会变成99.5/0.25/0.25%或者99.5/0.4/0.1%。
- 训练集和测试集的数据分布不匹配
测试集和训练集的数据分布不匹配的时候,建议确保测试集和交叉验证集(devset)的数据分布相同
比如说当构建一个可以识别猫的应用的时候,可能我们大部分训练的采用的网页上爬取的高分辨率的图片,用户上传的比较随意的手机糊照,这就可能造成两种不同的分布。解决办法是dev和test的分布相同。这样做的原因是devset要对许多不同的模型进行评估,进而取改善模型在devset上的性能。
- 没有测试集也是可以的
测试集是进行无偏估计来评价最终选取的网络的性能,如果不需要无偏估计的话只有交叉验证集没有测试集也是可以的。如果只有训练集和交叉验证集的情况时,所做的工作就是用训练集尝试不同的模型结构,用交叉验证集进一步的进行评估,根据评估结果进行迭代,目的是找到一个效果好的模型,由于模型也拟合了交叉验证集中的数据,就不能用交叉验证集做无偏估计。一般在没有测试集的情况下,很多时候喜欢把交叉验证集叫做“测试集”。虽然名为测试集,其实干的是交叉验证集的工作。
在正确的数据集划分,可以迭代的更快,更高效的计算算法存在的方差和偏差,就能更高效的选用适当的方法来改进算法。
对于bias(偏差)和variance(方差)的理解
很多机器学习的大牛对bias(偏离度)、variance(集中度)的处理都很有经验。我感觉对我来说了解很容易,精通是难如登天。虽然在深度学习领域对于bias-variance trade-off(偏差-方差困境/权衡)的讨论比较少。一般只是讨论方差和偏差。
如图所示,利用直线来分类下面的数据,逻辑回归的分类情况如蓝色的线所示。
对于欠拟合的情况我们一般也称为高偏差。太过于完美的拟合所有的数据,也就是过拟合,是高方差的分类器
上图是只有两个特征的情况,横轴标为x1,纵轴标为x2。此时可以降偏差和方差可视化,高纬度的情况下,无法将数据绘制在图上并形成可视化的决策边界。
偏差和方差的含义到底是什么?
对猫进行分类,前提是假设人工识别的误差为0%,人可以直接在辨识出图片上的动物是不是猫。
set error | 1 | 2 | 3 | 4 |
train set error | 1% | 15% | 15% | 0.5% |
dev set error | 11% | 16% | 30% | 1% |
高方差 | 高偏差 | 高方差 高偏差 | 刚刚好 |
1、训练集误差较小模型,但交叉验证集误差较大,对训练集的处理较好,对于交叉验证集处理的不尽人意,这种可能是模型在训练集过拟合,在验证集的泛化能力不是很好。我们将它定义为高方差的情况。也就是通过观察训练集和交叉要验证集的误差,可以判断模型是否有高方差的情况。
2、训练集误差为15%,交叉验证集误差为16%,首先在和人工识别误差相比,对训练集处理的不是很好,也就是欠拟合,我们认为这个算法是高偏差,交叉验证集的误差还算可以,因为只比训练集误差多了1%。这个算法的问题是不能对训练集的样本很好的识别,问题为高偏差。
3、训练集误差15%,没有将训练集处理好,算法问题是高偏差。此时交叉验证集的误差更糟糕,是30%。算法的问题是高方差。
4、我们最希望看到的情况,低偏差、低方差。刚刚好的情况
在理解方差和偏差含义之后,如何清晰的诊断出机器学习中的方差偏差问题,并采取正确的办法来解决问题?
如图所示,首先判断在训练集上是不是欠拟合,也就是第一步先判断模型是不是子啊训练集上表现不好,如果不好的话,要考虑更换一个有更多隐层或者隐层单元的网络(增加网络的深度、宽度),训练时间更长,让模型更加的收敛,采用高级的优化算法来解决欠拟合的问题,当偏差在可接受的程度内后,在dev set上判断是否高方差,也就是看一下泛化能力,是不是过拟合,如果存在高方差的情况,可以增大数据量、采取正则化。这样循环往复达到满意的效果。
比如有高偏差的问题,增大数据量,可能不是有效的办法。所以要明确是存在高偏差、高方差,还是两者都存在,才是有效解决问题的第一步。
之前提到在深度学习时代以前,容易存在bias-variance trade-off,在减小偏差的时候会增大方差,反之亦然。
在深度学习一般不会出现这样的情况,在增加网络的深度、宽度,会减小偏差而不增加方差。在增加数据量或采用正则化会减小方差而不会 增大方差。这种就是能够单独减小方差或偏差,却不会过多的影响另外一个指标。这也算是为什么深度学习在监督学习中很有用。也可以解释为什么深度学习中bias-variance trade-off不是很明显。
采取正则化可能会使偏差增大一点点,在网络足够大时增加的不是很多。所以采用正则化训练一个很大的网络并没有缺点,唯一的代价就是计算时间。
Regularizing your neural network
正则化
想要改变神经网络过拟合(存在高方差问题),首先尝试正则化,虽然获取更多的数据也是一种可靠的解决方法。但是实际工业中可能获取数据的代价太大。使用正则化就是解决高方差问题的常用手段。正则化可以有效的防止过拟合,减小误差。
为什么正则化能够减少过拟合呢?
为什么用于正则化的dropout表现这么好?
(1)从神经网络的角度来说,dropout会让神经元随机失活,每一次迭代都会在一个更小的神经网络中计算,这样使用更小的神经网络就能改善过拟合的现象,具有正则化的效果。
(2)从单一神经元的角度来说,因为dropout这种随机丢弃的神经元的举动,使得神经元不能依赖任何一个特征,也就不会把太多的权重都放在某一个上 ,会对于每个输入都给一个较小的权重,神经元以这种方式来泛化权值,更有利于亚索这些权重的平方范数(平方和)与L2正则类似,收缩权值来防止过拟合。
dropout准确的来说要看做一种自适应的模式,而L2正则对于不同权值的惩罚方式有所不同,取决于被激活的乘方的大小。总之,dropout可以起到和L2正则类似的效果。只是针对不同的情况L2正则有少许的变化,试用范围更广。
使用dropout需要注意:
图中的神经网络有3个输入,四个隐层,每个隐层的单元数分别为7\7\73\2\1,在确定使用dropout是要确定一个参数是keep-prob(留存率)。表示的是网络中神经元不失活的概率,可以对每一层设定不同的keep-prob(在这里我理解为dropout可以在神经网络的任何层使用,只不过在隐层单元不多的情况下将keep-prob设置为1.0)在输入特征的时候也可以采用dropout,一般设置为1.0或0.9,但一般不超过0.5。
在容易发生过拟合的层可以设定一个较低的留存率,这样个性化的服务虽然从理论层面上是过有更好的效果,但是在进行交叉验证的时候会有很多的超参数(不同数值的留存率)。另外一个选择就是对一些层使用相同的keep-prob,这样就只有一个超参数。
在这里吴恩达老师提出一个使用时的注意事项,dropout在计算机视觉领域应用非常广泛,因为在计算机视觉领域的输入层的向量维度很大,因为要包含每个图像的像素点。所以dropout才会使用很频繁,但是它只是一种正则化技术,改善过拟合的现象,如果网络没有过拟合,是不需要使用dropout的。此外还有一个缺点就是让代价函数变得不明确。无法用绘图的方式来观察梯度下降是否工作,这里会先把keep-prob设为1,确保代价函数是单调递减的,再打开dropout,并且期望没有引入别的错误。需要采用绘图以外的方法来确认代码执行无误。
other regularization methods
(1)数据扩增
数据扩增可以作为一种正则化技术,准确的说接近正则。
如果在训练数据时发生过拟合,可以增加训练数据,扩大数据集在现实工业中代价比较大,有时无法获取更多的数据,如下图这样处理图片可以增加数据量,虽然这样的效果不如全新的数据,这种方法还是在节约成本的同时也起一定的作用。
(2)early stopping
上图为在运行梯度下降时,关于train set和error set误差的曲线图。理想状态下代价函数的是递减的,Dev set 上的对数损失函数(log loss)通常会新下降后上升。early stopping所做的就是选取dev set中损失最小所对应的值。
之所一选取损失最小的值,在训练初始,由于参数随机初始化,w的值是接近于零的,随着迭代次数的增加,w的值不断增加,在训练时间足够长的时刻w的值会很大。early stopping做的就是停留在权重不大不小的时刻,与L2正则很类似,理想的情况下就可以减少过拟合。
early stopping也有一个缺点,将优化代价函数和防止过拟合这两个任务结合了,如果提早的停止了梯度下降,就意味着过早的打断优化代价函数,一个工具解决两个问题,会很复杂。
setting up your optimization problem
Normalizing inputs
Vabishing/Exploding gradients(梯度消失与梯度爆炸)
梯度消失、梯度爆炸是在训练层数非常多的神经网络时,损失函数的斜率或者导数有时候会变得非常大,或者非常下,甚至是呈现指数级的减小。
如图,当训练一个这样层数较多的神经网络,激活函数为,
假设每一个权重矩阵都是
那么忽略掉维数
可以看出激活函数的值是指数型增长的,如果降1.5换成0.5,激活函数的值就是呈指数型下降。代价函数的导数也是同样。
如果权重矩阵比单位矩阵大一点点的话,在很深的神经网络中容易形成激活函数会爆炸。在神经网络里如果激活函数或者梯度指数级的增加或减小,会让训练变得非常的困难。尤其是梯度消失,梯度下降会用很小的步走,梯度下降会用很长时间学习。
针对梯度消失和梯度爆炸的部分解决办法:更好、更细致的初始化你的神经网络
虽然不能完全解决,但是会有一定的帮助