1、什么是激活函数
它来自动物界的灵感,动物的神经元会接受来自对它有作用的其他神经元的信号,当然这些信号对该神经元的作用大小不同(即具有不同的权重)。那么该神经元的信号值就是其他神经元信号加权求和后的值。如果该信号值大于指定阈值,则会激活,否则不会激活,抽象的数学模型为:
这里的激活函数就是阶跃函数,但在0处跃变且不可导。
进一步抽象出神经网络模型中神经元模型为:
其中为激活函数
2、神经网络中激活函数有什么用?
作用就是:增加模型非线性
2.1 没有激活函数世界会怎样?(可能简单的二分类问题都不能被优雅解决)
现在有一个二分类问题,将三角形和圆点进行正确分类,如图1所示。我们试着用神经网络解决这个问题。跟大家说明一下,这是一个线性不可分的问题(就是你在这个平面里,找不到一条直线可以把图中的三角形和圆点完全分开)。如果你能找到,算你厉害!
可能的解决思路:
1)用单层感知机(不带激活函数)
首先我们想到利用最简单的单层感知机来解决,单层感知机可以画出一条直线,把平面分开,如图2所示。
图2中,左图是没有激活函数的单层感知机结构,其中是权重值,是偏置值,它的工作原理是:输入一个样本(有两个特征),如果说明该样本是正类;如果,说明该样本是负类。我们这里不讨论的特殊情况。根据单层感知机的工作原理,我们画出右边的坐标图。
结论是:不带激活函数的单层感知机是一个线性分类器,不能解决线性不可分的问题。 不能解决图1中的二分类问题。
2)用多个感知机(不带激活函数)
不带激活函数的单层感知机解决不了问题,那我们就会想到用多个感知机进行组合,获得更强的分类能力,看看能不能解决我们的线性不可分问题。如图3所示。
图3中,虽说模型变得复杂,表达能力更强一点,但还是一个关于和的线性表达式.
结论是:合并后的多个感知器本质上还是一个线性分类器,还是解决不了非线性的问题。
进一步分析总结:
不管是单层感知机还是多个感知器,只要不带激活函数,都只能解决线性可分的问题,解决不了我们的线性不可分问题。不信,那我们就在平面中画几条直线试试,结果发现这几条直线无论在平面中如何旋转,都不能完全正确的分开三角形和圆点。结果如图4所示。
在上面的线性方程的组合过程中,我们其实类似的在做三条直线的线性组合,如图5所示。图5描述了,当我们直接用没有激活函数的分类器时,其实我们还是线性组合,最多也就是更复杂的线性组合罢了。有人在这里又要抖机灵了!我数学学的好,我记得学高等数学的时候,在不定积分那一块,有个画曲为直思想来近似求解。那么,我们可以来借鉴一下,用无数条直线去近似接近一条曲线,你很聪明啊!但是比着用非线性的激活函数来说,你这解决办法还是太低端了一些。
因此就需要来引入激活函数了。
2.2 激活函数怎么起作用?
我们再设计一个神经网络,在所有的隐层和输出层加一个激活函数,这里激活函数我们就用Sigmoid函数,如图6所示。这样输出的就是一个非线性函数了,的输出更复杂,有了这样的非线性激活函数以后,神经网络的表达能力更加强大了。能不能解决我们一开始提出的线性不可分问题呢?我们接着来验证吧!
我们把图6中的带有激活函数的单层感知机扩展到带有激活函数的多个神经元的情况。那么神经网络的表达能力更强,具体如图7所示。
和图7相对应的非线性组合是图8所示的样子。这样看起来,似乎已经能解决我们线性不可分的问题了。最后,我们通过最优化损失函数的做法,通过不断的学习,能够学到正确分类三角形和圆点的曲线。具体学到什么曲线,我们不知道,或许是图9所示的曲线,也可能是其他曲线。
总结:激活函数是用来加入非线性因素的,提高神经网络对模型的表达能力,解决线性模型所不能解决的问题。要知道大部分问题是非线性问题,因此激活函数是必不可少的。
【待看】Hyper-parameters in Action! Part I — Activation Functions(可能需要翻墙)
3、常见的激活函数
26种神经网络激活函数可视化
Visualising Activation Functions in Neural Networks(可能需要翻墙)
以三种常见的为例介绍,Sigmoid、tanh、Relu
3.1 Sigmoid
Sigmoid函数式:
Sigmoid函数图像:
Sigmoid函数图像代码:
def sigmoid():
x = np.arange(-10, 10, 0.1)
y = 1 / (1+np.exp(-x))
plt.plot(x, y)
plt.grid()
plt.show()
Sigmoid函数求导:
Sigmoid函数优点:
- 能够将函数压缩至区间[0, 1]之间,保证数据稳定,波动幅度小
Sigmoid函数缺点:
- 函数在两端的饱和区梯度趋近于0,当反向传播时容易出现梯度消失或梯度爆炸(不清楚为什么会梯度爆炸?)
- 输出不是0均值(zero-centered),这样会导致,如果输入为正,那么导数总为正,反向传播总往正方向更新,如果输入为负,那么导数总为负,反向传播总往负方向更新,收敛速度缓慢
- 运算量较大
pytorch中Sigmoid函数的使用
3.2 tanh
tanh函数式:
tanh函数图像:
tanh函数图像代码:
def tanh():
x = np.arange(-10, 10, 0.1)
y = (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))
plt.plot(x, y)
plt.grid()
plt.show()
tanh 函数求导:
tanh 函数优点:
- 解决了Sigmoid函数非0均值的问题,将函数压缩至区间[-1, 1]之间
pytorch中tanh函数的使用
tanh 函数缺点:
- 函数在两端的饱和区梯度趋近于0,当反向传播时容易出现梯度消失或梯度爆炸(不清楚为什么会梯度爆炸?)
- 运算量大
pytorch中tanh函数的使用
3.3 Relu
Relu函数式:
Relu函数图像:
Relu函数图像代码:
def relu():
x = np.arange(-10, 10, 0.1)
y = np.where(x<0, 0, x)
plt.plot(x, y)
plt.grid()
plt.show()
Relu函数求导:
Relu优点:
- 梯度不饱和,收敛速度快
- 减轻反向传播时梯度弥散的问题
- 由于不需要进行指数运算,因此运算速度快、复杂度低
Relu缺点:
- 输出不是0均值(zero-centered)
- 对参数初始化和学习率非常敏感,设置不当容易造成神经元坏死现象,也就是有些神经元永远不会被激活(由于负部梯度永远为0造成)
pytorch中Relu函数的使用