Deep Learning Note: 1-6 激活函数

1. 激活函数

1.1 Sigmoid

  在设计神经网络时,需要选择隐藏层和输出层的激活函数(Activation Function)。之前一直使用 Sigmoid 函数作为激活函数:

\begin{equation}
\sigma(z) = \frac{1}{1 + e^{-z}} \tag{1}
\end{equation}

图 1

图 1

  Sigmoid 函数的形状如图 1 所示,其导数为:

\begin{align}
\sigma'(z) & = -(1 + e^{-z})^{-2}(-e^{-z}) \\
& = \frac{e^{-z}}{(1 + e^{-z})^2} \\
& = \frac{1 + e^{-z} – 1}{(1 + e^{-z})^2} \\
& = \frac{1}{1 + e^{-z}} \frac{(1 + e^{-z}) – 1}{1 + e^{-z}} \\
& = \frac{1}{1 + e^{-z}} (1 – \frac{1}{1 + e^{-z}}) \\
& = \sigma(z)(1 – \sigma(z)) \tag{2}
\end{align}

  Sigmoid 是一个有界函数,在各点均有非负的导数。当 $z \rightarrow \infty$ 时,$\sigma(z) \rightarrow 1$;当 $z \rightarrow -\infty$ 时,$\sigma(z) \rightarrow 0$。

1.2. Tanh

  Tanh 函数也是一个常用的激活函数:

\begin{equation}
tanh(z) = \frac{e^z – e^{-z}}{e^z + e^{-z}} \tag{3}
\end{equation}

图 2

图 2

  Tanh 函数的形状如图 2 所示,相当于将 Sigmoid 函数向下平移并在水平方向上压缩得到,即:

\begin{equation}
tanh(z) = 2\sigma(z) – 1 \tag{4}
\end{equation}

  Tanh 函数的导数为:

\begin{align}
tanh'(z) & = -(e^z + e^{-z})^{-2}(e^z – e^{-z})(e^z – e^{-z}) + (e^z + e^{-z})^{-1}(e^z + e^{-z}) \\
& = 1 – \frac{(e^z + e^{-z})^2}{(e^z – e^{-z})^2} \\
& = 1 – tanh^2(x) \tag{5}
\end{align}

  在实际应用中,Tanh 函数的性能几乎总是优于 Sigmoid 函数,因为对于随机的输入,Tanh 函数输出的均值倾向于 0。我们有时候会期望数据具有 0 均值这一特性,以利于下一层的学习,使用 Tanh 函数有助于做到这一点。

  虽然如此,Sigmoid 函数也有自己的用武之地,如用于输出层的激活函数:对于二分类,我们通常希望输出的预测值是一个 0 到 1 之间的概率,使用 Sigmoid 函数可以确保这一点。

  Sigmoid 函数 和 Tanh 函数共同的缺点是,当 $z$ 特别小或特别大的时候,两个函数的斜率都非常小,接近于 0,这会导致梯度下降的速度变慢。

1.3. ReLU

  另一个常用的激活函数称为 ReLU(Rectified Linear Unit),其形式如下:

\begin{equation}
relu(z) = max(0, z) \tag{6}
\end{equation}

图 3

图 3

  ReLU 的形状如图 3 所示,其导数为:

\begin{align}
{relu}'(z) =\begin{cases}0 & z < 0 \\1 & z > 0\end{cases} \tag{7}
\end{align}

  ReLU 的一个缺点是在 $z < 0$ 时斜率为 0。由此衍生出一种 ReLU 的变种,称为 Leaky ReLU,它在 $z < 0$ 时具有很小的斜率,如:

\begin{equation}
leakyrelu(z) = max(0.01z, z) \tag{8}
\end{equation}

  式 (8) 中的 0.01 是个经验值,也可以拿出来作为一个超参数来调优,不过很少有人这么做。

  无论是 ReLU 还是 Leaky ReLU,它们在 $z > 0$ 时保持很高的斜率,可以加快学习的速度。虽然它们在 $z < 0$ 时斜率为 0 或很小,在实际应用中,通常会有足够的隐藏单元输出大于 0 的值,保证学习的速度。

  一般来说,对于二分类问题,选择 Sigmoid 作为输出层的激活函数;对于其他情况,通常选择 ReLU 作为激活函数,也可以尝试 Leaky ReLU。如果难以选择,可以能通过在开发集(Development Set)上测试选出最适合的激活函数。

2. 使用非线性激活函数的原因

  上面介绍的激活函数都是非线性的函数,通常都会选择非线性函数作为激活函数,为模型带来更多的可变性。举例来说,对与前面 使用的模型:

\begin{equation}
z^{[1]} = W^{[1]}a^{[0]} + b^{[1]} \\
a^{[1]} = g(z^{[1]}) \\
z^{[2]} = W^{[2]}a^{[1]} + b^{[2]} \\
a^{[2]} = g(z^{[2]})
\end{equation}

  其中 $g$ 表示激活函数。如果使用一个线性的激活函数,如:

\begin{equation}
g(z) = z
\end{equation}

  则有:
\begin{align}
a^{[1]} = z^{[1]} & = W^{[1]}a^{[0]} + b^{[1]} = W^{[1]}x + b^{[1]} \\
a^{[2]} = z^{[2]} & = W^{[2]}a^{[1]} + b^{[2]} \\
& = W^{[2]}(W^{[1]}x + b^{[1]}) + b^{[2]} \\
& = W^{[2]}W^{[1]}x + (W^{[2]}b^{[1]} + b^{[2]}) \\
& = W’x + b’ \tag{5}
\end{align}

  其中:
\begin{equation}
W’ = W^{[2]}W^{[1]} \\
b’ = W^{[2]}b^{[1]} + b^{[2]}
\end{equation}

  由式 (5) 可见,由于两个线性函数的组合仍是一个线性函数,此时的模型实际上是一个线性模型,隐藏层完全没有作用,只会凭空消耗计算资源。

  使用线性激活函数的一个特例是对于回归(Regression)问题,输出的预测是任意范围的实数,此时可以使用线性函数作为输出层的激活函数,但其他层还是要使用非线性函数作为激活函数。