作者:欧新宇(Xinyu OU)
当前版本:Release v0.9
开发平台:Paddle 2.3.2
运行环境:Intel Core i7-7700K CPU 4.2GHz, nVidia GeForce GTX 1080 Ti
本教案所涉及的数据集仅用于教学和交流使用,请勿用作商用。
最后更新:2020年01月29日
所谓激活函数(Activation Function),就是在人工神经网络的神经元上运行的函数,负责将神经元的输入映射到输出端。
激活函数(Activation functions)对于人工神经网络模型去学习、理解非常复杂和非线性的函数来说具有十分重要的作用。它们将非线性特性引入到我们的网络中。如图1,在神经元中,输入的 inputs 通过加权,求和后,还被作用了一个函数,这个函数就是激活函数。引入激活函数是为了增加神经网络模型的非线性。没有激活函数的每层都相当于矩阵相乘。就算你叠加了若干层之后,无非还是个矩阵相乘罢了。
如果不用激活函数,每一层输出都是上层输入的线性函数,无论神经网络有多少层,输出都是输入的线性组合,这种情况就是最原始的感知机(Perceptron)。
如果使用的话,激活函数给神经元引入了非线性因素,使得神经网络可以任意逼近任何非线性函数,这样神经网络就可以应用到众多的非线性模型中。
Sigmoid函数是最基础也是曾经被应用最多的激活函数,它被广泛应用到BP神经网络,最初的ANN和MLP中。直到今天,在诸如循环神经网络RNN
, 概率模型
, 自编码器AutoEncode
中仍然被广泛使用。根据它的形状,我们有时候也称它为***S***形函数。下面给出Sigmoid函数的数学表达
和Python Code
.
import numpy as np import matplotlib.pyplot as plt def sigmoid(x): y=1.0/(1.0+np.exp(-x)) return y x=np.linspace(start=-10,stop=10,num=100) y=sigmoid(x) plt.plot(x,y) plt.grid(True) plt.show()
import numpy as np import matplotlib.pyplot as plt def tanh(x): y=(1.0-np.exp(-2*x))/(1.0+np.exp(-2*x)) return y x=np.linspace(start=-10,stop=10,num=100) y=tanh(x) plt.plot(x,y) plt.grid(True) plt.show()
修正线性单元(Rectified Linear Unit, ReLU)起源于神经科学的研究, 2001年,Dayan、Abott从生物学角度模拟出了脑神经元接受信号更精确的激活模型. 但是,它被广泛应用应该追溯到2013年的Alexnet:《ImageNet Classification with Deep Convolutional Neural Networks》. 该论文由Alex Krizhevsky和Geoffrey Hinton撰写,它们所提出的AlexNet获得了当年ImageNet竞赛的冠军,并且以较大优势领先第二名,并称为了今天著名的卷积神经网络(CNN)和深度学习(DeepLearning)的标杆之作。
所以,希望所有同学都要认真阅读这篇论文,同时将其实现出来(这也是《深度学习:Deep Learning》课程必修工作)。
ReLU是目前使用最广的激活函数,也是目前深度学习、卷积神经网络的事实标准激活函数,需要每个同学都认真掌握。
ReLU的数学表达式(简单之美):
或
ReLU的有效性体现在两个方面:
这两个方面是相辅相成的,因为克服了梯度消失问题,所以训练才会快。关于ReLU有一段精彩的话,引用如下:
几十年的机器学习发展中,我们形成了这样一个概念:非线性激活函数要比线性激活函数更加先进。
尤其是在布满Sigmoid函数的BP神经网络,布满径向基函数的SVM神经网络中,往往有这样的幻觉,非线性函数对非线性网络贡献巨大。
该幻觉在SVM中更加严重。核函数的形式并非完全是SVM能够处理非线性数据的主力功臣(支持向量充当着隐层角色)。
那么在深度网络中,对非线性的依赖程度就可以缩一缩。在深度神经网络中,稀疏特征并不需要网络具有很强的处理线性不可分机制。
综合以上两点,在深度学习模型中,使用简单、速度快的线性激活函数可能更为合适。
import numpy as np import matplotlib.pyplot as plt def relu(x): y=x.copy() y[y<0]=0 return y x=np.linspace(start=-10,stop=10,num=100) y=relu(x) # print(y) plt.plot(x,y) plt.grid(True) plt.show()
这三个激活函数都是对ReLU激活函数的改进,大体上可以统一为以下公示:
其中 可以看作是斜率,也就是说,改进版的ReLU多引入了一个参数。
下面给出LReLU的Python代码
# ReLU import numpy as np import matplotlib.pyplot as plt def lrelu(x,a): y=x.copy() for i in range(y.shape[0]): if y[i]<0: y[i]=a*y[i] return y x=np.linspace(start=-10,stop=10,num=100) y=lrelu(x,0.25) # print(x) # print(y) plt.plot(x,y) plt.grid(True) plt.show()
Exponential Linear Units的缩写,函数形式为
其中, .
import numpy as np import matplotlib.pyplot as plt def elu(x,a): y=x.copy() for i in range(y.shape[0]): if y[i]<0: y[i]=a*(np.exp(y[i])-1) return y x=np.linspace(start=-10,stop=10,num=100) y=elu(x,0.5) # print(x) # print(y) plt.plot(x,y) plt.grid(True) plt.show()
数学表达:
import numpy as np import matplotlib.pyplot as plt def softplus(x): y=np.log(np.exp(x)+1) return y x=np.linspace(start=-10,stop=10,num=100) y=softplus(x) plt.plot(x,y) plt.grid(True) plt.show()
数学表达:
import numpy as np import matplotlib.pyplot as plt def softsign(x): y=x/(np.abs(x)+1) return y x=np.linspace(start=-10,stop=10,num=100) y=softsign(x) plt.plot(x,y) plt.grid(True) plt.show()