激活函数

介绍激活函数及其特性

  • Sigmoid
  • Tanh
  • ReLU
  • Leaky ReLU
  • Maxout

Sigmoid

Sigmoid函数是最早出现的激活函数,估计是因为逻辑回归模型的缘故

它能够将输入数据压缩到[0,1]之间,值越小,越接近于0;值越大,越接近于1。数学公式如下:

$$
\sigma (x)=\frac{1}{1+e^{-x}}
$$

$$
\frac {\varphi \sigma (x)}{\varphi x}=
\frac{-1}{(1+e^{-x})^2}\cdot e^{-x} \cdot (-1)=
\frac{1}{1+e^{-x}}\cdot \frac{e^{-x}}{1+e^{-x}}=
\sigma (x)\cdot (1-\sigma (x))
$$

目前基本不使用Sigmoid作为激活函数,主要有两个缺陷

  1. 当激活值处于饱和(saturate)状态(接近01),此时得到的梯度几乎为0如下图所示),也就是说无法在反向传播过程中对权重进行有效更新,网络也将停止学习。所以初始化权重值不能过大,否则会导致激活函数饱和
  2. 因为Sigmoid的取值范围是[0,1],所以其输出不是零中心(zero-centered)。如果输入的数据总是正值,会导致计算得到的梯度值变为全正或全负(*依赖于线性运算的表达式$f$*)。非零中心会导致权重更新时呈$Z$字形下降,这个问题可以通过初始化权重时平衡正负值来减轻影响
1
2
3
4
5
def sigmoid(x):
return 1.0 / (1 + np.exp(-1 * x))

def dsigmoid(x):
return sigmoid(x) * (1 - sigmoid(x))

Tanh

Tanh(全局正切)函数在Sigmoid函数的基础上进一步发展,其将取值压缩在[-1,1]之间,值越小,越接近于-1;值越大,越接近于1。数学公式如下:

$$
tanh(x) = \frac{e^{x}-e^{-x}}{e^{x}+e^{-x}}=\frac{1-e^{-2x}}{1+e^{-2x}}=\frac{2-(1+e^{-2x})}{1+e^{-2x}}=2\sigma (2x)+1
$$

$$
\frac {\varphi tanh(x)}{\varphi x}=
\frac {v(x)’\cdot u(x)-v(x)\cdot u(x)’}{u(x)^2}
$$

其中

$$
v(x)=e^{x}-e^{-x}
\Rightarrow {v(x)}’= e^{x}+e^{-x} \
u(x)=e^{x}+e^{-x}
\Rightarrow {u(x)}’= e^{x}-e^{-x}
$$

所以

$$
\frac {\varphi tanh(x)}{\varphi x}=\frac {u(x)^2-v(x)^2}{u(x)^2}=
1-(tanh(x))^2
$$

根据公式可知,$tanh$函数是$sigmoid$函数的扩展,它解决了输出零中心的问题

1
2
3
4
5
6
7
8
def tanh(x):
x1 = np.exp(x)
x2 = np.exp(-1 * x)
return (x1 - x2) / (x1 + x2)
# return 2 * sigmoid(2 * x) + 1

def dtanh(x):
return 1 - tanh(x) ** 2

ReLU

ReLU(Rectified Linear Unit,整流线性单元)激活函数是因为在AlexNet网络中的使用而得到了推广。当输入小于0时,输出为0;否则,输入为输出值。其数学公式如下:

$$
f(x)=\max (0,x)
$$

$$
\frac {\varphi f(x)}{\varphi x}=
\left{\begin{matrix}
0, x<0\
1, x\geq 0
\end{matrix}\right.
=1(x\geq 0)
$$

优势如下:

  1. 计算高效。达到同样训练误差率的时间,使用ReLU能够比tanh6
  2. 实现简单。相比于sigmoid/tanh需要指数运算,ReLU仅是线性阈值操作

缺陷如下:

  1. 输出值没有零中心
  2. 当输入值小于0时,梯度消失,权值不再更新

如果步长(learning rate,学习率)设置过大,有可能导致梯度更新后,神经元线性计算结果永远小于0,无法再次更新权值,也就是说这个神经元在训练过程中死亡了,所以需要合理设置步长大小

1
2
3
4
5
def relu(x):
return np.array(list(map(lambda x: x if x > 0 else 0, x)))

def drelu(x):
return x >= 0

Leaky ReLU

Leaky ReLU试图解决ReLU单侧梯度消失的问题,其实现公式如下:

$$
f(x)=I (x<0)(ax)+I (x>=0)(x)
$$

$$
\frac {\varphi f(x)}{\varphi x}=
\left{\begin{matrix}
a, x<0\
1, x\geq 0
\end{matrix}\right.
$$

其中$a$是一个超参数,通常是一个很小的常数(比如$0.01$),这样当输入值小于$0$时仍旧能够进行权重更新

1
2
3
4
5
def leaky_relu(x, a=0.01):
return np.array(list(map(lambda x: x if x > 0 else a * x, x)))

def dleaky_relu(x, a=0.01):
return np.array(list(map(lambda x: 1 if x > 0 else a, x)))

小结

推荐使用顺序:ReLU > Leaky ReLU > Tanh > Sigmoid

相关阅读