深度学习之激活函数
1. Sigmoid激活函数
sigmoid非线性激活函数的公式为:
σ
(
x
)
=
1
1
+
e
−
x
\sigma (x) = \frac{1}{{1 + {e^{ - x}}}} % MathType!MTEF!2!1!+- % feaahqart1ev3aaatCvAUfeBSjuyZL2yd9gzLbvyNv2CaerbuLwBLn % hiov2DGi1BTfMBaeXatLxBI9gBaerbd9wDYLwzYbItLDharqqtubsr % 4rNCHbWexLMBbXgBd9gzLbvyNv2CaeHbl7mZLdGeaGqjY-Oj0xXdbb % a91rFfpec8Eeeu0xXdbba9frFj0-OqFfea0dXdd9vqaq-JfrVkFHe9 % pgea0dXdar-Jb9hs0dXdbPYxe9vr0-vr0-vqpWqaaeaabmGaciaaca % qabeaadaqaaqaafaGcbaGaeq4WdmNaaiikaiaadIhacaGGPaGaeyyp % a0ZaaSaaaeaacaaIXaaabaGaaGymaiabgUcaRiaadwgadaahaaWcbe % qaaiabgkHiTiaadIhaaaaaaaaa!4ADB!
σ(x)=1+e−x1其图形如下所示。由图可知,sigmoid激活函数是将一个实数输入转化到0~1之间的输出。可以将越大的负数转化到越靠近0,越大的正数转化到越靠近1。历史上 sigmoid函数频繁地使用,因为其具有良好的解释性。
sigmoid函数的导数图像如下所示。观察该图可知,在输入为0时导数达到最大值0.25;而在任一方向上越远离0点时,导数越接近0。
但近几年,sigmoid激活函数已经越来越少地被人使用了,主要是因为有以下两大缺点。
(1)sigmoid 函数会造成梯度消失。正如其导数图所示,在靠近1和0的两端时,梯度会几乎变成0,梯度下降法通过梯度乘上学习率来更新参数,因此如果梯度接近0,那么没有任何信息来更新参数,这样就会造成模型不收敛。另外,如果使用sigmoid函数,那么需要在初始化权重的时候也必须非常小心。如果初始化的时候权重太大,那么经过激活函数也会导致大多数神经元变得饱和,没有办法更新参数。
(2)sigmoid输出不是以0为均值,这就会导致经过sigmoid激活函数之后的输出,作为后面一层网络的输入的时候是非0均值的,这个时候如果输入进入下一层神经元的时候全是正的,这就会导致梯度全是正的,那么在更新参数的时候永远都是正梯度。怎么理解呢?比如进入下一层神经元的输入是x,参数是w和b,那么输出就是f = wx+b,f(x)的导数为x。所以如果x是0均值的数据、那么梯度就会有正有负。但是这个问题并不是太严重,因为一般神经网络在训练的时候都是按batch进行训练的,这个时候可以在一定程度上缓解这个问题,所以说虽然0均值这个问题会产生一些不好的影响,但是总体来讲跟上一个缺点:梯度消失相比还是要好很多。
2. Tanh激活函数
tanh激活函数是sigmoid的变形,其数学表达为:
tanh
(
x
)
=
2
σ
(
2
x
)
−
1
\tanh (x) = 2\sigma (2x) - 1 % MathType!MTEF!2!1!+- % feaahqart1ev3aaatCvAUfeBSjuyZL2yd9gzLbvyNv2CaerbuLwBLn % hiov2DGi1BTfMBaeXatLxBI9gBaerbd9wDYLwzYbItLDharqqtubsr % 4rNCHbWexLMBbXgBd9gzLbvyNv2CaeHbl7mZLdGeaGqipGI8Vfeu0d % Xdh9vqqj-hEeeu0xXdbba9frFj0-OqFfea0dXdd9vqaq-JfrVkFHe9 % pgea0dXdar-Jb9hs0dXdbPYxe9vr0-vr0-vqpWqaaeaabmGaciaaca % qabeaadaqaaqaafaGcbaGaciiDaiaacggacaGGUbGaaiiAaiaacIca % caWG4bGaaiykaiabg2da9iaaikdacqaHdpWCcaGGOaGaaGOmaiaadI % hacaGGPaGaeyOeI0IaaGymaaaa!4D93!
tanh(x)=2σ(2x)−1其图形如下所示。它将输入的数据转化到-1~1之间。可以通过图像看出它将输出变成了0均值,在一定程度上解决了sigmoid函数的第二个问题,但是它仍然存在梯度消失的问题。
tanh函数的导数如下,当输入接近0时,tanh函数的导数接近最大值1。与sigmoid函数图像中看到的类似,输入在任一方向上远离0点,导数越接近0。因此依然面临sigmoid函数的第一个问题。现在一般都采用Relu激活函数来避免该问题,但是在RNN中还是会使用tanh激活函数,用以降低梯度爆炸的风险。具体原因如下 https://kexue.fm/archives/7888
3. ReLU激活函数
ReLU激活函数近几年变得越来越流行,它的数学表达式为:
f
(
x
)
=
max
(
0
,
x
)
f(x) = \max (0,x) % MathType!MTEF!2!1!+- % feaahqart1ev3aaatCvAUfeBSjuyZL2yd9gzLbvyNv2CaerbuLwBLn % hiov2DGi1BTfMBaeXatLxBI9gBaerbd9wDYLwzYbItLDharqqtubsr % 4rNCHbWexLMBbXgBd9gzLbvyNv2CaeHbl7mZLdGeaGqipGI8Vfeu0d % Xdh9vqqj-hEeeu0xXdbba9frFj0-OqFfea0dXdd9vqaq-JfrVkFHe9 % pgea0dXdar-Jb9hs0dXdbPYxe9vr0-vr0-vqpWqaaeaabmGaciaaca % qabeaadaqaaqaafaGcbaGaamOzaiaacIcacaWG4bGaaiykaiabg2da % 9iGac2gacaGGHbGaaiiEaiaacIcacaaIWaGaaiilaiaadIhacaGGPa % aaaa!4A1C!
f(x)=max(0,x)换句话说,这个激活函数只是简单地将大于0的部分保留,将小于0的部分变成0,它的图形如下所示。
观察ReLU的导数图可以知道,当输入为负时,ReLU函数的导数为0,而当输入为正时,ReLU函数的导数为1。当输入值等于0时,ReLU函数不可导。
下面简单介绍下ReLU的优缺点。
优点:
(1)相比于sigmoid 激活函数和tanh激活函数,ReLU激活函数能够极大地加速随机梯度下降法的收敛速度,这因为它是线性的,且不存在梯度消失的问题。
(2)相比于Sigmoid激活函数和Tanh激活函数的复杂计算而言,ReLU的计算方法更加简单,只需要一个阈值过滤就可以得到结果,不需要进行一大堆复杂的运算。
缺点:
当学习率过大时会出现某些神经元永久死亡的现象,导致网络后期无法正常更新。详细理由如下https://zhuanlan.zhihu.com/p/390655512 。在实际操作中,除了设置比较小的学习率,还可以通过改进ReLU函数来避免该问题。
4. Leaky ReLU激活函数
Leaky ReLU激活函数是ReLU激活函数的变式,主要是为了修复ReLU激活函数中训练比较脆弱的这个缺点.不将x <0的部分变成0,而给它一个很小的负的斜率,比如0.01,它的数学形式可以表现为 f ( x ) = I ( x < 0 ) ( α x ) + I ( x ≥ 0 ) ( x ) f(x) = I(x < 0)(\alpha x) + I(x \ge 0)(x) % MathType!MTEF!2!1!+- % feaahqart1ev3aaatCvAUfeBSjuyZL2yd9gzLbvyNv2CaerbuLwBLn % hiov2DGi1BTfMBaeXatLxBI9gBaerbd9wDYLwzYbItLDharqqtubsr % 4rNCHbWexLMBbXgBd9gzLbvyNv2CaeHbl7mZLdGeaGqipGI8Vfeu0d % Xdh9vqqj-hEeeu0xXdbba9frFj0-OqFfea0dXdd9vqaq-JfrVkFHe9 % pgea0dXdar-Jb9hs0dXdbPYxe9vr0-vr0-vqpWqaaeaabmGaciaaca % qabeaadaqaaqaafaGcbaGaamOzaiaacIcacaWG4bGaaiykaiabg2da % 9iaadMeacaGGOaGaamiEaiabgYda8iaaicdacaGGPaGaaiikaiabeg % 7aHjaadIhacaGGPaGaey4kaSIaamysaiaacIcacaWG4bGaeyyzImRa % aGimaiaacMcacaGGOaGaamiEaiaacMcaaaa!553B! f(x)=I(x<0)(αx)+I(x≥0)(x)其中α是一个很小的常数,这样就可以使得输入小于0的时候也有一个小的梯度。关于Leaky ReLU激活函数的效果,众说纷纭,一些实验证明很好,一些实验证明并不好。同时也有人提出可以对α进行参数化处理,也就是说可以在网络的训练过程中对α也进行更新,但是否对所有情况都有效、目前也不清楚。
通过上面的部分我们简单地介绍了一些激活函数的优缺点,在实际我们使用较多的还是ReLU激活函数,但是需要注意学习率的设定不要太大了;一定不要使用sigmoid激活函数,可以试试tanh 激活函数。但是一般它的效果都比ReLU。最后一点,我们在实际使用中也很少使用混合类型的激活函数,也就是说一般在同一个网络中我们都使用同一种类型的激活函数。