目的
神经元引入非线性因素,从而使神经网络能够解决线性不可分的问题,比如最简单的异或。
Hornik证明,只需一个包含足够多的神经元的隐层,多层前馈网络就能以任意精度逼近任意复杂度的连续函数。因此使得神经网络可以任意逼近任何非线性函数,这样神经网络就可以应用到众多的非线性模型中。
如果不用激励函数,每一层输出都是上层输入的线性函数,无论神经网络有多少层,输出都是输入的线性组合。则多层网络退化为单层网络。
常用激活函数
比较经典的函数包括:Sigmoid函数、tanh函数、ReLU函数。
一个好的激活函数,通常要满足以下性质:
- 非线性:即导数不是常数
- 可微性:保证了在优化中梯度的可计算性。虽然 ReLU 存在有限个点处不可微,但处处 subgradient,可以替代梯度。
- 计算简单:激活函数复杂就会降低计算速度,因此 RELU 要比 sigmoid等带有Exp操作的激活函数更受欢迎。
- 非饱和性(saturation):饱和指的是在某些区间梯度接近于零(即梯度消失),使得参数无法继续更新的问题。最经典的例子是 Sigmoid,它的导数在 x 为比较大的正值和比较小的负值时都会接近于 0。RELU 对于 x<0,其梯度恒为 0,这时候它也会出现饱和的现象。Leaky ReLU 和 PReLU 的提出正是为了解决这一问题。
- 单调性(monotonic):即导数符号不变。当激活函数是单调的时候,单层网络能够保证是凸函数。但是激活函数如 mish 等并不满足单调的条件,因此单调性并不是硬性条件,因为神经网络本来就是非凸的。
- 参数少:大部分激活函数都是没有参数的。像 PReLU 带单个参数会略微增加网络的大小。还有一个例外是 Maxout,尽管本身没有参数,但在同样输出通道数下 k 路 Maxout 需要的输入通道数是其它函数的 k 倍,这意味着神经元数目也需要变为 k 倍。
激活函数优缺点
Sigmoid激活函数
优点:
- 梯度平滑,求导容易
- 输出值在 0-1 之间
缺点:
- 激活函数计算量大(在正向传播和反向传播中都包含幂运算和除法);
- 梯度消失:输入值较大或较小(图像两侧)时,sigmoid 函数值接近于零。sigmoid 导数则接近于零,导致最终的梯度接近于零,无法实现更新参数的目的;
- Sigmoid 的输出不是 0 为中心(zero-centered)。这个特性会导致后面网络层的输入也不是零中心的,进而影响梯度下降的运作。
sigmoid为何会出现梯度消失:
反向传播算法中,要对激活函数求导,sigmoid 的导数表达式为:
sigmoid 原函数及导数图形如下:
由图可知,导数从 0 开始很快就又趋近于 0 了,易造成“梯度消失”现象
梯度消失的解决之道:一般来说, sigmoid 网络在 5 层之内就会产生梯度消失现象。梯度消失问题至今仍然存在,但被新的优化方法有效缓解了,例如DBN中的分层预训练,Batch Normalization的逐层归一化,Xavier和MSRA权重初始化等代表性技术。
为什么追求0为中心(zero-centered):越接近0为中心,SGD会越接近 natural gradient(一种二次优化技术),从而降低所需的迭代次数。
tanh函数
双曲正切函数取值范围为[-1,1]。
tanh在特征相差明显时的效果会很好,在循环过程中会不断扩大特征效果。
优点:
- 比Sigmoid函数收敛速度更快。
- 相比Sigmoid函数,其输出以0为中心。
缺点:
没有改变Sigmoid函数的最大问题——由于饱和性产生的梯度消失。
ReLU函数
优点:
由于不需要做指数运算,使用 ReLU 得到的 SGD 的收敛速度会比 sigmoid、tanh 快很多
缺点:
- 训练的时候很“脆弱”,随着训练的进行,可能会出现神经元死亡,权重无法更新的情况。例如,一个非常大的梯度流过一个 ReLU 神经元,更新过参数之后,这个神经元再也不会对任何数据有激活现象了,那么这个神经元的梯度就永远都会是 0,也就是说,ReLU神经元在训练中不可逆地死亡了。如果 learning rate 很大,那么很有可能网络中的 40% 的神经元都”dead”了。
- ReLU的输出具有偏移现象,即输出均值恒大于零。偏移现象和神经元死亡会共同影响网络的收敛性。
针对RELU的缺陷,后续有多种改进函数(Leaky ReLU、PReLU 或者 Maxout),这里不详细展开。
拓展:饱和性
Bengio 教授等将只有在极限状态下偏导数等于0的函数定义为软饱和激活函数;相对应的,对任意的x,如果存在常数c,当x>c或x<c时恒有 h′(x)=0则称其为右/左硬饱和,当x比c小时恒 有h′(x)=0则称其为左硬饱和。若既满足左硬饱和,又满足右硬饱和,则称这种激活函数为硬饱和。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。