激活函数
之前使用的 a = σ ( z ) a=\sigma(z) a=σ(z) ,其中 σ ( ) \sigma(~) σ( ) 便是激活函数。
在神经网络中,不同层的激活函数可以不同。
在学习中,一般以 g ( z ) g(z) g(z) 来表示激活函数。
为什么需要(线性)激活函数?
不需要激活函数就等同于使用线性激活函数
g
(
z
)
=
z
g(z)=z
g(z)=z (恒等激活函数),那么使用单个样本下的双层网络代码就为:
G
i
v
e
n
i
n
p
u
t
x
:
a
[
0
]
=
x
z
[
1
]
=
W
[
1
]
a
[
0
]
+
b
[
1
]
a
[
1
]
=
z
[
1
]
z
[
2
]
=
W
[
2
]
a
[
1
]
+
b
[
2
]
a
[
2
]
=
z
[
2
]
\begin{align*} &Given~~input~~x:\\ &~~~~~~~~a^{[0]}=x\\ &~~~~~~~~z^{[1]}=W^{[1]}a^{[0]}+b^{[1]}\\ &~~~~~~~~a^{[1]}=z^{[1]}\\ &~~~~~~~~z^{[2]}=W^{[2]}a^{[1]}+b^{[2]}\\ &~~~~~~~~a^{[2]}=z^{[2]} \end{align*}
Given input x: a[0]=x z[1]=W[1]a[0]+b[1] a[1]=z[1] z[2]=W[2]a[1]+b[2] a[2]=z[2]
将最后的结果展开,则
a
[
2
]
=
z
[
2
]
=
W
[
2
]
(
W
[
1
]
a
[
0
]
+
b
[
1
]
)
+
b
[
2
]
=
(
W
[
2
]
W
[
1
]
)
a
[
0
]
+
W
[
2
]
b
[
1
]
+
b
[
2
]
a^{[2]}=z^{[2]}=W^{[2]}(W^{[1]}a^{[0]}+b^{[1]})+b^{[2]}=(W^{[2]}W^{[1]})a^{[0]}+W^{[2]}b^{[1]}+b^{[2]}
a[2]=z[2]=W[2](W[1]a[0]+b[1])+b[2]=(W[2]W[1])a[0]+W[2]b[1]+b[2] ,其中
W
[
2
]
W
[
1
]
W^{[2]}W^{[1]}
W[2]W[1] 可以看作
W
′
W^{'}
W′ ,
W
[
2
]
b
[
1
]
+
b
[
2
]
W^{[2]}b^{[1]}+b^{[2]}
W[2]b[1]+b[2] 可以看作
b
′
b^{'}
b′ ,最终可等效为
a
[
2
]
=
W
′
a
[
0
]
+
b
′
a^{[2]}=W^{'}a^{[0]}+b^{'}
a[2]=W′a[0]+b′ 。
这说明,如果没有激活函数,或者是其他线性激活函数,那么无论层数多深,总会存在与之等效的单层神经网络,那么深度学习的意义就没有了,就变成了单纯的逻辑回归了。
特例
针对回归问题,输出层可以使用线性激活函数,而隐藏层依旧不可以。
sigma函数
g ( z ) = σ ( z ) g(z)=\sigma(z) g(z)=σ(z)
公式: a = σ ( z ) = 1 1 + e − z a=\sigma(z)=\frac{1}{1+e^{-z}} a=σ(z)=1+e−z1 。
函数图像:
梯度/斜率/导数:
g
′
(
z
)
=
d
d
z
g
(
z
)
=
1
1
+
e
−
z
(
1
−
1
1
+
e
−
z
)
=
g
(
z
)
[
1
−
g
(
z
)
]
\begin{align*} g^{'}(z)=\frac{d}{dz}g(z)&=\frac{1}{1+e^{-z}}(1-\frac{1}{1+e^{-z}})\\ &=g(z)[1-g(z)] \end{align*}
g′(z)=dzdg(z)=1+e−z1(1−1+e−z1)=g(z)[1−g(z)]
导数图像:
使用:在**二元分类**问题上(输出层的结果为0~1),输出层的激活函数可以使用sigma函数。
禁用:在非二元分类问题上,禁用,即使是二元分类问题,隐藏层中也不能用。
缺点: z z z 非常大或者非常小时, σ ( z ) \sigma(z) σ(z) 函数的梯度(斜率)会很小,会形成梯度消失问题,从而拖慢梯度下降算法。
双曲正切函数
g ( z ) = t a n h ( z ) g(z)=tanh(z) g(z)=tanh(z)
公式: a = t a n h ( z ) = e z − e − z e z + e − z a=tanh(z)=\frac{e^z-e^{-z}}{e^z+e^{-z}} a=tanh(z)=ez+e−zez−e−z 。
函数图像:
优点:可达到“数据中心化”的效果,即数据平均值接近 0 0 0 。
缺点:① 二元分类问题上(输出层的结果为0~1),输出层不能用。
② z z z 非常大或者非常小时, t a n h ( z ) tanh(z) tanh(z) 函数的梯度(斜率)会很小,会形成梯度消失问题,从而拖慢梯度下降算法。
梯度/斜率/导数:
g
′
(
z
)
=
d
d
z
g
(
z
)
=
1
−
g
2
(
z
)
\begin{align*} g^{'}(z)=\frac{d}{dz}g(z)=1-g^{2}(z) \end{align*}
g′(z)=dzdg(z)=1−g2(z)
导数图像:
线性修正单元(ReLU)
g ( z ) = R e L U ( z ) g(z)=ReLU(z) g(z)=ReLU(z)
现在已经变成隐层激活函数的默认选择了。
公式: a = R e L U ( z ) = m a x { 0 , z } a=ReLU(z)=max\{0,z\} a=ReLU(z)=max{0,z} 。
函数图像:
P.S.: z = 0 z=0 z=0 这一点的导数不存在,但在编程中,刚好 z = 0 z=0 z=0 的概率非常之低,所以不用担心。或者自己可以给 z = 0 z=0 z=0 点的导数赋值。
**注意:**ReLU并不是线性激活函数,其导数并不是在全域都为恒定值。
梯度/斜率/导数:
g
′
(
z
)
=
{
0
,
if
z
<
0
1
,
if
z
≥
0
\begin{align*} g^{'}(z)=\begin{cases} 0, & \text {if $z<0$}\\ 1, & \text {if $z≥0$}\\ \end{cases} \end{align*}
g′(z)={0,1,if z<0if z≥0
z
=
0
z=0
z=0 处的导数,可以人为定义成
1
1
1 或
0
0
0 。
导数图像:
带泄露ReLU(Leaky ReLU)
g ( z ) = L e a k y R e L U ( z ) g(z)=Leaky~ReLU(z) g(z)=Leaky ReLU(z)
公式: a = L e a k y R e L U ( z ) = m a x { b ⋅ z , z } a=Leaky~ReLU(z)=max\{b·z,z\} a=Leaky ReLU(z)=max{b⋅z,z} , b b b 可以取 0.01 0.01 0.01 。
函数图像:
梯度/斜率/导数:
g
′
(
z
)
=
{
0.01
,
if
z
<
0
1
,
if
z
≥
0
\begin{align*} g^{'}(z)=\begin{cases} 0.01, & \text {if $z<0$}\\ 1, & \text {if $z≥0$}\\ \end{cases} \end{align*}
g′(z)={0.01,1,if z<0if z≥0
z
=
0
z=0
z=0 处的导数,可以人为定义成
1
1
1 或
0.01
0.01
0.01 。
导数图像: