Dishashree Gupta作者王琦、林亦霖校对王菁 编辑王紫岳翻译

深度学习基础——激活函数以及什么时候使用它们?(附代码)

本文简要介绍了作者在初次进行机器学习的操作时所遇到的情况与得到的教训。

摘要

  • 激活函数神经网络的组成部分之一。

  • 学习深度学习中不同的激活函数

  • 在python中编写激活函数并在实时编码窗口中将结果可视化。

本文最初发表于2017年10月,并于2020年1月进行了更新,增加了三个新的激活函数和python代码。

引言

今天,因特网提供了获取大量信息的途径。无论我们需要什么,只需要谷歌搜索一下即可。然而,当我们获取了这么多的信息时,我们又面临着如何区分相关和无关的信息的挑战。

当我们的大脑被同时灌输大量信息时,它会努力去理解这些信息并将其分为“有用的”和“不那么有用的”。对于神经网络而言,我们需要类似的机制来将输入的信息分为“有用的”或“不太有用的”。

这是网络学习的重要方式,因为并不是所有的信息都同样有用。它们中的一些仅仅是噪音,而这就是激活函数的用武之地了。激活函数帮助神经网络使用重要信息,并抑制不相关的数据点。

接下来让我们来看看这些激活函数,了解它们是如何工作的,并找出哪些激活函数适合于什么样的问题情景。

目录

1. 神经网络概述
2. 我们可以不使用激活函数么?
3. 常用的激活函数以及什么时候使用他们
  • Binary Step(二元阶跃)
  • Linear(线性)
  • Sigmoid(S型)
  • Tanh(双曲正切)
  • ReLU(线性整流单元)
  • Leaky ReLU(泄露型线性整流函数
  • Parameterised ReLU(参数线性整流函数
  • Exponential Linear Unit(指数化线性单元)
  • Swish
  • Softmax
4. 选择正确的激活函数

1. 神经网络概述

在我深入研究激活函数的细节之前,让我们先快速了解一下神经网络的概念以及它们是如何工作的。神经网络是一种非常强大的模仿人脑学习方式的机器学习机制。

大脑接收外界的刺激,对输入进行处理,然后产生输出。当任务变得复杂时,多个神经元形成一个复杂的网络,相互传递信息。

人工神经网络试图模仿类似的行为。你下面看到的网络是由相互连接的神经元构成的神经网络。每个神经元的特征是其权重、偏置和激活函数

输入信息被输入到输入层,神经元使用权重和偏差对输入进行线性变换。
x = (weight * input) + bias

之后,对上述结果应用一个激活函数

最后,激活函数的输出移动到下一个隐藏层,重复相同的过程。这种信息的前向移动称为前向传播。

如果生成的输出与实际值相距甚远怎么办?利用前向传播的输出来计算误差。根据这个误差值,更新神经元的权值和偏差。这个过程称为反向传播。

注:要详细理解正向传播和反向传播,您可以阅读下面的文章:

Understanding and coding neural network from scratch
附链接:https://www.analyticsvidhya.com/blog/2017/05/neural-network-from-scratch-in-python-and-r/

2. 我们可以不使用激活函数么?

我们知道,在正向传播期间,使用激活函数会在每一层引入一个额外的步骤。现在我们的问题是,假如激活函数神经网络增加了复杂性,我们可以不使用激活函数吗?

想象一个没有激活函数神经网络在这种情况下,每个神经元只会利用权重和偏差对输入信息进行线性变换。虽然线性变换使神经网络更简单,但这个网络的功能会变得更弱,并无法从数据中学习复杂的模式。

没有激活函数神经网络本质上只是一个线性回归模型。

因此,我们对神经元的输入进行非线性变换,而神经网络中的这种非线性是由激活函数引入的。

在下一节中,我们将研究不同类型的激活函数、它们的数学公式、图形表示和python代码。

3. 常用的激活函数以及什么时候使用他们
  • 二元阶跃函数

当我们有一个激活函数时,首先想到的是一个基于阈值的分类器,即神经元是否应该根据线性变换的值被激活。

换句话说,如果激活函数的输入大于阈值,则神经元被激活,否则它就会失效,即它的输出不考虑下一个隐含层。让我们从数学的角度来看。
f(x) = 1, x>=0     = 0, x<0

这是最简单的激活函数,可以用python中的一个if-else判断来实现
def binary_step(x):    
if x<0:        
return 0    
else:        
return 1binary_step(5), binary_step(-1)
输出:
(5,0)

在创建二分类器时,可以将二二元阶跃函数用作激活函数。可以想象,当目标变量中有多个类时,这个函数将会失效。这就是二元阶跃函数的局限性之一。

此外,阶跃函数的梯度为零,在反向传播过程中造成了障碍。也就是说,如果计算f(x)关于x的导数,结果是0。

f'(x) = 0, for all x

反向传播过程中的权重和偏差是通过计算梯度来更新的。因为函数的梯度是零,所以权值和偏差不会更新。
  • Linear Function

在上面,我们看到了阶跃函数的问题是函数的梯度变成了0。这是由于在二元阶跃函数中没有x的分量,因此我们可以用线性函数代替二元函数。我们可以把这个函数定义为:
f(x)=ax

这里的活性值(activation)与输入成正比。本例中的变量“a”可以是任何常数值。让我们快速定义python中的函数:

def linear_function(x):
return 4*x linear_function(4), 
linear_function(-2)

输出:

(16, -8)

你认为这种情况下的导数是什么呢?当我们对函数关于x求导时,得到的结果将是x的系数,而这个系数是一个常数。

f'(x) = a

虽然这里的梯度不为零,但它是一个常数,与输入值x无关。这意味着权值和偏差在反向传播过程中会被更新,但更新因子是相同的。

在这种情况下,神经网络并不能真正改善误差,因为每次迭代的梯度是相同的。网络将不能很好地训练和从数据中捕获复杂的模式。因此,线性函数可能是需要高度解释能力的简单任务的理想选择。
  • Sigmoid

我们要看的下一个激活函数是Sigmoid函数。它是应用最广泛的非线性激活函数之一。Sigmoid将值转换为0和1之间。这是sigmoid的数学表达式:
f(x) = 1/(1+e^-x)

这里值得注意的一点是,与二元阶跃和线性函数不同,sigmoid是一个非线性函数。

这本质上意味着,当我有多个神经元以sigmoid激活函数作为它们的激活函数时,它们的输出也是非线性的。下面是在python定义函数的python代码:
import numpy as np
def sigmoid_function
(x):    z = (1/(1 + np.exp(-x)))    
return z sigmoid_function(7),sigmoid_function(-22)

输出:

(0.9990889488055994, 2.7894680920908113e-10)

另外,正如你在上图中看到的,这是一个光滑的s型函数,并且是连续可微的。这个函数的导数是(1-sigmoid(x))。让我们来看看它的梯度图。

f'(x) = 1-sigmoid(x)

梯度值在-3和3范围内是显著的,但在其他区域,图形变得更平坦。这意味着对于大于3或小于-3的值,梯度非常小。当梯度值趋近于0时,网络就不是真的在学习。

另外,sigmoid函数不是关于0对称的。所以所有神经元的输出都是相同的符号。这可以通过缩放sigmoid函数来解决,这正是tanh函数所做的。请让我们继续读下去。
  • Tanh

tanh函数与sigmoid函数非常相似。唯一不同的是它是关于原点对称的。本例中值的范围是从-1到1。因此,下一层的输入并不总是相同的符号。tanh函数定义为:
tanh(x)=2sigmoid(2x)-1

为了使用python编写代码,让我们简化前面的表达式。
tanh(x) = 2sigmoid(2x)-1
tanh(x) = 2/(1+e^(-2x)) -1
下面是它的python代码:
def tanh_function(x):    
z = (2/(1 + np.exp(-2*x))) -1
return z tanh_function(0.5), 
tanh_function(-1)
输出:
(0.4621171572600098, -0.7615941559557646)

就像你看到的,值的范围是-1到1。除此之外,tanh函数的其他性质都与sigmoid函数相同。与sigmoid相似,tanh函数在所有点上都是连续可微的。

我们来看看tanh函数的梯度。

与sigmoid函数相比,tanh函数的梯度更陡。你可能会好奇,我们如何决定选择哪个激活函数。通常tanh比sigmoid函数更受欢迎,因为它是以0为中心的,而且梯度不受一定方向的限制。
  • ReLU

ReLU函数是另一个在深度学习领域得到广泛应用的非线性激活函数。ReLU表示线性整流单元(Rectified Linear Unit)。与其他激活函数相比,使用ReLU函数的主要优点是它不会同时激活所有神经元

这意味着只有当线性变换的输出小于0时,神经元才会失效。下图将帮助你更好地理解这一点:
f(x)=max(0,x)

对于负的输入值,结果是零,这意味着神经元没有被激活。由于只有一定数量的神经元被激活,ReLU函数的计算效率远高于sigmoid和tanh函数。下面是ReLU的python函数:

def relu_function(x):    
if x<0:        
return 0    
else:        
return x relu_function(7), relu_function(-7)

输出:

(7, 0)
我们来看看ReLU函数的梯度。
f'(x) = 1, x>=0      
= 0, x<0

如果你观察图形的负方向,你会注意到梯度值是零。由于这个原因,在反向传播过程中,一些神经元权重和偏差没有更新。这可能会产生从未被激活的死亡神经元这种情况可通过“泄漏”ReLU函数来处理。
  • Leaky ReLU

Leaky ReLU函数只是ReLU函数的一个改进版本。如我们所见,对于ReLU函数,当x<0时,梯度为0,这将使该区域的神经元失活。

定义Leaky ReLU是为了解决这个问题。我们不把x的负值定义为0,而是定义为x的一个极小的线性分量,这里给出它的数学定义:
f(x)= 0.01x, x<0   
=   x, x>=0

通过这个小的修改,图形左边的梯度就变成了一个非零值。因此,我们将不再在那个区域遇到死亡的神经元。这是Leaky ReLU函数的导数

f'(x) = 1, x>=0     
     =0.01, x<0

因为Leaky ReLU是ReLU的一个变体,所以python代码可以通过一个小的修改来实现:
def leaky_relu_function(x):   
if x<0:        
return 0.01*x    
else:        return x leaky_relu_function(7), leaky_relu_function(-7)
输出:
(7, -0.07)
除了Leaky ReLU,还有一些其他的ReLU变体,最流行的是Parameterised ReLU函数和Exponential Liner Unit。
  • Parameterised ReLU

这是ReLU的另一个变体,旨在解决轴的左半部分的梯度为零的问题。顾名思义,参数化ReLU引入了一个新参数作为函数负部分的斜率。下面是如何修改ReLU函数以体现包含的斜率参数-
f(x) = x, x>=0    
= ax, x<0

当a的值固定为0.01时,函数就变成了Leaky ReLU函数。然而,对于Parameterised ReLU函数,‘a’也是一个可训练的参数。该网络还学习了' a '的值,以便更快、更优地收敛

这个函数的导数和Leaky ReLu函数是一样的,除了0.01的值会被替换成a的值。
f'(x) = 1, x>=0       
= a, x<0

当使用Leaky ReLU函数仍然不能解决未激活神经元问题,相关信息无法成功传递到下一层时,我们就可以使用Parameterised ReLU函数。
  • Exponential Linear Unit

指数化线性单元(简称ELU)也是线性整流单元(ReLU)的一种变体,它改变了函数负部分的斜率。与Leaky Relu和parametric Relu函数不同,ELU使用了Log曲线来代替直线定义函数的负数部分。它被定义为
f(x) = x,   x>=0    
= a(e^x-1), x<0

让我们在python中定义这个函数:
def elu_function(x, a):    
if x<0:        
return a*(np.exp(x)-1)    
else:        
return x elu_function(5, 0.1),elu_function(-5, 0.1)
输出:
(5, -0.09932620530009145)
ELU函数对于x大于0的值的导数是1,就像所有ReLU变体一样。但对于x<0的值,导数是a.e ^x 。
f'(x) = x,   x>=0    
= a(e^x), x<0
  • Swish

Swish是一个不太为人所知的激活函数,它是由谷歌的研究人员发现的。Swish的计算效率与ReLU相当,并且在层次更深的模型上显示出比ReLU更好的性能。swish的值从负无穷到正无穷。函数定义为-

f(x) = x*sigmoid(x)
f(x) = x/(1-e^-x)

正如你所看到的,函数曲线是平滑且在所有点上都是可微的。这在模型优化过程中是有帮助的,也是Swish被认为优于Relu的原因之一。

关于这个函数的一个独特的特征是,swich函数不是单调的。这意味着即使输入值增加,函数值也可能减少。让我们看看swish函数的python代码:
def swish_function(x):    
return x/(1-np.exp(-x)) 
swish_function(-67), swish_function(4)
输出:
(5.349885844610276e-28, 4.074629441455096)
  • Softmax

Softmax函数通常被描述为多个sigmoid的组合。我们知道sigmoid返回0到1之间的值,可将函数值视为数据点属于特定类的概率。因此,sigmoid被广泛应用于二分类问题

softmax函数可用于多类分类问题。这个函数返回属于每个类的数据点的概率。这是相同的数学表达式:

在为一个多类问题构建神经网络时,输出层的神经元数量与目标中的类的数量相同。

例如,如果你有三个类,在输出层会有三个神经元。假设神经元的输出是[1.2,0.9,0.75]。

对这些值应用softmax函数,您将得到以下结果—[0.42,0.31,0.27]。这些值表示这些数据点属于每个类的概率。值得注意的是,所有值的和为1。让我们在python中编码:
def softmax_function(x):    z = np.exp(x)    z_ = z/z.sum()    return z_ softmax_function([0.8, 1.2, 3.1])
输出:
softmax_function([1.2 , 0.9 , 0.75])

4.选择正确的激活函数

现在我们已经看到了这么多的激活函数,我们需要一些逻辑/启示来了解在什么情况下应该使用哪个激活函数。好或坏的判断并没有经验法则。

然而,根据问题的性质,我们可以做出更好的选择,使网络更容易、更快地收敛

  • 对于分类器,Sigmoid函数及其组合通常工作得更好。

  • 由于有梯度消失的问题,有时会避免使用sigmoid和tanh函数。

  • ReLU函数是一种通用的激活函数,目前被广泛使用。

  • 如果在我们的网络中遇到神经元未激活的情况,Leaky ReLU函数是最好的选择。

  • 始终记住,ReLU函数应该只在隐藏层中使用。

  • 根据经验,您可以从使用ReLU函数开始,然后在ReLU不能提供最佳结果的情况下转移到其他激活函数

项目

现在,是时候冒险尝试一下其他真实的数据集了。那么你准备好接受挑战了吗?通过以下实践问题加速你的深度学习之旅:

l Practice Problem: Identify the Apparels(见下面链接)
https://datahack.analyticsvidhya.com/contest/practice-problem-identify-the-apparels/?utm_source=fundamentals-deep-learning-activation-functions-when-to-use-them&utm_medium=blog

l Practice Problem: Identify the Digits(见下面链接)

https://datahack.analyticsvidhya.com/contest/practice-problem-identify-the-digits/?utm_source=fundamentals-deep-learning-activation-functions-when-to-use-them&utm_medium=blog 

结语:在本文中,我讨论了各种类型的激活函数,以及在使用它们时可能遇到的问题类型。我建议你先从ReLU函数开始,并随着你慢慢深入时,探索其他函数。你还可以设计自己的激活函数,为你的神经网络提供一个非线性组件。如果您使用了自己的激活函数并且效果非常好,请与我们分享,我们将很乐意将其纳入列表。
 
原文链接: 
https://www.analyticsvidhya.com/blog/2020/01/fundamentals-deep-learning-activation-functions-when-to-use-them/
原文标题:
Fundamentals of Deep Learning – Activation Functions and When to Use Them?
THU数据派
THU数据派

THU数据派"基于清华,放眼世界",以扎实的理工功底闯荡“数据江湖”。发布全球大数据资讯,定期组织线下活动,分享前沿产业动态。了解清华大数据,敬请关注姐妹号“数据派THU”。

入门激活函数深度学习
5
相关数据
深度学习技术

深度学习(deep learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。 深度学习是机器学习中一种基于对数据进行表征学习的算法,至今已有数种深度学习框架,如卷积神经网络和深度置信网络和递归神经网络等已被应用在计算机视觉、语音识别、自然语言处理、音频识别与生物信息学等领域并获取了极好的效果。

激活函数技术

在 计算网络中, 一个节点的激活函数定义了该节点在给定的输入或输入的集合下的输出。标准的计算机芯片电路可以看作是根据输入得到"开"(1)或"关"(0)输出的数字网络激活函数。这与神经网络中的线性感知机的行为类似。 一种函数(例如 ReLU 或 S 型函数),用于对上一层的所有输入求加权和,然后生成一个输出值(通常为非线性值),并将其传递给下一层。

权重技术

线性模型中特征的系数,或深度网络中的边。训练线性模型的目标是确定每个特征的理想权重。如果权重为 0,则相应的特征对模型来说没有任何贡献。

机器学习技术

机器学习是人工智能的一个分支,是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、计算复杂性理论等多门学科。机器学习理论主要是设计和分析一些让计算机可以自动“学习”的算法。因为学习算法中涉及了大量的统计学理论,机器学习与推断统计学联系尤为密切,也被称为统计学习理论。算法设计方面,机器学习理论关注可以实现的,行之有效的学习算法。

参数技术

在数学和统计学裡,参数(英语:parameter)是使用通用变量来建立函数和变量之间关系(当这种关系很难用方程来阐述时)的一个数量。

收敛技术

在数学,计算机科学和逻辑学中,收敛指的是不同的变换序列在有限的时间内达到一个结论(变换终止),并且得出的结论是独立于达到它的路径(他们是融合的)。 通俗来说,收敛通常是指在训练期间达到的一种状态,即经过一定次数的迭代之后,训练损失和验证损失在每次迭代中的变化都非常小或根本没有变化。也就是说,如果采用当前数据进行额外的训练将无法改进模型,模型即达到收敛状态。在深度学习中,损失值有时会在最终下降之前的多次迭代中保持不变或几乎保持不变,暂时形成收敛的假象。

导数技术

导数(Derivative)是微积分中的重要基础概念。当函数y=f(x)的自变量x在一点x_0上产生一个增量Δx时,函数输出值的增量Δy与自变量增量Δx的比值在Δx趋于0时的极限a如果存在,a即为在x0处的导数,记作f'(x_0) 或 df(x_0)/dx。

线性整流函数技术

线性整流函数(Rectified Linear Unit, ReLU),又称修正线性单元, 是一种人工神经网络中常用的激活函数(activation function),通常指代以斜坡函数及其变种为代表的非线性函数。比较常用的线性整流函数有斜坡函数f(x)=max(0, x),以及带泄露整流函数 (Leaky ReLU),其中x为神经元(Neuron)的输入。

神经网络技术

(人工)神经网络是一种起源于 20 世纪 50 年代的监督式机器学习模型,那时候研究者构想了「感知器(perceptron)」的想法。这一领域的研究者通常被称为「联结主义者(Connectionist)」,因为这种模型模拟了人脑的功能。神经网络模型通常是通过反向传播算法应用梯度下降训练的。目前神经网络有两大主要类型,它们都是前馈神经网络:卷积神经网络(CNN)和循环神经网络(RNN),其中 RNN 又包含长短期记忆(LSTM)、门控循环单元(GRU)等等。深度学习是一种主要应用于神经网络帮助其取得更好结果的技术。尽管神经网络主要用于监督学习,但也有一些为无监督学习设计的变体,比如自动编码器和生成对抗网络(GAN)。

线性回归技术

在现实世界中,存在着大量这样的情况:两个变量例如X和Y有一些依赖关系。由X可以部分地决定Y的值,但这种决定往往不很确切。常常用来说明这种依赖关系的最简单、直观的例子是体重与身高,用Y表示他的体重。众所周知,一般说来,当X大时,Y也倾向于大,但由X不能严格地决定Y。又如,城市生活用电量Y与气温X有很大的关系。在夏天气温很高或冬天气温很低时,由于室内空调、冰箱等家用电器的使用,可能用电就高,相反,在春秋季节气温不高也不低,用电量就可能少。但我们不能由气温X准确地决定用电量Y。类似的例子还很多,变量之间的这种关系称为“相关关系”,回归模型就是研究相关关系的一个有力工具。

逻辑技术

人工智能领域用逻辑来理解智能推理问题;它可以提供用于分析编程语言的技术,也可用作分析、表征知识或编程的工具。目前人们常用的逻辑分支有命题逻辑(Propositional Logic )以及一阶逻辑(FOL)等谓词逻辑。

噪音技术

噪音是一个随机误差或观测变量的方差。在拟合数据的过程中,我们常见的公式$y=f(x)+\epsilon$中$\epsilon$即为噪音。 数据通常包含噪音,错误,例外或不确定性,或者不完整。 错误和噪音可能会混淆数据挖掘过程,从而导致错误模式的衍生。去除噪音是数据挖掘(data mining)或知识发现(Knowledge Discovery in Database,KDD)的一个重要步骤。

分类问题技术

分类问题是数据挖掘处理的一个重要组成部分,在机器学习领域,分类问题通常被认为属于监督式学习(supervised learning),也就是说,分类问题的目标是根据已知样本的某些特征,判断一个新的样本属于哪种已知的样本类。根据类别的数量还可以进一步将分类问题划分为二元分类(binary classification)和多元分类(multiclass classification)。

神经元技术

(人工)神经元是一个类比于生物神经元的数学计算模型,是神经网络的基本组成单元。 对于生物神经网络,每个神经元与其他神经元相连,当它“兴奋”时会向相连的神经元发送化学物质,从而改变这些神经元的电位;神经元的“兴奋”由其电位决定,当它的电位超过一个“阈值”(threshold)便会被激活,亦即“兴奋”。 目前最常见的神经元模型是基于1943年 Warren McCulloch 和 Walter Pitts提出的“M-P 神经元模型”。 在这个模型中,神经元通过带权重的连接接处理来自n个其他神经元的输入信号,其总输入值将与神经元的阈值进行比较,最后通过“激活函数”(activation function)产生神经元的输出。

模型优化技术

像卷积神经网络(CNN)这样的深度学习模型具有大量的参数;实际上,我们可以调用这些超参数,因为它们原本在模型中并没有被优化。你可以网格搜索这些超参数的最优值,但需要大量硬件计算和时间。改进模型的最佳方法之一是基于在你的领域进行过深入研究的专家的设计和体系结构,他们通常拥有强大的硬件可供使用。常见的简单模型优化技巧包括迁移学习、dropout、学习率调整等

推荐文章
暂无评论
暂无评论~