改善深层神经网络
学习资料:深度学习课程笔记、deeplearning.ai的《改善深层神经网络》、《python深度学习》
另一篇笔记《结构化机器学习项目》对所有机器学习项目都有帮助,这篇笔记是专门针对神经网络的一些改善方法。
一. 解决过拟合问题
解决过拟合的方向有两个:降低参数空间的维度、降低每个维度上的有效规模。或者还可以从根源上增加数据,使数据更全面,但是收集样本数据和标注往往是代价昂贵的。
降低参数空间的维度:减小模型规模、减少参数、参数共享等;
降低每个维度上的有效规模:正则化、early stopping等。
1. 正则化Regularization
有许多不同的正则化函数,其中介绍了L1 regularizaion、L2 regularization、dropout正则化等,用的比较多的是L2 regularization。
L2 regularization
下图为:L2正则化的使用。用在代价函数中
L2:
L1:
\(\lambda\)是正则化参数,也是一个超参数。
下面的这个是要正则化的参数W,指的是:所有w参数的*方和
上图的含义是指将每个参数w逐渐的减少
当w约等于0时,也就是说这个隐藏单元的作用消失了,就意味着正则化使得神经网络变简单了。这也叫做“权重损失”。在正则化过程中,渐渐的从图三的神经网络转变成图一的简单网络,中间会有一个刚刚好的结果。
Dropout正则化
dropout正则化通过随机使一些节点失活来使神经网络简单化。
每一层都可以设置keep-prob的值使每一层失活率不同
代码实现:
a_3是指第三层的a的矩阵
keep_prob是概率值 例:keep_prob = 0.8 说明有80%的节点不失活
d_3 = np.random.rand(a_3.shape[0],a_3.shape[1]) < keep_prob
#d_3是一个和a_3相同维度的布尔矩阵
a_3 = np.multipy(a_3,d_3) #也就是a_3=a_3*d_3
#这个操作决定哪些节点失活了,a_3中乘了false的节点失活
a_3 = a_3/keep_prob
#inverted dropout反向随机失活的使用,此运算可以很好的计算*均值,避免以后还要计算
2. 增加数据:数据增强
常用的数据扩增包括镜像翻转、随机裁剪、色彩转换。通过数据增强可以得到更多的数据样本。
缺点:新增的数据质量不够高,不如全新的数据好
优点:代价几乎为0
3. Early stopping
只在训练集上进行训练,并每个一个周期计算模型在验证集上的误差,当模型在验证集上的误差比上一次训练结果差(或定义其他停止规则)的时候停止训练,以上一次最优的情况作为训练模型
缺点:无法同时达成偏差和方差的最优。
优点:迅速、能够有效避免过拟合、不像L2正则化那样需要大量的时间计算\(\lambda\)超参的合适值。
二. 梯度消失、梯度爆炸
在深层次的神经网络中,可能因为w的权重全部或大部分大于1或小于1使得传递过去的值不停的呈指数级增加或减少,从而出现梯度消失、梯度爆炸的情况。
合理的初始化参数可以有效缓解这种情况:
WL = np.random.randn(WL.shape[0], WL.shape[1]) * np.sqrt(1/n)
n是输入的神经元个数,即WL.shape[1]
三. 梯度检验
梯度检验只用与debug时,可以使用这种方法来判断反向传播进行梯度下降时,是否出现了错误。
对于那些参数如w、b的偏导数
在用梯度下降时有时要判断dw是否正确,用梯度检验的方法。
梯度检验其实就是用导数的定义来解:
计算这个结果是否等于dw
在神经网络实施梯度检验的实用技巧和注意事项
- 不要在训练中使用梯度检验,它只用于调试(debug)。使用完毕关闭梯度检验的功能;
- 如果算法的梯度检验失败,要检查所有项,并试着找出 bug,即确定哪个 dθapprox[i] 与 dθ 的值相差比较大;
- 当成本函数包含正则项时,也需要带上正则项进行检验;
- 梯度检验不能与 dropout 同时使用。因为每次迭代过程中,dropout 会随机消除隐藏层单元的不同子集,难以计算 dropout 在梯度下降上的成本函数 J。建议关闭 dropout,用梯度检验进行双重检查,确定在没有 dropout 的情况下算法正确,然后打开 dropout;
四. 优化算法
深度学习难以在大数据领域发挥最大效果的一个原因是,在巨大的数据集基础上进行训练速度很慢。而优化算法能够帮助快速训练模型,大大提高效率。
1. BGD
- 批梯度下降法(Batch gradient descent):遍历全部数据集算一次损失函数,然后算函数对各个参数的梯度,更新梯度。这种方法每更新一次参数都要把数据集里的所有样本都看一遍,计算量开销大,计算速度慢,不支持在线学习。
2. SGD
-
随机梯度下降法(stochastic gradient descent)是通过每个样本迭代更新一次,每看一个数据就算一下损失函数,然后求梯度更新。
-
优点:速度快
-
缺点:准确度下降,很可能不是全局最优、收敛性能不太好。可能在最优点附*晃来晃去,两次参数的更新也有可能互相抵消掉,造成目标函数震荡的比较剧烈。
3. MBGD
为了克服两种方法的缺点,现在一般采用的是一种折中手段,mini-batch gradient decent,小批量梯度下降,这种方法把数据分为若干个批,按批来更新参数,这样,一个批中的一组数据共同决定了本次梯度的方向,下降起来就不容易跑偏,减少了随机性。另一方面因为一批的样本数与整个数据集相比小了很多,计算量也不是很大。
- 如果训练样本的大小比较小,如 m ⩽ 2000 时,选择 batch 梯度下降法;
- 如果训练样本的大小比较大,选择 Mini-Batch 梯度下降法。为了和计算机的信息存储方式相适应,代码在 mini-batch 大小为 2 的幂次时运行要快一些。典型的大小为 \(2^6\)、\(2^7\)、\(2^8\)、\(2^9\)。mini-batch 的大小要符合 CPU/GPU 内存。
- mini-batch 的大小也是一个重要的超参数,需要根据经验快速尝试,找到能够最有效地减少成本函数的值。
4. 动量梯度下降法
动量梯度下降法是对MBGD的改良,mini-batch主要的问题是在训练过程中函数振荡较大,优化之后左右的摆动减小,从而提高效率。
指数加权*均
\(V_t=\beta V_{t-1}+(1-\beta)\theta_t\)
指数加权*均求的是前\(\frac{1}{(1-\beta)}\)天的*均
指数*均加权并不是最精准的计算*均数的方法,你可以直接计算过去 10 天或 50 天的*均值来得到更好的估计,但缺点是保存数据需要占用更多内存,执行更加复杂,计算成本更加高昂。
指数加权*均数公式的好处之一在于它只需要一行代码,且占用极少内存,因此效率极高,且节省成本。
指数*均加权的偏差修正
动量梯度下降法公式
动量梯度下降法思想很简单,就是先将导数值用指数*均加权求*均,然后用该值去更新参数值
5. RMSprop算法
RMSProp 有助于减少抵达最小值路径上的摆动,并允许使用一个更大的学习率 α,从而加快算法学习速度。并且,它和 Adam 优化算法已被证明适用于不同的深度学习网络结构。
6. Adams算法
Adams算法就是将Momentum 和 RMSProp 算法结合在一起。
具体过程如下(省略了 l):
注意:一定要偏差修正
Adam 优化算法有很多的超参数,其中
- 学习率 α:需要尝试一系列的值,来寻找比较合适的;
- β1:常用的缺省值为 0.9;
- β2:Adam 算法的作者建议为 0.999;
- ϵ:不重要,不会影响算法表现,Adam 算法的作者建议为\(10^{-8}\);
β1、β2、ϵ 通常不需要调试。
7. 学习率衰减
对于学习率\(\alpha\)这个超参数,如果设置一个固定的学习率 α,在最小值点附*,由于不同的 batch 中存在一定的噪声,因此不会精确收敛,而是始终在最小值周围一个较大的范围内波动。
而如果随着时间慢慢减少学习率 α 的大小,在初期 α 较大时,下降的步长较大,能以较快的速度进行梯度下降;而后期逐步减小 α 的值,即减小步长,有助于算法的收敛,更容易接*最优解。
8. 局部最优问题
-
鞍点(saddle)是函数上的导数为零,但不是轴上局部极值的点。当我们建立一个神经网络时,通常梯度为零的点是鞍点,而非局部最小值。
-
在训练较大的神经网络、存在大量参数,并且成本函数被定义在较高的维度空间时,困在所有维度导数都是0的这种极差的局部最优中是不大可能的,大多情况都是到达鞍点。
-
鞍点附*的*稳段会使得学习非常缓慢,而这也是动量梯度下降法、RMSProp 以及 Adam 优化算法能够加速学习的原因,它们能帮助尽早走出*稳段。
五. 超参数选择
1. 超参数重要程度(不绝对)
2. 调参技巧
系统地组织超参调试过程的技巧:
- 随机选择点(而非均匀选取),用这些点实验超参数的效果。这样做的原因是我们提前很难知道超参数的重要程度,可以通过选择更多值来进行更多实验;
- 由粗糙到精细:聚焦效果不错的点组成的小区域,在其中更密集地取值,以此类推;
3. 选择合适的标尺
- 对于学习率 α,用对数标尺而非线性轴更加合理:0.0001、0.001、0.01、0.1 等,然后在这些刻度之间再随机均匀取值;
- 对于 β,取 0.9 就相当于在 10 个值中计算*均值,而取 0.999 就相当于在 1000 个值中计算*均值。可以考虑给 1-β 取值,这样就和取学习率类似了。
六. 批归一化Batch Normalization
作用:
- 会使参数搜索问题变得很容易,使神经网络对超参数的选择更加稳定,超参数的范围会更庞大,工作效果也很好,也会使训练更容易。
- 通过对隐藏层各神经元的输入做类似的标准化处理,提高神经网络训练速度;
- 可以使前面层的权重变化对后面层造成的影响减小,整体网络更加健壮。
之前的归一化是对特征值(也就是输入层),而Batch归一化用来归一Z的值(也就是隐藏层),虽然与归一化特征值类似,但batch norm不仅仅是零均值化、统一方差,而且添加了\(\gamma\)和\(\beta\)两个参数,可以自定义均值和方差。设置 γ 和 β 的原因是,如果各隐藏层的输入均值在靠* 0 的区域,即处于激活函数的线性区域,不利于训练非线性神经网络,从而得到效果较差的模型。因此,需要用 γ 和 β 对标准化后的结果做进一步处理。
使用 Batch Normalization 时,因为标准化处理中包含减去均值的一步,因此 b 实际上没有起到作用,其数值效果交由 β 来实现。因此,在 Batch Normalization 中,可以省略 b 或者暂时设置为 0。——所以使用Batach Norm后超参变为了\(W\)$\beta $$\gamma$
七. 迁移学习
迁移学习(Tranfer Learning)是通过将已训练好的神经网络模型的一部分网络结构应用到另一模型,将一个神经网络从某个任务中学到的知识和经验运用到另一个任务中,以显著提高学习任务的性能。迁移对象两者之间是有关联的。比如猫狗识别与放射诊断的低层特征是相似的, 都是关于图像处理的边缘检测、线条的特征等等, 这就是两个学习任务共同的知识。在迁移学习中就可以省略这些层数的重新训练。
如果新的数据集很小,可能只需要重新训练输出层前的最后一层的权重,即\(W^{[L]}、b^{[L]}\),并保持其他参数不变;而如果有足够多的数据,可以只保留网络结构,重新训练神经网络中所有层的系数。这时初始权重由之前的模型训练得到,这个过程称为预训练(Pre-Training),之后的权重更新过程称为微调(Fine-Tuning)。
在下述场合进行迁移学习是有意义的:
- 两个任务有同样的输入(比如都是图像或者都是音频);
- 拥有更多数据的任务迁移到数据较少的任务;
- 某一任务的低层次特征(底层神经网络的某些功能)对另一个任务的学习有帮助。
模型微调步骤
- 在已经训练好的基网络(base network)上添加自定义网络
- 冻结基网络
- 训练所添加的部分
- 解冻基网络的一些层
- 联合训练解冻的这些层和添加的部分
模型微调就是训练完后面自己定义的网络后解冻之前的训练过的网络。模型微调一般解冻顶层的一些层,因为底层更具有通用性。
数据集很小,可以不进行微调;数据集大的话可以适当解冻一些层微调甚至可以把所有预训练的网络作为初始值全部进行训练。