边境的悍匪—机器学习实战:第十一章 训练深度神经网络

第十一章 训练深度神经网络

文章目录

  • 第十一章 训练深度神经网络
  • 前言
  • 一、思维导图
  • 二、主要内容
    • 1、梯度消失与梯度爆炸问题
    • 2、重用预训练层
    • 3、更快的优化器
    • 4、通过正则化避免过拟合
    • 5、总结和实用指南
  • 三、课后练习
  • 四、总结


前言

前面的一章我们了解了什么是神经网络,神经网络的发展、组成、应用等一系列的知识。在上一章的基础上我们开始进入这一章训练深度神经网络的学习。
我们在训练一个神经网络的过程中会遇到的很多的问题例如:1、梯度消失与梯度爆炸。2、训练速度极其缓慢。3、由于神经网络大量的参数造成的模型过拟合。在完成这一章的学习之后我们就将会了解为什么会在训练神经网络时出现这些问题,面对这些问题时我们都有什么样的解决方法。


一、思维导图

二、主要内容

1、梯度消失与梯度爆炸问题

  1. 简介
    由于我们在训练深度神经网络时使用的是反向转播技术来调整模型参数,我们根据链式求导法则可以推导出,当需要计算一个连接的权重梯度时需要计算连接之前所经过的所有神经元激活函数的导数,当求导结果大于1时,梯度会随着层数的增加而呈指数上升,此时称为梯度爆炸。相反如果求导结果小于1时,梯度会随着层数的增加而呈指数下降,此时成为梯度消失。
  2. 解决方法
    Glorot和He初始化
    Glorot和Bengio提出了一种特定的初始化神经网络所有连接权重的方法来缓解梯度的不稳定性,称为Gloror初始化。其他的论文中也提出了针对不同的激活函数的初始化策略,不过这些所有的初始化策略的差异只是使用的方差大小和使用的是fanavg还是fanin。
    非饱和的激活函数
    在2010年Glorot和Bengio又提出另一个见解,他们认为造成梯度不稳定的另外一个原因是没有选择一个合适的激活函数。在这个想法提出之前,人们一直坚信与生物网络相似的sigmoid激活函数会是一个很好的选择,但是事实证明ReLU的表现要好于sigmoid。
    但不幸的是,ReLU激活函数也有不足的地方。由于ReLU激活函数的特性,当使用很大的学习率的时候,会出现神经元死亡的现象,也就是神经元不会再输出除了0之外的任何值。为了解决ReLU激活函数会出现神经元死亡的问题,在ReLU激活函数的基础上生成了很多的变体,例如:LeakyReLU,RReLU。不过在数据集很小的情况下RReLU会造成过拟合。
    批量归一化
    尽管我们选择了一个很好的权重初始化策略和一个很好激活函数,也不能完全保证梯度的不稳定性不会出现。
    2015年科学提出了一种批量归一化的技术,来解决梯度不稳定的问题。方法建议在每个隐藏层的前面或者后面添加一个批量归一化层,对每个数据都0中心并归一化。
    由于算法会在训练的时候计算每一个批次的均值和标准差,但是在预测的时候每次只有一个实例,无法计算均值和标准差。为了解决这个问题,就会在训练模型时,在每个归一化层训练四个参数:输出缩放量,输出偏移量,最终输入均值向量,最终输入标准差向量。最后两个向量不受反向传播的影响,所以在训练时不可训练参数。
    使用批量归一化会在原本的神经网络上添加上归一化层,使模型变得复杂,在训练时很缓慢。但是可以使用把批量归一化层与上一层结合的方式来解决缓慢的问题。
    梯度裁剪
    梯度裁剪是一种解决梯度不稳定中不常用的方法。它通过在反向传播中使得梯度永远不会超过一个指定的阀值。这种方式常用于循环神经网络(RNN)中,因为循环神经网络很难进行批量归一化。

2、重用预训练层

  1. 简介
    迁移学习
    我们自己从无到有训练一个神经网络并不是一个很好的选择,我们可以选择重用一些相似任务已经训练好的神经网络的部分层,这种方式称为迁移学习。
    在迁移学习中我们一般会替换掉输出层,因为我们每一个任务的结果并不相同,并且我们在重用隐藏层时需要根据自己的实际情况解冻迁移过来的隐藏层,你拥有的数据量越多你可以解冻的隐藏层就越多,如果你拥有的数据足够多,你甚至可以替换掉一些隐藏层而不是删除他们。一般情况下,你们的任务越相似,可以重用的隐藏层也就越多。
  2. 应用
    无监督预训练
    当你拥有的数据并没有标签,或者是有很少的标签,并且你也找不到与你任务类似的神经网络时,就可以使用无监督预训练生成神经网络的较低层,然后根据实际情况添加输出层,并用包含标签的数据微调神经网络的参数。
    辅助任务的预训练
    当你遇到很多没有标签的数据时,你还可以训练一个用于复制当前任务的第一个神经网络,然后重用第一个神经网络的较低层来完成你的任务。

3、更快的优化器

  1. 动量优化
    由于常规的梯度下降只会考虑到当前的梯度,所以会导致训练缓慢,动量优化引入了动量的概念,使得每次在更新梯度时会考虑到之前的梯度,此时的梯度不再是用于速度,而是用于加速度。
  2. Nesterov加速梯度
    Nesterov加速梯度是动量优化的变体,它会使得动量向量总是指向正确的方向,所以Nesterov加速梯度在计算梯度时不会在原始位置,而是在向量指向稍微往远一点的位置。
  3. AdaGrad
    在面对一个拉长的碗状问题时,AdaGrad会根据峭壁的陡峭程度缩小向量的大小,使其竟可能的指向正确的位置。由于AdaGrad会自动调节学习率,所以在你使用AdaGrad时几乎不需要调整学习率超参数,但是由于超参数会越来越小,使得神经网络提前收敛,所以AdaGrad不适用于深层神经网络。
  4. RMSProp
    为了使得AdaGrad可以适用于深层神经网络,提出了一个AdaGrad的变体RMSProp。添加了一个衰减率的超参数,计算向量时不再使用所有的梯度,而是使用最近的一部份梯度,解决了AdaGrad下降太快的问题。
  5. Adam和Nadam优化
    Adam
    Adam结合了动量优化和RMSProp的思想,它像动量优化一样根据过去梯度的指数衰减平均值,像RMSProp一样根据过去平方梯度的指数衰减平均值。
    AdaMax是Adam的变体,具体的性能取决于数据集,一般情况下依旧是Adam的性能会好。
    Nadam优化
    Nadam优化是在Adam的基础上Nesterov的技巧。
    虽然自适应算法有很好的性能,但是根据研究发现,在有的数据集中,自适应优化算法会导致模型泛化能力不佳。这个时候就可以尝试使用Nesterov加速梯度。
  6. 学习率调度
    当你在使用的优化器是需要自己手动调节学习率的情况,这时候学习率的调节是一个很关键的事情。文中提到的常用的学习率调度:幂调度,指数调度,分段恒定调度,性能调度,1周期调度。每一种都有自己不同的适应情况。

4、通过正则化避免过拟合

  1. 11和l2正则化
    我们可以像在第四章一样使用l2正则化深度神经网络。并且Keras也提供了一套完整的流程来使用l1和l2正则化。
  2. dropout
    dropout是目前神经网络训练中最受欢迎的正则化技术,他会使用使神经网络中的神经元在训练的过程中有概率P被删除掉的方式来对神经网络进行正则化。由于dropout只会在训练的过程中被激活,所以这个时候比较训练损失与验证损失是没有意义的。当模型过拟合的时候应该升高dropout率,当模型欠拟合的时候应该降低dropout率。为了dropout可以更加广泛的应用,提出了一种称为(MC)Dropout的技术,可以提高使用了dropout神经网络的性能。
  3. 最大范数正则化
    最大范数正则化通过限制每个神经元传入的连接权重的方式来对神经网络进行正则化。

5、总结和实用指南

其实在一般的情况下,神经网络中的一些默认参数就已经有一个很好的性能了。
下面列举了一些特殊的情况:

  1. 当你需要得到一个稀疏模型时,可以使用正则化,如果还需要更加稀疏的模型可以使用TensorFlow模型优化工具包。
  2. 如果你不希望你得到一个有延迟的模型。那么你就需要很少的层,并且需要把批量归一化层(BN)与上一层结合再选择一个比较快速的激活函数。
  3. 如果你在处理风险敏感型应用,那么你可以使用(MC)Dropout来提高性能并获得一个更可靠的概率估计及不不确定性估计。
  4. 如果你可以找到与你任务相似的已经训练好的神经网络,那么你可以重用他的层。如果你有很多未标记的数据可以使用无监督预训练,然后使用部分标记数据微调模型参数。如果你有相似任务的大量标记数据,那么可以在辅助任务上进行预训练。

三、课后练习

  1. 将所有权重初始化为相同的值是否可以(只要该值是使用He初始化随机选择的)?
    权重初始化是不能将所有的值都设置为一个相同的值。设置随机权重的目的就是打破对称性,如果将所有的权重设置为一个值,即使不是0,对称性也不会被破坏,每一层都相当于是一个神经元,并且反向传播并不能破坏它,这样的神经网络不仅慢而且无法收敛到一个很好的结果。
  2. 将偏置项初始化为0可以吗?
    可以,有些人还会喜欢像初始化权重一样初始化偏执项这样也是可以的。
  3. 列举SELU激活函数相比ReLU的三个优点。
    1、可以使用负值, 某一给定层的神经元输出平均值理论上更接近0。这样有助于缓解梯度消失问题。
    2、它总是有一个非零的导数,可以避免影响ReLU单元的单元消失问题。
    3、当条件合适时,SELU激活函数可以确保模型进行自归一化,这样可以解决梯度消失和梯度爆炸问题。
  4. 在哪种情况下,你想使用以下每个激活函数:SELU、leakyReLU(及其变体)、ReLU、tanh、logistic和softmax?
    SELU激活函数是一个不错的默认选择。如果你需要对一个神经网络的速度要求很高那么可以使用leakyReLU以及他的变体。ReLU被广泛的使用是因为他使用起来简单方便,即使有的时候性能会被leakyReLU超过,但是激活函数ReLU准确输出0的能力是有用的,并且我们还可以从优化的实现和硬件的加速中获益。如果你需要输出一个介于-1和1之间的数,那么使用tanh激活函数在输出层会比较有效,这个激活函数在隐藏层的使用频率并不高。如果你需要评估可能性时,逻辑激活函数在输出层会比较有效,同样在隐藏层中也不怎么使用。当你在输出层的输出是互斥的概率时可以使用softmax。
  5. 如果在使用SGD优化器时将超参数momentum设置得太接近1(例如0.99999),会发生什么情况?
    如果使用SGD优化器,将超参数momentum设置得太接近1,算法就会提速很高,偏向全局最小值,但是其动量使其刚好超过最小值。之后就会慢慢降速回落,再加速,再超调,循环往复。这种方式会在收敛前震荡好几次,所以总体来说,收敛速度会比小动量慢。
  6. 列举三种能产生稀疏模型的方法。
    第一种方法在训练完成之后,将小权重设置为0,第二种是在训练过程中使用l1正则化。第三种方法是使用TensorFlow的模型优化工具箱。
  7. dropout会减慢训练速度吗?它会减慢推理速度(即对新实例进行预测)吗?MC Dropout呢?
    是的,dropout会减慢训练速度,一般会减慢到正常的一半,但是它只会在训练期间打开,对预测的速度没有影响。MC Dropout在训练期间与dropout一样,但是在预测时通常是运行状态,所以MC Dropout预测的速度一般都会慢一些。但是当你在使用MC Dropout是你都是希望能够得到一个预测很快的模型,这也就意味着,MC Dropout的慢相对来说已经很慢。

四、总结

以上就是训练深度神经网络章节的所有内容。大概例举了我们在训练神经网络中会遇到的问题,以及一些除了默认值之外的特殊情况和特殊情况的应对方法。把所有内容总结起来就是:

  1. 由于反向传播的特性使得在训练深度神经网络时会出现由于梯度不稳定造成的梯度消失与梯度爆炸问题。
    缓解问题
    我们可以使用初始化策略和选择一个非饱和激活函数的方式来缓解梯度不稳定的问题。
    解决问题
    批量归一化通过在神经元的前面或者后面添加一个归一化层的方式来解决梯度不稳定的问题。
  2. 我们可以使用重用其他神经网络层的方式来构建自己的神经网络,这种方式成为迁移学习。迁移学习可以减少你的神经网络训练时间,还可以用于处理一些没有标签的数据,对数据进行预训练然后重用训练好的层。
  3. 由于正常的梯度下降会导致在训练深度神经网络的时候非常的缓慢,所以提出了很多的更加快速的优化器,每种优化器的算法各不相同应用场景也也不相同。
  4. 为了防止训练出来的模型出现过拟合的情况,需要对模型进行正则化,文中一共提到了:11和l2正则化,dropout正则化,最大范数正则化三种方式,在实际的应用中,最受欢迎的还是dropout正则化。

对文章有任何疑惑或者想要和博主一起学机器学习一起进步的朋友们可以添加 群号:666980220。需要机器学习实战电子版或是思维导图的也可以联系我。祝你好运!

项目地址: github

你可能感兴趣的:(机器学习实战,机器学习,神经网络,dnn)