一、tanh函数
使用一个神经网络时,需要决定使用哪种激活函数用在隐藏层上,哪种用在输出节点上。到目前为止,我们只介绍过sigmoid激活函数,但是,有时其他的激活函数效果会更好。
在神经网络的前向传播中,
a
[
1
]
=
σ
(
z
[
1
]
)
a^{[1]} = \sigma(z^{[1]})
a[1]=σ(z[1])和
a
[
2
]
=
σ
(
z
[
2
]
)
a^{[2]} = \sigma(z^{[2]})
a[2]=σ(z[2])这两步会用到sigmoid激活函数。
a
=
σ
(
z
)
=
1
1
+
e
−
z
a = \sigma(z) = \frac{1}{1 + e^{-z}}
a=σ(z)=1+e−z1
更通常情况下,使用不同的函数
g
(
z
[
1
]
)
g(z^{[1]})
g(z[1]),
g
g
g可以是除了sigmoid函数之外的非线性函数。tanh函数或者双曲正切函数是总体上都优于sigmoid函数的激活函数。
如图, a = t a n ( z ) a = tan(z) a=tan(z)的值域是位于 + 1 +1 +1和 − 1 -1 −1之间的。
事实上,tanh函数时sigmoid的向下平移和伸缩后的结果,对它进行了变形后,图像穿过了原点,并且值域介于 − 1 -1 −1和 + 1 +1 +1之间。
结果表明,如果在隐藏层上使用函数 g ( z [ 1 ] ) = t a n h ( z [ 1 ] ) g(z^{[1]}) = tanh(z^{[1]}) g(z[1])=tanh(z[1])效果总是优于sigmoid函数。因为函数值在 − 1 -1 −1和 + 1 +1 +1的激活函数,其均值是更接近零均值的。在训练一个算法模型时,如果使用tanh函数代替sigmoid函数中心化数据,使得数据的平均值更接近 0 0 0而不是 0.5 0.5 0.5。这会使下一层学习简单一点,原因我们会在之后解释。
在讨论优化算法时,tanh函数在几乎所有场合都优于sigmoid函数。
但也有一个例外:在二分类问题中,对于输出层,因为 y y y的值是 0 0 0或 1 1 1,所以想让 y ^ \hat{y} y^的数值介于其中,而不是 − 1 -1 −1和 1 1 1之间,我们需要使用sigmoid函数。我们可以在隐藏层使用tanh函数,在输出层使用sigmoid函数。
所以,在不同的神经网络层中,激活函数可以不同。
sigmoid函数和tanh函数两者共同的缺点是,在 z z z特别大或者特别小的情况下,导数的梯度或者说函数的斜率会变得特别小,最后就会接近于 0 0 0,导致梯度下降的速度降低。
二、ReLU函数
在机器学习中另一个很流行的函数是,修正线性单元的函数(ReLU),ReLU函数 a = m a x ( 0 , z ) a = max(0,z) a=max(0,z)图像如下图。所以,只要 z z z是正值的情况下,导数恒等于 1 1 1,当 z z z是负值的时,导数恒等于 0 0 0。从实际上来说,当使用 z z z的导数时, z = 0 z=0 z=0 的导数时没有定义的。但是当编程实现的时候, z z z的取值刚好等于 0.00000001 0.00000001 0.00000001,其导数值相当小。所以在实践中,不需要担心这个值, z z z等于 0 0 0 的时候,假设一个导数为 1 1 1或 0 0 0都可以。
还有一些选择激活函数的经验法则:
如果输出是0、1值(二分类问题),则输出层选择sigmoid函数,然后其他的所有单元都选择ReLU函数。
这是很多激活函数的默认选择,如果在隐藏层上不确定使用哪个激活函数,那么通常会使用ReLU激活函数。有时也会使用tanh函数,但ReLU的一个优点是:当 z z z为负值的时候,导数等于 0 0 0。
这里也有另一个版本的ReLU被称为Leaky ReLU。
LeakyReLU
(
x
)
=
{
x
,
x
>
0
α
x
,
x
≤
0
\text { LeakyReLU }(x)=\left\{\begin{array}{cl} x & , x>0 \\ \alpha x & , x \leq 0 \end{array}\right.
LeakyReLU (x)={xαx,x>0,x≤0
当
z
z
z为负值时,这个函数的值不是等于0,而是轻微(
α
\alpha
α值较小)的倾斜。
这个函数通常比ReLU激活函数效果要好,尽管在实际中Leaky ReLU使用的并不多。
二者的优点是:
第一,在 z z z的区间变动很大的情况下,激活函数的导数或者激活函数的斜率都会远大于 0,在程序实现就是一个 if-else语句,而sigmoid函数需要进行浮点四则运算,在实践中,使用ReLU激活函数神经网络通常会比使用 sigmoid或者tanh激活函数学习的更快。
第二,sigmoid和tanh函数的导数在正负饱和区的梯度都会接近于 0,这会造成梯度弥散,而ReLU和Leaky ReLU函数大于 0 部分都为常数,不会产生梯度弥散现象。(同时应该注意到的是,ReLU进入负半区的时候,梯度为 0,神经元此时不会训练,产生所谓的稀疏性, 而Leaky ReLU不会有这问题)
z z z在ReLU的梯度一半都是 0,但是,有足够的隐藏层使得 z z z 值大于 0,所以对大多数的训练数据来说学习过程仍然可以很快。
三、激活函数的比较
快速概括一下不同激活函数的过程和结论。
sigmoid激活函数:除了输出层是一个二分类问题基本不会用它。
tanh激活函数:tanh是非常优秀的,几乎适合所有场合。
ReLU激活函数:最常用的默认函数,如果不确定用哪个激活函数,就使用ReLU或者Leaky ReLU。
鉴于以上三个原因,以及在工业界的见闻,提供一种直观的感受,哪一种工业界用的多, 哪一种用的少。但是,自己的神经网络的应用,以及其特殊性,是很难提前知道选择哪些效 果更好。所以通常的建议是:如果不确定哪一个激活函数效果更好,可以把它们都试试,然后在验证集或者发展集上进行评价。然后看哪一种表现的更好,就去使用它。
为自己的神经网络的应用测试这些不同的选择,会在以后检验自己的神经网络或者评估算法的时候,看到不同的效果。如果仅仅遵守使用默认的ReLU激活函数,而不要用其他的激励函数,那就可能在近期或者往后,每次解决问题的时候都使用相同的办法。
四、为什么需要非线性激活函数
为什么神经网络需要非线性激活函数?事实证明:要让你的神经网络能够计算出有趣的函数,你必须使用非线性激活函数,证明如下:
这是神经网络正向传播的方程,现在我们去掉函数 g g g,然后令 a [ 1 ] = z [ 1 ] a^{[1]} = z^{[1]} a[1]=z[1],或者我们也可以令 g ( z ) = z g(z) = z g(z)=z,这个有时被叫做线性激活函数(更学术点的名字是恒等激励函数,因为它们就是把输入值输出)。为了说明问题我们把 a [ 2 ] = z [ 2 ] a^{[2]} = z^{[2]} a[2]=z[2],那么这个模型的输出 y y y或仅仅只是输入特征 x x x的线性组合。
如果我们改变前面的式子,令:
(
1
)
a
[
1
]
=
z
[
1
]
=
W
[
1
]
x
+
b
[
1
]
(
2
)
a
[
2
]
=
z
[
2
]
=
W
[
2
]
a
[
1
]
+
b
[
2
]
(1) a^{[1]} = z^{[1]} = W^{[1]}x + b^{[1]} \\ (2) a^{[2]} = z^{[2]} = W^{[2]}a^{[1]} + b^{[2]}
(1)a[1]=z[1]=W[1]x+b[1](2)a[2]=z[2]=W[2]a[1]+b[2]
我们将式子
(
1
)
(1)
(1)带入式子
(
2
)
(2)
(2),则有
(
3
)
a
[
2
]
=
z
[
2
]
=
W
[
2
]
(
W
[
1
]
x
+
b
[
1
]
)
+
b
[
2
]
=
W
[
2
]
W
[
1
]
x
+
W
[
2
]
b
[
1
]
+
b
[
2
]
(3) a^{[2]} = z^{[2]} = W^{[2]}(W^{[1]}x + b^{[1]}) + b^{[2]} = W^{[2]}W^{[1]}x + W^{[2]}b^{[1]} + b^{[2]}
(3)a[2]=z[2]=W[2](W[1]x+b[1])+b[2]=W[2]W[1]x+W[2]b[1]+b[2]
简化多项式为
a
[
2
]
=
z
[
2
]
=
W
′
x
+
b
′
a^{[2]} = z^{[2]} = W'x + b'
a[2]=z[2]=W′x+b′
如果你是用线性激活函数或者叫恒等激励函数,那么神经网络只是把输入线性组合再输出。
我们稍后会谈到深度网络,有很多层的神经网络,很多隐藏层。事实证明,如果你使用线性激活函数或者没有使用一个激活函数,那么无论你的神经网络有多少层一直在做的只是计算线性函数,所以不如直接去掉全部隐藏层。在我们的简明案例中,事实证明如果你在隐藏层用线性激活函数,在输出层用 sigmoid 函数,那么这个模型的复杂度和没有任何隐藏层的标准 Logistic 回归是一样的(如果你愿意的话,可以证明一下)。
在这里线性隐层一点用也没有,因为这两个线性函数的组合本身就是线性函数,所以除非你引入非线性,否则你无法计算更有趣的函数,即使你的网络层数再多也不行;只有一个 地方可以使用线性激活函数------ g ( z ) = z g(z) = z g(z)=z,就是你在做机器学习中的回归问题。 y y y是一个实数,举个例子,比如你想预测房地产价格,𝑦 就不是二分类任务 0 或 1,而是一个实数,从 0 到正无穷。如果𝑦 是个实数,那么在输出层用线性激活函数也许可行,你的输出也是一个 实数,从负无穷到正无穷。
总而言之,不能在隐藏层用线性激活函数,可以用ReLU或者tanh或者leaky ReLU或者其他的非线性激活函数,唯一可以用线性激活函数的通常就是输出层;除了一些特殊情况,比如与压缩有关的,在这里将不深入讨论。 在这之外,在隐层使用线性激活函数非常少见。因为房价都是非负数,所以我们也可以在输出层使用ReLU函数这样你的 y ^ \hat{y} y^ 都大于等于 0。
五、激活函数的导数
在神经网络中使用反向传播的时候,你需要计算激活函数的导数。对于之前介绍的激活函数,求导数如下:
1、sigmoid
求导过程如下:
d
d
z
g
(
z
)
=
1
1
+
e
−
z
(
1
−
1
1
+
e
−
z
)
=
g
(
z
)
(
1
−
g
(
z
)
)
\frac{d}{d z} g(z)=\frac{1}{1+e^{-z}}\left(1-\frac{1}{1+e^{-z}}\right)=g(z)(1-g(z))
dzdg(z)=1+e−z1(1−1+e−z1)=g(z)(1−g(z))
在神经网络中,
a
=
g
(
z
)
g
(
z
)
′
=
d
d
z
g
(
z
)
=
a
(
1
−
a
)
a = g(z) \\ g(z)' = \frac{d}{dz}g(z) = a(1 - a)
a=g(z)g(z)′=dzdg(z)=a(1−a)
2、tanh
求导如下:
g
(
z
)
=
t
a
n
h
(
z
)
=
e
z
−
e
−
z
e
z
+
e
−
z
d
d
z
g
(
z
)
=
1
−
(
t
a
n
h
(
z
)
)
2
g(z) = tanh(z) = \frac{e^z - e^{-z}}{e^z + e^{-z}} \\ \frac{d}{dz}g(z) = 1 - (tanh(z))^{2}
g(z)=tanh(z)=ez+e−zez−e−zdzdg(z)=1−(tanh(z))2
3、ReLU
g ( z ) = m a x ( 0 , z ) g ( z ) ′ = { 0 , z < 0 1 , z > 0 u n d e f i n e d , z = 0 g(z) = max(0, z) \\ g(z)' = \left\{\begin{array}{cl} 0 & , z < 0 \\ 1 & , z > 0 \\ undefined &, z = 0 \end{array}\right. g(z)=max(0,z)g(z)′=⎩⎨⎧01undefined,z<0,z>0,z=0
4、Leaky ReLu
与ReLU类似:
g
(
z
)
=
m
a
x
(
α
z
,
z
)
g
(
z
)
′
=
{
α
,
z
<
0
1
,
z
>
0
u
n
d
e
f
i
n
e
d
,
z
=
0
g(z) = max(\alpha z, z) \\ g(z)' = \left\{\begin{array}{cl} \alpha & , z < 0 \\ 1 & , z > 0 \\ undefined &, z = 0 \end{array}\right.
g(z)=max(αz,z)g(z)′=⎩⎨⎧α1undefined,z<0,z>0,z=0