一文详解常用的**函数

常见的**函数及其特点

什么是**函数?

神经网络中的每个神经元节点接受上一层神经元的输出值作为本神经元的输入值,并将输入值传递给下一层,输入层神经元节点会将输入属性值直接传递给下一层(隐层或输出层)。在多层神经网络中,上层节点的输出和下层节点的输入之间具有一个函数关系,这个函数称为**函数(又称激励函数)。

**函数的用途(为什么需要**函数)?

如果不用激励函数(其实相当于激励函数是f(x)=x),在这种情况下你每一层节点的输入都是上层输出的线性函数,很容易验证,无论你神经网络有多少层,输出都是输入的线性组合,与没有隐藏层效果相当,这种情况就是最原始的感知机(Perceptron)了,那么网络的逼近能力就相当有限。正因为上面的原因,我们决定引入非线性函数作为激励函数,这样深层神经网络表达能力就更加强大(不再是输入的线性组合,而是几乎可以逼近任意函数)。

sigmoid

Sigmoid 是常用的非线性的**函数,它的数学形式如下:

一文详解常用的**函数

Sigmoid的几何图像如下:

一文详解常用的**函数

特点:

它能够把输入的连续实值变换为0和1之间的输出,特别的,如果是非常大的负数,那么输出就是0;如果是非常大的正数,输出就是1.

缺点:

缺点1:在深度神经网络中梯度反向传递时导致梯度爆炸和梯度消失,其中梯度爆炸发生的概率非常小,而梯度消失发生的概率比较大。首先来看Sigmoid函数的导数,如下图所示:

一文详解常用的**函数

如果我们初始化神经网络的权值为 [0,1] 之间的随机值,由反向传播算法的数学推导可知,梯度从后向前传播时,每传递一层梯度值都会减小为原来的0.25倍,如果神经网络隐层特别多,那么梯度在穿过多层后将变得非常小接近于0,即出现梯度消失现象;当网络权值初始化为 (1,+∞) 区间内的值,则会出现梯度爆炸情况。

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

缺点2:Sigmoid 的 output不是0均值(即zero-centered)。这是不可取的,因为这会导致后一层的神经元将得到上一层输出的非0均值的信号作为输入。 产生的一个结果就是:如x>0,f= w^Tx+b ,那么对w求局部梯度则都为正,这样在反向传播的过程中w要么都往正方向更新,要么都往负方向更新,导致有一种捆绑的效果,使得收敛缓慢。 当然了,如果按batch去训练,那么那个batch可能得到不同的信号,所以这个问题还是可以缓解一下的。因此,非0均值这个问题虽然会产生一些不好的影响,不过跟上面提到的梯度消失问题相比还是要好很多的。

缺点3:其解析式中含有幂运算,计算机求解时相对来讲比较耗时。对于规模比较大的深度网络,这会较大地增加训练时间。

tanh

tanh函数解析式:

一文详解常用的**函数

tanh函数及其导数的几何图像如下图:

一文详解常用的**函数

tanh读作Hyperbolic Tangent,它解决了Sigmoid函数的不是zero-centered输出问题,收敛速度比sigmoid要快,然而,梯度消失(gradient vanishing)的问题和幂运算的问题仍然存在。

ReLU及其变体

Relu函数

Relu函数的解析式:

一文详解常用的**函数

Relu函数及其导数的图像如下图所示:

一文详解常用的**函数

ReLU函数其实就是一个取最大值函数,注意这并不是全区间可导的,但是我们可以取sub-gradient,如上图所示。ReLU虽然简单,但却是近几年的重要成果,有以下几大优点:

1) 解决了gradient vanishing问题 (在正区间)

2)计算速度非常快,只需要判断输入是否大于0

3)收敛速度远快于sigmoid和tanh

ReLU也有几个需要特别注意的问题:

1)ReLU的输出不是zero-centered

2)Dead ReLU Problem,指的是某些神经元可能永远不会被**,导致相应的参数永远不能被更新

有两个主要原因可能导致这种情况产生:

(1)非常不幸的参数初始化,这种情况比较少见
(2)learning rate太高导致在训练过程中参数更新太大,不幸使网络进入这种状态。解决方法是可以采用He初始化方法,以及避免将learning rate设置太大或使用adagrad等自动调节learning rate的算法。

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

Leaky ReLU函数(PReLU)

函数表达式:

一文详解常用的**函数

Leaky Relu函数及其导数的图像如下图所示:

一文详解常用的**函数

人们为了解决Dead ReLU Problem,提出了将ReLU的前半段设为αx而非0,通常α=0.01。另外一种直观的想法是基于参数的方法,即ParametricReLU:f(x)=max(αx,x) ,其中α
可由方向传播算法学出来。理论上来讲,Leaky ReLU有ReLU的所有优点,外加不会有Dead ReLU问题,但是在实际操作当中,并没有完全证明Leaky ReLU总是好于ReLU。

ELU (Exponential Linear Units) 函数

函数表达式:

一文详解常用的**函数

函数及其导数的图像如下图所示:

一文详解常用的**函数

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

1. 不会有Dead ReLU问题

2. 输出的均值接近0,zero-centered

不过还是有梯度饱和和指数运算的问题。

Maxout

Maxout可以看做是在深度学习网络中加入一层**函数层,包含一个参数k.这一层相比ReLU,sigmoid等,其特殊之处在于增加了k个神经元,然后输出**值最大的值.
我们常见的隐含层节点输出:
一文详解常用的**函数

而在Maxout网络中,其隐含层节点的输出表达式为:

一文详解常用的**函数

一文详解常用的**函数

然而任何一个凸函数,都可以由线性分段函数进行逼近近似。其实我们可以把以前所学到的**函数:relu、abs**函数,看成是分成两段的线性函数,如下示意图所示:

一文详解常用的**函数

maxout的拟合能力是非常强的,它可以拟合任意的的凸函数。最直观的解释就是任意的凸函数都可以由分段线性函数以任意精度拟合(学过高等数学应该能明白),而maxout又是取k个隐隐含层节点的最大值,这些”隐隐含层"节点也是线性的,所以在不同的取值范围下,最大值也可以看做是分段线性的(分段的个数与k值有关)

以如下最简单的多层感知器(MLP)为例:

一文详解常用的**函数

假设网络第i层有2个神经元x1、x2,第i+1层的神经元个数为1个.原本只有一层参数,将ReLU或sigmoid等**函数替换掉,引入Maxout,将变成两层参数,参数个数增为k倍.

优点:

  • Maxout的拟合能力非常强,可以拟合任意的凸函数。
  • Maxout具有ReLU的所有优点,线性、不饱和性。
  • 同时没有ReLU的一些缺点。如:神经元的死亡。

缺点:
从上面的**函数公式中可以看出,每个神经元中有多组(w,b)参数,那么参数量就增加了k倍,这就导致了整体参数的数量激增。

softmax

一文详解常用的**函数

应用中如何选择合适的**函数?

这个问题目前没有确定的方法,凭一些经验吧。

1)深度学习往往需要大量时间来处理大量数据,模型的收敛速度是尤为重要的。所以,总体上来讲,训练深度学习网络尽量使用zero-centered数据 (可以经过数据预处理实现) 和zero-centered输出。所以要尽量选择输出具有zero-centered特点的**函数以加快模型的收敛速度。

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

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

神经网络的输入为什么要0均值化

这样做的优点是为了在反向传播中加快网络中每一层权重参数的收敛。为什么0均值化就会加快收敛呢?
一文详解常用的**函数

在梯度下降的时候,假设图中蓝色箭头方向理想最优向量,根据上述公式,我们可以想一想:

当x全为正或者全为负时,每次返回的梯度都只会沿着一个方向发生变化,这样就会使得权重收敛效率很低。

但当x正负数量“差不多”时,那么梯度的变化方向就会不确定,这样就能达到上图中的变化效果,加速了权重的收敛。

参考

常用**函数(激励函数)理解与总结

常见**函数特点分析

几种常用**函数的简介

**函数(ReLU, Swish, Maxout)

深度学习(二十三)Maxout网络学习

GitHub

个人主页