课上一个偶然的提问让我觉得有必要重新思考一下激活函数,现以Rethinking Activation Function为题写下这篇博客。
Rethinking Activation Function
1. 什么是激活函数?
在深度神经网络中,激活函数是一个必不可少的组件。所谓激活函数(Activation Function),就是在人工神经网络的神经元上运行的函数,负责将神经元的输入映射到输出端。
举一个具体的例子:
神经网络的一个基本范式:
Y
=
f
(
X
∗
W
+
b
)
\textbf Y = f(\textbf X * \textbf W + b)
Y=f(X∗W+b)
其中
f
f
f 就是激活函数,即上图中的阶跃函数。从这个角度看,激活函数就是对前向计算结果做了一次映射。
2. 简单激活函数
2.1 单位阶跃函数
可以看出,阶跃函数是对于小于0的输入激活后输出0,对大于0的输入激活后输出1。显然,这是一个二分类思想,非黑即白。的确,这个函数被用来作为感知器的激活函数,而感知器就是二分类的线性分类模型。(注:感知器用了另一种形式,即符号函数(sign))
那么如果是一个非线性的二分类情况呢?阶跃函数是否也能发挥作用?直观一点,你是否能用一条直线将下图中的圆与正方形分开?显然一条直线是无法分开的。
那么阶跃函数为什么不能表达非线性问题呢?这里我只从直观上解释一下,希望有大佬可以在评论区补充详细的数学证明!
因为阶跃函数只是对一条直线两侧的内容作了一个判别。
3. 为什么需要激活函数?
看了2节的内容你可能已经感受到神经网络为什么需要激活函数了。前方高能:
(1)学习一种映射;(2)学习一种复杂映射。
对于(1),神经网络的目的就是学习一种映射,感知器学习了一种二分类映射。从这个角度看,激活函数是为了希望模型学习一种表达能力。那么如果要学习非线性的映射能力怎么办呢?换一个更复杂的激活函数是否可以达到目的呢?可以!
对于(2),通过引入非线性的激活函数,使得神经网络能够学习任意复杂的映射(即表示输入输出之间非线性的复杂的任意函数映射)。从这个角度看,激活函数是用来加入非线性因素的,提高神经网络对模型的表达能力,解决线性模型所不能解决的问题。
4. 进阶激活函数
先看来看看是哪些复杂的函数使得神经网络能够学习复杂的非线性表达能力。
4.1 Sigmoid
相比于阶跃函数,Sigmoid函数能够表达非线性能力。值域区间在0和1之间,是一个S形曲线。(注:值域在0-1之间与概率有着天然的联系)
但是sigmoid也有缺点:
- Sigmoid函数饱和会造成梯度消失问题;
- Sigmoids函数收敛缓慢;
- 梯度剧烈变化。
另外,Sigmoid函数有一个重要的性质:
1
−
g
(
s
)
=
g
(
−
s
)
1 - g(s) = g(-s)
1−g(s)=g(−s)
4.2 tanh
注:tanh函数值域为[-1, 1],思考一下为什么值域在[-1, 1]更好?
4.3 ReLU
ReLu - Rectified linear units(线性修正单元):
为什么要使用ReLu呢?收敛速度快!
但也存在问题:
- 只能在神经网络模型的隐藏层中使用,输出层使用Softmax(参见博客)。
- 一些梯度在训练过程中可能很脆弱,甚至可能会死亡。简单地说ReLu可能会导致死亡神经元。
注:为了解决这个问题2,我们引进了另一个被称为Leaky ReLu的修改函数,让它来解决死亡神经元的问题。它引入了一个小斜坡从而保持更新值具有活力。然后,我们还有另一个变体,它形成于ReLu函数和Leaky ReLu函数的结合,我们称之为Maxout函数。
4.4 Softmax
对于Softmax的详细讲解参见博客,这里只作简单介绍。
其中,ai为神经网络输出,n为输出个数(即分类类别数)。
对于文中的代码,如有需要可以留下邮箱私发~
再推荐两篇博客,互补一下:
https://www.cnblogs.com/ya-qiang/p/9258714.html
https://blog.csdn.net/qq_23304241/article/details/80300149