引言
学习神经网络的时候我们总是听到激活函数这个词,常用的激活函数,比如Sigmoid函数、tanh函数、Relu函数。
Question:
什么是激活函数?
为什么需要激活函数?
有哪些激活函数,都有什么性质和特点?
应用中如何选择合适的激活函数?
什么是激活函数?
首先要了解神经网络的基本模型:
神经网络中的每个神经元节点接受上一层神经元的输出值作为本神经元的输入值,并将输入值传递给下一层,输入层神经元节点会将输入属性值直接传递给下一层(隐层或输出层)。在多层神经网络中,上层节点的输出和下层节点的输入之间具有一个函数关系,这个函数称为激活函数(又称激励函数)。
为什么需要激活函数?
如果不用激励函数(其实相当于激励函数是f(x) = x),在这种情况下你每一层节点的输入都是上层输出的线性函数,很容易验证,无论你神经网络有多少层,输出都是输入的线性组合,与没有隐藏层效果相当,这种情况就是最原始的感知机(Perceptron)了,那么网络的逼近能力就相当有限。正因为上面的原因,我们决定引入非线性函数作为激励函数,这样深层神经网络表达能力就更加强大(不再是输入的线性组合,而是几乎可以逼近任意函数)。
举个简单的例子,二分类问题,如果不使用激活函数,例如使用简单的逻辑回归,只能作简单的线性划分,如下图所示:
如果使用激活函数,则可以实现非线性划分,如下图所示:
Q:为什么激活函数一般都是非线性的,而不能是线性的呢?
A:从反面来说,如果所有的激活函数都是线性的,则激活函数 g(z)=z,即 a=z。那么,以两层神经网络为例,最终的输出为:
经过推导我们发现网络输出仍是 X 的线性组合。这表明,使用神经网络与直接使用线性模型的效果并没有什么两样。即便是包含多层隐藏层的神经网络,如果使用线性函数作为激活函数,最终的输出仍然是线性模型。这样的话神经网络就没有任何作用了。因此,隐藏层的激活函数必须要是非线性的。
值得一提的是,如果所有的隐藏层全部使用线性激活函数,只有输出层使用非线性激活函数,那么整个神经网络的结构就类似于一个简单的逻辑回归模型,效果与单个神经元无异。另外,如果是拟合问题而不是分类问题,输出层的激活函数可以使用线性函数。
有哪些激活函数,都有什么性质和特点?
早期研究神经网络主要采用sigmoid函数或者tanh函数,输出有界,很容易充当下一层的输入。
近些年Relu函数及其改进型(如Leaky-ReLU、P-ReLU、R-ReLU等)在多层神经网络中应用比较多。
总结下这些激活函数:
(1) Sigmoid函数
Sigmoid 是常用的非线性的激活函数,它的数学形式如下:
Sigmoid的几何图像如下:
特点:
它能够把输入的连续实值变换为0和1之间的输出,特别的,如果是非常大的负数,那么输出就是0;如果是非常大的正数,输出就是1.
缺点:
sigmoid函数曾经被使用的很多,不过近年来,用它的人越来越少了。主要是因为它固有的一些缺点。
缺点1:
在深度神经网络中梯度反向传递时导致梯度爆炸和梯度消失,其中梯度爆炸发生的概率非常小,而梯度消失发生的概率比较大。首先来看Sigmoid函数的导数,如下图所示:
饱和区如下图所示:
上图中红色椭圆标注的饱和区曲线平缓,梯度的值很小,近似为零。而且 Sigmoid 函数的饱和区范围很广,例如除了 [-5,5],其余区域都近似饱和区。这种情况很容易造成梯度消失,梯度消失会增大神经网络训练难度,影响神经网络模型的性能。
其次,Sigmoid 函数输出是非零对称的,即输出恒大于零。这会产生什么影响呢?我们来看,假如 Sigmoid 函数的输出为 σ(Wx+b),且满足 0<σ(Wx+b)<1。在反向求导过程中,令损失函数 J 对 σ(Wx+b) 的求导为 dσ,现在计算 J 对 W 的偏导数:
缺点2:
Sigmoid 函数输出是非零对称的,即输出恒大于零。这是不可取的,因为这会导致后一层的神经元将得到上一层输出的非0均值的信号作为输入。 产生的一个结果就是:
这会产生什么影响呢?我们来看,假如 Sigmoid 函数的输出为 σ(Wx+b),且满足 0<σ(Wx+b)<1。在反向求导过程中,令损失函数 J 对 σ(Wx+b) 的求导为 dσ,现在计算 J 对 W 的偏导数:
其中,σ(Wx+b)>0,1-σ(Wx+b)>0。
若神经元的输入 x>0,则无论 dσ 正负如何,总能得到 dW 恒为正或者恒为负。也就是说参数矩阵 W 的每个元素都会朝着同一个方向变化,同为正或同为负。这对于神经网络训练是不利的,所有的 W 都朝着同一符号方向变化会减小训练速度,增加模型训练时间。
值得一提的是,针对 Sigmoid 函数的这一问题,神经元的输入 x 常会做预处理,即将均值归一化到零值。这样也能有效避免 dW 恒为正或者恒为负。
缺点3:
其解析式中含有幂运算exp,计算机求解时相对来讲比较耗时。对于规模比较大的深度网络,这会较大地增加训练时间。
(2) tanh函数
tanh函数解析式:
tanh函数及其导数的几何图像如下图:
tanh 函数的取值范围在 (-1,1) 之间,单调连续,求导容易。
相比于 Sigmoid 函数,tanh 函数的优点主要有两个:
其一,收敛速度更快,如下图所示,tanh 函数线性区斜率较 Sigmoid 更大一些。在此区域内训练速度会更快。
其二,tanh 函数输出均值为零,也就不存在 Sigmoid 函数中 dW 恒为正或者恒为负,解决了Sigmoid函数的不是zero-centered输出问题,然而,梯度消失(gradient vanishing)的问题和幂运算的问题仍然存在。
(3) ReLU函数
激活函数 ReLU 的全称是 Rectified Linear Unit,Relu函数的解析式:
Relu函数及其导数的图像如下图所示:
ReLU函数其实就是一个取最大值函数,注意这并不是全区间可导的,但是我们可以取sub-gradient,如上图所示。ReLU虽然简单,但却是近几年的重要成果,有以下几大优点:
1) 没有饱和区,不存在梯度消失问题。 (在正区间)
2)计算速度非常快,只需要判断输入是否大于0。
3)收敛速度远快于sigmoid和tanh,大约是 Sigmoid/tanh 的 6 倍,比 Sigmoid 更符合生物学神经激活机制。
ReLU也有几个需要特别注意的问题:
1)ReLU的输出不是zero-centered,ReLU 的输出仍然是非零对称的,可能出现 dW 恒为正或者恒为负,从而影响训练速度。
2)Dead ReLU Problem,指的是某些神经元可能永远不会被激活,导致相应的参数永远不能被更新:当 x<0 时,ReLU 输出总为零。该神经元输出为零,则反向传播时,权重、参数的梯度横为零,造成权重、参数永远不会更新,即造成神经元失效,形成了“死神经元”。所以,针对这一问题,有时候会将 ReLU 神经元初始化为正偏值,例如 0.01。
有两个主要原因可能导致这种情况产生:
(1) 非常不幸的参数初始化,这种情况比较少见。
(2) learning rate太高导致在训练过程中参数更新太大,不幸使网络进入这种状态。解决方法是可以采用Xavier初始化方法,以及避免将learning rate设置太大或使用adagrad等自动调节learning rate的算法。
(4) Leaky ReLU函数(PReLU)
PReLU函数的解析式:
PReLU函数及其导数的图像如下图所示:
PS:左半边直线斜率非常接近0,所以看起来像是平的。就不改了, α = 0.01看起来就是这样的.
优点:
(1)没有饱和区,不存在梯度消失问题。
(2)没有复杂的指数运算,计算简单、效率提高。
(3)实际收敛速度较快,大约是 Sigmoid/tanh 的 6 倍。
(4)不会造成神经元失效,形成了“死神经元”。
当然,0.01 的系数是可调的,一般不会太大。
(5)ELU (Exponential Linear Units) 函数
ELU 函数的解析式:
函数及其导数的图像如下图所示:
ELU 继承了 Leaky ReLU 的所有优点
优点:
(1)没有饱和区,不存在梯度消失问题。
(2)没有复杂的指数运算,计算简单、效率提高。
(3)实际收敛速度较快,大约是 Sigmoid/tanh 的 6 倍。
(4)不会造成神经元失效,形成了“死神经元”。
(5)输出均值为零
(6)负饱和区的存在使得 ELU 比 Leaky ReLU 更加健壮,抗噪声能力更强。
缺点:
ELU 包含了指数运算,存在运算量较大的问题。
(6) MaxOut函数
MaxOut 函数的解析式:
Maxout 的拟合能力是非常强的,它可以拟合任意的的凸函数。最直观的解释就是任意的凸函数都可以由分段线性函数以任意精度拟合,而 Maxout 又是取 k 个隐藏层节点的最大值,这些”隐藏层"节点也是线性的,所以在不同的取值范围下,最大值也可以看做是分段线性的(上面的公式中 k = 2)。
应用中如何选择合适的激活函数?
这个问题目前没有确定的方法,凭一些经验吧。
1)深度学习往往需要大量时间来处理大量数据,模型的收敛速度是尤为重要的。所以,总体上来讲,训练深度学习网络尽量使用zero-centered数据 (可以经过数据预处理实现) 和zero-centered输出。所以要尽量选择输出具有zero-centered特点的激活函数以加快模型的收敛速度。
2)如果使用 ReLU,那么一定要小心设置 learning rate,而且要注意不要让网络出现很多 “dead” 神经元,如果这个问题不好解决,那么可以试试 Leaky ReLU、PReLU 或者 Maxout.
3)最好不要用 sigmoid,你可以试试 tanh,不过可以预期它的效果会比不上 ReLU 和 Maxout.