深度学习中的激活函数与梯度消失

转载自https://blog.csdn.net/shwan_ma/article/details/76252355

https://www.cnblogs.com/willnote/p/6912798.html


Sigmoid激活函数

sigmoid函数在历史上很受欢迎,因为他很符合神经元的特征, 
这里写图片描述

优点是: 能够把输出控制在[0,1]之间, 直观 
缺点是:1)他的饱和区和未激活区的梯度均为0,容易造成梯度弥散,比如x = 10时和x = -10时,链式求导的时候,梯度会变得很小导致权重更新很慢 

2)非0均值输出。这会引入一个问题,当输入均为正值的时候,由于f = sigmoid(wTx+b)),那么对w求局部梯度则都为正,这样在反向传播的过程中w要么都往正方向更新,要么都往负方向更新,导致有一种捆绑的效果,使得收敛缓慢。 

3)计算量比较大,都将把时间放在exp和矩阵点乘上了

在sigmod函数中我们可以看到,其输出是在(0,1)这个开区间内,这点很有意思,可以联想到概率,但是严格意义上讲,不要当成概率。sigmod函数曾经是比较流行的,它可以想象成一个神经元的放电率,在中间斜率比较大的地方是神经元的敏感区,在两边斜率很平缓的地方是神经元的抑制区。

当然,流行也是曾经流行,这说明函数本身是有一定的缺陷的。

1) 当输入稍微远离了坐标原点,函数的梯度就变得很小了,几乎为零。在神经网络反向传播的过程中,我们都是通过微分的链式法则来计算各个权重w的微分的。当反向传播经过了sigmod函数,这个链条上的微分就很小很小了,况且还可能经过很多个sigmod函数,最后会导致权重w对损失函数几乎没影响,这样不利于权重的优化,这个问题叫做梯度饱和,也可以叫梯度弥散。

2) 函数输出不是以0为中心的,这样会使权重更新效率降低。对于这个缺陷,在斯坦福的课程里面有详细的解释。

3) sigmod函数要进行指数运算,这个对于计算机来说是比较慢的。


这里写图片描述 

tanh激活函数

tanh并没有解决sigmoid的梯度弥散问题,然而却解决了输出是0均值的问题,这使得tanh的收敛速度要比sigmoid要快的多。 

这里写图片描述

tanh是双曲正切函数,tanh函数和sigmod函数的曲线是比较相近的,咱们来比较一下看看。首先相同的是,这两个函数在输入很大或是很小的时候,输出都几乎平滑,梯度很小,不利于权重更新;不同的是输出区间,tanh的输出区间是在(-1,1)之间,而且整个函数是以0为中心的,这个特点比sigmod的好。

一般二分类问题中,隐藏层用tanh函数,输出层用sigmod函数。不过这些也都不是一成不变的,具体使用什么激活函数,还是要根据具体的问题来具体分析,还是要靠调试的。


Relu激活函数

Relu是目前用的最多的一种激活函数, 
这里写图片描述

由于在正区域中很好的解决了梯度弥散的问题,而且其计算速度很快(只进行比较操作),在收敛速度上也比sigmoid和tanh要快 
然而:其并没有解决负区域的梯度弥散问题,当初始权重设置的比较糟的时候,会导致dead relu,整个网络的权重不会进行更新 
而且,relu输出也不是0均值的 

(为了弄出一个0均值的relu,好像有个进化版的叫ELU)

ReLU(Rectified Linear Unit)函数是目前比较火的一个激活函数,相比于sigmod函数和tanh函数,它有以下几个优点:

1) 在输入为正数的时候,不存在梯度饱和问题。

2) 计算速度要快很多。ReLU函数只有线性关系,不管是前向传播还是反向传播,都比sigmod和tanh要快很多。(sigmod和tanh要计算指数,计算速度会比较慢)

当然,缺点也是有的:

1) 当输入是负数的时候,ReLU是完全不被激活的,这就表明一旦输入到了负数,ReLU就会死掉。这样在前向传播过程中,还不算什么问题,有的区域是敏感的,有的是不敏感的。但是到了反向传播过程中,输入负数,梯度就会完全到0,这个和sigmod函数、tanh函数有一样的问题。

2) 我们发现ReLU函数的输出要么是0,要么是正数,这也就是说,ReLU函数也不是以0为中心的函数

总结

**1.尽量不要用sgmoid,因为其收敛速度比较慢 
2.可以去尝试tanh 
3.尽量去使用relu,relu的收敛速度块,计算量少**


深度学习的基本原理是基于人工神经网络,信号从一个神经元进入,经过非线性的激活函数,传入到下一层神经元;再经过该层神经元的激活,继续往下传递,如此循环往复,直到输出层。正是由于这些非线性函数的反复叠加,才使得神经网络有足够的能力来抓取复杂的模式,在各个领域取得不俗的表现。显而易见,激活函数在深度学习中举足轻重,也是很活跃的研究领域之一。目前来讲,选择怎样的激活函数不在于它能否模拟真正的神经元,而在于能否便于优化整个深度神经网络。

本文首先着重对Sigmoid函数的特点与其存在的梯度消失问题进行说明,之后再对其他常用的一些激活函数的特点进行对比介绍。

Sigmoid函数


Sigmoid函数是深度学习领域开始时使用频率最高的激活函数。

函数形式




梯度消失

  • 梯度消失问题
    首先,我们将一个使用Sigmoid作为激活函数的网络,在初始化后的训练初期结果进行可视化如下:




    在上图中,神经元上的橙色柱条可以理解为神经元的学习速率。虽然这个网络是经过随机初始化的,但是从上图不难发现,第二层神经元上的柱条都要大于第一层对应神经元上的柱条,即第二层神经元的学习速率大于第一层神经元学习速率。那这可不可能是个巧合呢?其实不是的,Nielsen在《Neural Networks and Deep Learning》中通过实验说明了这种现象是普遍存在的。

    接下来我们再来看下对于一个具有四个隐层的神经网络,各隐藏层的学习速率曲线如下:




    可以看出,第一层的学习速度和最后一层要差两个数量级,也就是比第四层慢了100倍。 实际上,这个问题是可以避免的,尽管替代方法并不是那么有效,同样会产生问题——在前面的层中的梯度会变得非常大!这也叫做梯度激增(exploding gradient problem),这也没有比梯度消散问题更好处理。

    更加一般地说,在深度神经网络中的梯度是不稳定的,在前面的层中或会消失,或会激增,这种不稳定性才是深度神经网络中基于梯度学习的根本原因。

  • 梯度消散的产生原因
    为了弄清楚为何会出现梯度消散问题,来看看一个简单的深度神经网络:每一层都只有一个单一的神经元。下面就是有三层隐藏层的神经网络:




    我们把梯度的整个表达式写出来:


    我们再来看一下Sigmoid函数导数的曲线:



    该导数在σ(0)=14σ′(0)=14时达到最高。现在,如果我们使用标准方法来初始化网络中的权重,那么会使用一个均值为0标准差为1的高斯分布。因此所有的权重通常会满足|wj|<1|wj|<1。有了这些信息,我们发现会有wjσ(zj)<14wjσ′(zj)<14,并且在进行所有这些项的乘积时,最终结果肯定会指数级下降:项越多,乘积的下降也就越快。
    下面我们从公式上比较一下第三层和第一层神经元的学习速率:



  • 不稳定的梯度问题
    根本的问题其实并非是梯度消失问题或者梯度激增问题,而是在前面的层上的梯度是来自后面的层上项的乘积。当存在过多的层次时,就出现了内在本质上的不稳定场景。唯一让所有层都接近相同的学习速度的方式是所有这些项的乘积都能得到一种平衡。如果没有某种机制或者更加本质的保证来达成平衡,那网络就很容易不稳定了。简而言之,真实的问题就是神经网络受限于不稳定梯度的问题。所以,如果我们使用标准的基于梯度的学习算法,在网络中的不同层会出现按照不同学习速度学习的情况。

zero-centered




运算时耗

相对于前两项,这其实并不是一个大问题,我们目前是具备相应计算能力的,但面对深度学习中庞大的计算量,最好是能省则省。之后我们会看到,在ReLU函数中,需要做的仅仅是一个thresholding,相对于幂运算来讲会快很多。

tanh函数


tanh函数即双曲正切函数(hyperbolic tangent)。

函数形式



评价

  • 优点
    解决了zero-centered的输出问题。
  • 缺点
    梯度消失的问题和幂运算的问题仍然存在。

ReLU函数


ReLU函数(Rectified Linear Units)其实就是一个取最大值函数,注意这并不是全区间可导的,但是我们可以取次梯度(subgradient)。

函数形式


评价

  • 优点
    • 解决了梯度消失的问题 (在正区间)
    • 计算速度非常快,只需要判断输入是否大于0
    • 收敛速度远快于sigmoid和tanh
  • 缺点
    • 输出不是zero-centered
    • Dead ReLU Problem
      Dead ReLU Problem指的是某些神经元可能永远不会被激活,导致相应的参数永远不能被更新。有两个主要原因可能导致这种情况产生: (1) 非常不幸的参数初始化,这种情况比较少见 (2) 学习速率太高导致在训练过程中参数更新太大,不幸使网络进入这种状态。解决方法是可以采用Xavier初始化方法,以及避免将学习速率设置太大或使用adagrad等自动调节学习速率的算法。

尽管存在这两个问题,ReLU目前仍是最常用的激活函数,在搭建神经网络的时候推荐优先尝试!

Leaky ReLU函数


为了解决ReLU函数的Dead ReLU Problem而提出的激活函数。

函数形式


ELU函数



评价

ELU也是为解决ReLU存在的问题而提出,显然,ELU有ReLU的基本所有优点,以及:

  • 不会有Dead ReLU问题
  • 输出的均值接近0,zero-centered

它的一个小问题在于计算量稍大。类似于Leaky ReLU,理论上虽然好于ReLU,但在实际使用中目前并没有好的证据ELU总是优于ReLU。

ELU函数是针对ReLU函数的一个改进型,相比于ReLU函数,在输入为负数的情况下,是有一定的输出的,而且这部分输出还具有一定的抗干扰能力。这样可以消除ReLU死掉的问题,不过还是有梯度饱和和指数运算的问题。

PReLU函数

PReLU函数公式和曲线如下图

prelu公式 
prelu函数图

PReLU也是针对ReLU的一个改进型,在负数区域内,PReLU有一个很小的斜率,这样也可以避免ReLU死掉的问题。相比于ELU,PReLU在负数区域内是线性运算,斜率虽然小,但是不会趋于0,这算是一定的优势吧。

我们看PReLU的公式,里面的参数α一般是取0~1之间的数,而且一般还是比较小的,如零点零几。当α=0.01时,我们叫PReLU为Leaky ReLU,算是PReLU的一种特殊情况吧。

总体来看,这些激活函数都有自己的优点和缺点,没有一条说法表明哪些就是不行,哪些激活函数就是好的,所有的好坏都要自己去实验中得到。

Maxout

Maxout 是对 ReLU 和 Leaky ReLU 的一般化归纳,它的函数公式是(二维时):max(wT1+b1,WT2+b2)max(w1T+b1,W2T+b2)。ReLU 和 Leaky ReLU 都是这个公式的特殊情况(比如 ReLU 就是当 w1,b1=0w1,b1=0时)。

这样 Maxout 神经元就拥有 ReLU 单元的所有优点(线性和不饱和),而没有它的缺点(死亡的ReLU单元)。然而和 ReLU 对比,它每个神经元的参数数量增加了一倍,这就导致整体参数的数量激增。

如何选择激活函数?

通常来说,很少会把各种激活函数串起来在一个网络中使用的。

如果使用 ReLU,那么一定要小心设置 learning rate,而且要注意不要让你的网络出现很多 “dead” 神经元,如果这个问题不好解决,那么可以试试 Leaky ReLU、PReLU 或者 Maxout.

最好不要用 sigmoid,可以试试 tanh,不过可以预期它的效果会比不上 ReLU 和 Maxout.



softmax函数:用于多分类神经网络输出



猜你喜欢

转载自blog.csdn.net/dulingtingzi/article/details/80319997