激活函数:
首先来看激活函数在神经网络模型中的位置,如图(a) 所示的激活函数实际上隐藏在神经网络模型中的连接线上。前文反复强调神经网络模型中的连接是最重要的,该连接线包括输入矩阵与权值矩阵相乘的过程,还包括激活函数对数据进行激活的过程。
激活函数作用于I层的神经元到1+1层神经元之间。其中(a)为单个神经元模型,激活
函数用f表示: (b)为神经网络的第1层和第1+1层,每个圆圈表示一个激活函数
激活函数的一般性质如下。
(1)单调可微
一:般情况下,我们使用梯度下降算法更新神经网络中的参数,因此必须要求激活函数可微。如果函数是单调递增的,求导后函数必大于零(方便计算),因此需要激活函数具有单调性。
二:限制输出值的范围,输入的数据通过神经元上的激活函数来控制输出数值的大小,该输出数值是一个非线性值。通过激活函数求得的数值,根据极限值来判断是否需要激活该神经元。也就是说,我们可以通过激活函数确定是否对一个神经元的输出感兴趣。
三:非线性,因为线性模型的表达能力不够(从数据输入到与权值求和加偏置,都是在线性函数内执行权重与输入数据进行加权求和的过程,如(z =WX+b),因此激活函数的出现还为神经网络模型加入非线性因素。
激活函数拥有上述特性,它存在的核心意义在于:一个没有激活函数的神经网络只不过是一个线性回归模型,它不能表达复杂的数据分布。神经网络中加入了激活函数,相当于引入了非线性因素,从而解决了线性模型不能解决的问题。
线性模型:
如图所示,线性(Linear) 函数是最基本的激活函数,其因变量与自变量之间有直接的比例关系。因此,线性变换类似于线性回归。实际上,在神经网络中线性变换,意味着节点按原样通过数据信号通常与单层神经网络一起使用。 线性激活函数如式所示。
代码实现:
def Linear1(x, W=1.5):
return W * x
x = np.arange(-2, 2, 0.01)
y_linear1 = Linear1(x)
plt.plot(x, y_linear1, color='#1797ff', linewidth=3)
ax = plt.gca()
ax.set_xlim([-2, 2])
ax.set_ylim([-2, 2])
ax.axhline(0, linestyle='--', color='gray', linewidth=1)
ax.axvline(0, linestyle='--', color='gray', linewidth=1)
plt.title("Linear")
plt.show()
Sigmoid 模型:
如图所示,Sigmoid 函数是一种在不删除数据的情况下,减少数据的极值或异常值的函数。因此,它能够很好地表达激活的意思,未激活值为0,完全饱和的激活值则为1。在数学上,Sigmoid激活函数为每个类输出提供独立的概率。Sigmoid激活函数如式所示:
代码实现:
def sigmoid(x):
return 1 / (1 + np.exp(-1 * x))
x = np.arange(-2, 2, 0.01)
y_sigmoid = sigmoid(x)
plt.plot(x, y_sigmoid, color='#1797ff', linewidth=3)
ax = plt.gca()
ax.set_xlim([-2, 2])
ax.set_ylim([-1, 1])
ax.axhline(0, linestyle='--', color='gray', linewidth=1)
ax.axvline(0, linestyle='--', color='gray', linewidth=1)
plt.title("sigmoid")
plt.show()
优点:
●Sigmoid 函数的输出映射在[0, 1]范围内,函数单调连续,且输出范围有限制,优化稳定:
●易于求导;
●输出值为独立概率,可以用在输出层。
缺点:
●Sigmoid 函数容易饱和,导致训练结果不佳:其输出并不是零均值,数据存在偏差,分布不平均。
双曲正切函数模型:
双曲正切函数(Tanh)与Sigmoid函数类似。不同的是,Tanh 的归一化范围为-1到1,而不是0到1,因此Tanh的优点是可以更容易地处理负数。同时,因为Tanh是0均值,也就解决了Sigmoid函数的非0均值的缺点,所以实际中Tanh函数会比Sigmoid函数更常用。Tanh激活函数如下图所示:
代码实现:
def tanh(x):
return np.tanh(x)
x = np.arange(-2, 2, 0.01)
y_tanh = tanh(x)
plt.plot(x, y_tanh, color='#1797ff', linewidth=3)
ax = plt.gca()
ax.set_xlim([-2, 2])
ax.set_ylim([-1.1, 1.1])
ax.axhline(0, linestyle='--', color='gray', linewidth=1)
ax.axvline(0, linestyle='--', color='gray', linewidth=1)
plt.title("tanh")
plt.show()
ReLU函数:
研究表明,大脑同时被激活的神经元只有1% ~ 4%,这表明神经元工作的稀疏性。从信号方面来看,神经元同时只对输入信号的少部分进行选择性响应,大量信号被刻意地屏蔽,这样可以提高神经网络的学习精度,更好地提取稀疏特征。而ReLU函数则满足仿生学中的稀疏性,只有当输入值高于一定数目时才激活该神经元节点。当输入值低于0时进行限制,当输入上升到某一阈值以上时,函数中的自变量与因变量呈线性关系。ReLU激活函数如下图所示:
代码实现:
def leak_relu(data, epsilon=0.1):
return np.maximum(epsilon * data, data)
def relu(data):
return np.maximum(0, data)
x = np.arange(-2, 2, 0.01)
y_leak_relu = leak_relu(x)
y_relu = relu(x)
plt.plot(x, y_leak_relu, color='#1797ff', linewidth=3)
ax = plt.gca()
ax.set_xlim([-2, 2])
ax.set_ylim([-0.5, 2])
ax.axhline(0, linestyle='--', color='gray', linewidth=1)
ax.axvline(0, linestyle='--', color='gray', linewidth=1)
plt.title("leak ReLU")
plt.show()
plt.plot(x, y_relu, color='#1797ff', linewidth=3)
ax = plt.gca()
ax.set_xlim([-2, 2])
ax.set_ylim([-0.5, 2])
ax.axhline(0, linestyle='--', color='gray', linewidth=1)
ax.axvline(0, linestyle='--', color='gray', linewidth=1)
plt.title("ReLU")
plt.show()
ReLU函数对比Sigmoid函数主要有如下3点变化:
●单侧抑制:
●相对宽阔的兴奋边界;
●稀疏激活性。
优点:
●相比Sigmoid函数和Tanh函数,ReLU函数在随机梯度下降算法中能够快速收敛;
ReLU函数的梯度为0或常数,因此可以缓解梯度消散问题;
ReLU函数引入稀疏激活性,在无监督预训练时也能有较好的表现。
缺点:
●ReLU神经元在训练中不可逆地死亡:
● 随着训练的进行,可能会出现神经元死亡、权重无法更新的现象,流经神经元的梯度从该点开始将永远是零。
正是因为ReLU函数比其他激活函数更适合在神经网络中作为激活函数,或者说优点更加明显,因此综合速率和效率,神经网络中大部分激活函数都使用了ReLU函数。
SoftMax函数:
Softmax函数的本质是将-一个K维的任意实数向量,压缩(映射)成另一个K维的实数向量,其中向量中的每个元素取值都介于(0,1)范围内。
Softmax是对逻辑回归(Logistic Regression, LR) 的推广,逻辑回归用于处理:二分类问题,其推广Softmax回归则用于处理多分类问题。如图3-6所示,在数学上,Softmax函数会返回输出类的互斥概率分布,例如,网络的输出为(1, 1,1,1),经过Softmax函数后输出为(0.25, 0.25, 0.25, 0.25)。我们可以得到分类中唯一所属类 别,因此通常把Softmax作为输出层的激活函数。Softmax 激活函数如下式所示
代码实现:
def softmax(x):
return np.exp(x) / np.sum(np.exp(x))
x = np.arange(-2, 2, 0.01)
y_softmax = softmax(x)
plt.plot(x, y_softmax, color='#1797ff', linewidth=3)
ax = plt.gca()
ax.set_xlim([-2, 2])
ax.set_ylim([-0.001, 0.01])
ax.axhline(0, linestyle='--', color='gray', linewidth=1)
ax.axvline(0, linestyle='--', color='gray', linewidth=1)
plt.title("Softmax")
plt.show()