在深度学习中,信号从一个神经元传入到下一层神经元之前是通过线性叠加来计算的,而进入下一层神经元需要经过非线性的激活函数,继续往下传递,如此循环下去。由于这些非线性函数的反复叠加,才使得神经网络有足够的capacity来抓取复杂的特征。
为什么要使用非线性激活函数?
答:如果不使用激活函数,这种情况下每一层输出都是上一层输入的线性函数。无论神经网络有多少层,输出都是输入的线性函数,这样就和只有一个隐藏层的效果是一样的。这种情况相当于多层感知机(MLP)(非深度学习)。
1、Sigmoid函数
优点:(1)便于求导的平滑函数,其导数形式为:;
(2)能压缩数据,保证数据幅度不会有问题;
(3)适合用于前向传播。
缺点:
(1)容易出现梯度消失(gradient vanishing)的现象:当激活函数接近饱和区时,变化太缓慢,导数接近0,根据后向传递的数学依据是微积分求导的链式法则,当前导数需要之前各层导数的乘积,几个比较小的数相乘,导数结果很接近0,从而无法完成深层网络的训练。
解释:优化神经网络的方法是Back Propagation,即导数的后向传递:先计算输出层对应的loss,然后将loss以导数的形式不断向上一层网络传递,修正相应的参数,达到降低loss的目的。 Sigmoid函数在深度网络中常常会导致导数逐渐变为0,使得参数无法被更新,神经网络无法被优化。原因在于两点:(1) 在上图中容易看出,当中较大或较小时,导数接近0,而后向传递的数学依据是微积分求导的链式法则,当前层的导数需要之前各层导数的乘积,几个小数的相乘,结果会很接近0 (2) Sigmoid导数的最大值是0.25,这意味着导数在每一层至少会被压缩为原来的1/4,通过两层后被变为1/16,…,通过10层后为1/1048576。请注意这里是“至少”,导数达到最大值这种情况还是很少见的。
(2)Sigmoid的输出不是0均值(zero-centered)的:这会导致后层的神经元的输入是非0均值的信号,这会对梯度产生影响。以 f=sigmoid(wx+b)为例, 假设输入均为正数(或负数),那么对w的导数总是正数(或负数),这样在反向传播过程中要么都往正方向更新,要么都往负方向更新,导致有一种捆绑效果,使得收敛缓慢。
解释:
Sigmoid函数的输出值恒大于0,这会导致模型训练的收敛速度变慢。举例来讲,对,如果所有均为正数或负数,那么其对的导数总是正数或负数,这会导致如下图红色箭头所示的阶梯式更新,这显然并非一个好的优化路径。深度学习往往需要大量时间来处理大量数据,模型的收敛速度是尤为重要的。所以,总体上来讲,训练深度学习网络尽量使用zero-centered数据 (可以经过数据预处理实现) 和zero-centered输出。
(3)幂运算相对耗时
解释:相对于前两项,这其实并不是一个大问题,我们目前是具备相应计算能力的,但面对深度学习中庞大的计算量,最好是能省则省。之后我们会看到,在ReLU函数中,需要做的仅仅是一个thresholding,相对于幂运算来讲会快很多。
2、tanh函数
tanh函数(Hyperbolic Tangent)将输入值压缩到 -1~1 的范围,因此它是0均值的,
优点:
(1) [-1,1]
(2)输出以0为对称,解决了Sigmoid函数的非zero-centered问题
缺点:
(1)但是它也存在梯度消失和幂运算的问题。其实 tanh(x)=2sigmoid(2x)-1。
3、ReLU函数:全区间不可导
优点:
(1)解决了gradient vanishing问题 (在正区间)
(1)SGD算法的收敛速度比 sigmoid 和 tanh 快,快6倍;
(2)计算复杂度低,不需要进行指数运算,只需要判断输入是否大于0;
(3)适合用于后向传播。
缺点:
(1)ReLU的输出不是zero-centered;
(2)Dead ReLU Problem(神经元坏死现象)
解释:指的是某些神经元可能永远不会被激活,导致相应的参数永远不能被更新。有两个主要原因可能导致这种情况产生: 1、非常不幸的参数初始化,这种情况比较少见 2、learning rate太高导致在训练过程中参数更新太大,不幸使网络进入这种状态。解决方法是可以采用Xavier初始化方法,以及避免将learning rate设置太大或使用adagrad等自动调节learning rate的算法。
(3)ReLU不会对数据做幅度压缩,所以数据的幅度会随着模型层数的增加不断扩张。
ReLU目前仍是最常用的activation function,在搭建人工神经网络的时候推荐优先尝试!
4、Leakly ReLU函数
优点:
(1)解决ReLU坏死的问题。
人们为了解决Dead ReLU Problem(神经坏死),提出了将ReLU的前半段设为而非0。另外一种直观的想法是基于参数的方法,即Parametric ReLU:,其中可由back propagation学出来。
(2)计算成本低
(3)不饱和
缺点:
(1)不稳定
理论上来讲,Leaky ReLU有ReLU的所有优点,外加不会有Dead ReLU问题,但是在实际操作当中,并没有完全证明Leaky ReLU总是好于ReLU。
5、PRelu(Parametric Rectified Linear Unit), 顾名思义:带参数的ReLU)
方法来自于何凯明paper
优点:
(1)relu优点都有
(2)比起Leaky relu在少于0部分梯度增加了对噪声的鲁棒性
缺点:
没看到,应该和Leaky ReLU 一样可能不稳定吧(没有找到依据,瞎猜的,欢迎指正)
6、ELU函数(指数线性函数)
ELU有ReLU的所有优点
(1)并且不会有 Dead ReLU问题
(2)输出的均值接近0(zero-centered)。
缺点:
(1)但是计算量大,其表现并不一定比ReLU好。。
Maxout
优点:
(1)产生于Leaky Relu,Relu,继承他们的优点
(2)没有梯度消失
缺点:
(1)参数为2倍(神经元为2倍)
解释:一些其他类型的单元被提了出来,它们对于权重和数据的内积结果不再使用函数形式。一个相关的流行选择是Maxout(最近由Goodfellow等发布,在2013年)神经元。Maxout是对ReLU和leaky ReLU的一般化归纳,它的函数是:。ReLU和Leaky ReLU都是这个公式的特殊情况(比如ReLU就是当的时候)。这样Maxout神经元就拥有ReLU单元的所有优点(线性操作和不饱和),而没有它的缺点(死亡的ReLU单元)。然而和ReLU对比,它每个神经元的参数数量增加了一倍,这就导致整体参数的数量激增。
从论文中可以看出,maxout其实一种激发函数形式。通常情况下,如果激发函数采用sigmoid函数的话,在前向传播过程中,隐含层节点的输出表达式为:
其中W一般是2维的,这里表示取出的是第i列,下标i前的省略号表示对应第i列中的所有行。但如果是maxout激发函数,则其隐含层节点的输出表达式为:
这里的W是3维的,尺寸为d*m*k,其中d表示输入层节点的个数,m表示隐含层节点的个数,k表示每个隐含层节点对应了k个”隐隐含层”节点,这k个”隐隐含层”节点都是线性输出的,而maxout的每个节点就是取这k个”隐隐含层”节点输出值中最大的那个值。因为激发函数中有了max操作,所以整个maxout网络也是一种非线性的变换。因此当我们看到常规结构的神经网络时,如果它使用了maxout激发,则我们头脑中应该自动将这个”隐隐含层”节点加入。参考一个日文的maxout ppt 中的一页ppt如下:
ppt中箭头前后示意图大家应该可以明白什么是maxout激发函数了。
maxout的拟合能力是非常强的,它可以拟合任意的的凸函数。最直观的解释就是任意的凸函数都可以由分段线性函数以任意精度拟合(学过高等数学应该能明白),而maxout又是取k个隐隐含层节点的最大值,这些”隐隐含层"节点也是线性的,所以在不同的取值范围下,最大值也可以看做是分段线性的(分段的个数与k值有关)。论文中的图1如下(它表达的意思就是可以拟合任意凸函数,当然也包括了ReLU了):
作者从数学的角度上也证明了这个结论,即只需2个maxout节点就可以拟合任意的凸函数了(相减),前提是”隐隐含层”节点的个数可以任意多,如下图所示:
详细代码见博客:http://www.cnblogs.com/tornadomeet/p/3428843.html
建议:(cs231n课程上的老师原话)
建议使用ReLU函数,但是要注意初始化和learning rate的设置;
可以尝试使用Leaky ReLU或ELU函数;
不建议使用tanh,尤其是sigmoid函数。