激活函数在 cs231n 的 Lecture 6: Training Neural Networks, Part I 涉及。
我认为在 神经网络激励函数的作用是什么?有没有形象的解释? 已经对激活函数解释的很清楚了,这里只能做出一些自己的理解。
谈一下神经网络的历史,首先是单层 感知机,使用单层感知机实现了字母的识别。但是单层感知机最大的问题在于只能解决线性问题,也就是线性不可分,甚至连简单的异或问题也解决不了。
再之后就是多层感知机,解决了线性不可分的问题。到现在则是我们熟知的神经网络、卷积神经网络等。
但是对这几种,仍然脱离不了一个概念,对于单个神经元进行的操作是 $y=Wx+b$,也就是一个线性函数。就算是多层组合在一起,你把输入一层一层代入进去,最后得到的结果依然是一个线性函数,只不过这个线性函数比较复杂而已。更为具体点,多层感知机或神经网络只是多次矩阵的乘法。
所以才需要激活函数,为神经网络引入非线性因素。 这时候代入激活函数就会得到非常复杂的函数了: $\sigma(Wx+b)$
这张图形容的非常好:
激活函数有以下性质:
激活函数当然很好,但是使用激活函数时也面临一个问题:梯度消失,也就是激活函数梯度接近于 0。
对于梯度下降法不了解的,可以参考我的 从一元函数的角度理解梯度下降法。
假设损失函数 $L$ 在激活函数的梯度为 $\frac{\partial{L}}{\partial{\sigma}}$,输入激活函数的数据为 $x$。
激活函数输入:
则上一层 $w$ 的梯度是(需要更新权重):
这是导数的链式法则,需要了解一些反向传播的知识,权重是利用该层的梯度更新的。
当 $\frac{\partial{\sigma}}{\partial{x}}$ 接近 0 时,也就是激活函数饱和,则梯度消失,参数几乎不更新。梯度消失的情况在具体的激活函数中会出现。
import numpy as np
import matplotlib.pyplot as plt
X = np.linspace(-10, 10, 10000)
Y = 1/(1+np.exp(-X))
plt.plot(X, Y)
plt.grid()
plt.show()
Sigmoid 有一个很大的特性,对 Sigmoid 求导会发现,它的导数恰好是 $\sigma'(x)=\sigma(x)(1-\sigma(x))$
cs231n 问及:Consider what happens when the input to a neuron is always positive...What can we say about the gradients on w?
答案是 Always all positive or all negative :( (this is also why you want zero-mean data!),在非零为中心中解答。
Sigmoid 面临的问题是:
Y = np.tanh(X)
plt.plot(X, Y)
plt.grid()
plt.show()
和 Sigmoid 形状类似,但是 tanh 的值域为 $(-1,1)$。
对 tanh 求导可得:
tanh 虽然满足 zero centered,关于原点对称,但是饱和时,仍然会出现梯度消失(梯度接近于 0),而且指数计算复杂。
Y = np.maximum(0, X)
plt.plot(X, Y)
plt.grid()
plt.show()
ReLU 常用于深度学习中,好处显而易见:
坏处是:
需要注意的是,ReLU 不能配合 Xavier 初始化使用,这个希望能在权重初始化中介绍。
Y = np.maximum(0.01*X, X)
plt.plot(X, Y)
plt.grid()
plt.show()
ReLU 加上一点正的偏置就是 Leaky ReLU 了,通常用在 GAN 中。优势和面临的问题和 ReLU 一样,但重要的是 Leaky ReLU 解决了 ReLU 的梯度消失问题,当 $x<0$,梯度不会消失。
PReLU 将 Leaky ReLU 的偏置设为超参,$\alpha$ 需要优化,当 $\alpha=0.01$ 时就是 Leaky ReLU。反向传播的时候会出现 $\alpha$ 更新权重。
alpha = 1
import copy
Y = copy.deepcopy(X)
Y[Y<=0] = alpha*(np.exp(X[X<=0])-1)
plt.plot(X, Y)
plt.grid()
plt.show()
不是乘积再到激活函数,而是直接两个输出取最大。cs231n 描述 Linear Regime! Does not saturate! Does not die!
坏处是增加了一倍的参数。