【DL基础】盘天盘地盘“直男”,激活函数不简单

独自空忆成欢 提交于 2021-02-06 01:30:44

戳一戳!和我一起走进深度学习的世界

导读

我们常常在深度学习中听到激活函数的概念,作为深度学习中的经典“骚操作”,激活函数一直在发浪,却从未被超越。

今天要分享这篇文章带我们一起了解什么是激活函数?为什么要有激活函数?激活函数都有哪些?它们的优缺点分别是什么?让我们走进这篇文章,一起来了解一下吧!

如果你有什么问题,或者有什么想法,欢迎评论与我一起沟通交流。



如果你想了解更多有关于机器学习、深度学习、计算机视觉、OpenCV、等相关技术的内容,想与更多大佬一起沟通,那就加群:326866692 或者扫描下方二维码加入我们吧!



本文目录

导读

1 激活函数是什么

2 为啥要引入激活函数

    A 引入非线性

    B 修正线性结果

3 常见激活函数

    A Sigmoid

    B tanh

    C arctan

    D ReLU

    E ReLU变异家族

    F 其他激活函数

4 为啥要求激活函数可导

1 激活函数是什么

我们常常听到激活函数,特别是当我们深入研究深度学习的时候,在我们搭建神经网络的时候,我们经常会使用激活函数,当然也有一些小伙伴可能还不是特别熟悉激活函数,所以我们先来看一下激活函数是什么?


当我们对图像做完卷积操作,添加偏置量(不是必须)之后,我们能够得到一个计算结果,把这个计算结果作为输入,经过一个函数得到我们想要的输出。这个函数就是激活函数。


上面这句话说得有点土,就是为了能让大家更直白地理解,现在我们有个大致的印象了,激活函数就是一个“加工厂”,比如:


整容工厂


你也可以把激活函数当成一个大爷,盘天盘地盘万物。看见一个东西,干干巴巴的,麻麻赖赖的,一点都不圆润,盘他!



玩笑说完了,接下来我们来看一个比较标准的描述吧:


神经网络中的每个神经元节点接受上一层神经元的输出值作为本神经元的输入值,并将输入值传递给下一层,输入层神经元节点会将输入属性值直接传递给下一层(隐层或输出层)。在多层神经网络中,上层节点的输出和下层节点的输入之间具有一个函数关系,这个函数称为激活函数(又称激励函数)


2 为啥要引入激活函数

我们知道了激活函数大概是个啥了之后,就要来看一下,为啥要引入激活函数了?


因为好用呗!!!



当然,我们作为新时代好青年,肯定不能这样迷惑自己,比较,我们还要明明白白地改变世界,改变自己,所以我们就不能不明不白地学习。

为啥要引用激活函数,主要是因为如下两个原因:

A 引入非线性

来,我们先来看几个激活函数图像:


_
_
_
_
_

_
_
_
_
_

_
_
_
_
_

_
_
_
_
_

_
_
_
_
_

_
_
_
_
_

激活函数图像示例


你发现了啥?


可能不咋好发现,那我们举个栗子:


我们设置两个函数:



对于这个函数呢,我们画一下他们对应的图像,图像如下:


图像


本来是根好好的长长的棍,咋就被掰弯了呢?没错,激活函数的第一个功能就是把前一层的结果“掰弯”。前一层操作中,我们得到的一个结果是线性结果,这会有问题的。


我们以最简单的神经网络单层感知机为例讲解一下,单层感知机只有输入层和输出层。下图是一个只有2个输入单元和1个输出单元的简单单层感知机。图中x1、x2代表神经网络的输入神经元,w1、w2代表输入神经元的权重,b代表输偏置量,y为输出神经元的输出。则,我们的输出就是:

y=w1*x1+w2*x2+b


这个公式对应的图像如下:


单层感知机


我们可以使用该单层感知机划出一条线将平面分割开:

单层感知机分割平面


单层感知机可以较好地进行二分类,将明显的两种类别的物体分别开来,但是真实世界都是这么简单地情况吗?


并不是,可能我们遇到的是这样的:


非线性分布


这样的话,如果我们使用传统的这种感知机就无法解决了,所以我们通过引入激活函数引入非线性,就可以实现非线性分类了:


非线性分类



B 修正线性结果

这个我们在讲LeNet-5的时候简单提到过。

当我们计算神经网络得到输出的时候,因为是线性结果,所以,输出的结果很可能就超出了我们的范围:


卷积操作


以卷积操作计算神经网络为例,假设我们图像的像素范围是0-9。当我们使用卷积操作之后,我们会发现有的位置上的的值已经不在像素范围之内了。这在图像编码的时候是会出错的。那怎么办呢?

最简单的想法是,我们可以把大于9的统统改为9,小于0的统统改为0,这样,我们就能保证图像的像素在一个合法的范围内了。我们把这个想法用数学公式表示一下,就是下面这个公式:

数学公式


这个公式起到的就是修正像素的作用,可以让像素停留在一个合法区间之内的。这个公式对应的修正图如下:


修正图


除了这种情况,在输出结果中,我们经常也要输出概率值,那我们就需要把值转化到0-1之间,我们可能也只需要非负值,那我们就需要把所有的负值变为0。所以我们需要通过激活函数,修正输出范围。所以有一些激活函数也有人叫做修正线性单元,例如ReLU是最基本的修正线性单元。

3 常见激活函数

现在我们对激活函数有个比较深刻的认识了,现在,我们来看看激活函数这个家族里面,都有哪些“人才”吧!


讲到这些可能激活函数就不服了,确实咱们太厉害。激活函数,不服出来比比,看谁认识谁。



讲真,激活函数确实人多势众,这不是吹得:


激活函数


接下来就让我们一起来看一下这里面常见的激活函数吧!

A Sigmoid

Sigmoid 函数是一个 Logistic 函数,也是传统神经网络中最常用的激活函数。不管你的输入是什么,得到的输出都在 0 到 1 之间。也就是说,你输入的每个神经元、节点或激活都会被缩放为一个介于 0 到 1 之间的值。我们看后面这个图像,我们也会发现,这个图在x=0处的导数最大,在x趋于无穷导数最小,而且导数是恒大于等于0的。


Sigmoid函数定义如下:

Sigmoid函数导数如下:

Sigmoid函数与导数图像如下:

优点

(1)便于求导:我们发现,这个函数非常的光滑,从导出定义来说,就是处处可导,而且求导也比较方便。后面我们会讲为什么要对激活函数求导数。

(2)便于数据压缩:我们发现,不管什么输入,我们都能通过该函数将输出变到0-1之间。比较好的一个例子就是,我们能很容易通过输入数据归一化。

(3)适合前向传播:Sigmoid函数形式简单,计算简单,所以非常适合前向传播。


缺点

(1)容易饱和:我们发现,这个函数图像在x的取值非常大或者非常小的时候,我们发现导数几乎是趋于0的,也就是说梯度是几乎趋于0的,那我们在使用梯度下降算法的时候,由于梯度太小,权重更新太慢,甚至几乎没有更新,也就是所谓的梯度消失(gradient vanishing)问题

(2)输出不是0均值:我们发现,这个图像是关于(0,0.5)对称的,出入值的均值为0,输出值的均值为0.5,也就是说,这个激活函数输出不是0均值。

以 f=sigmoid(wx+b)为例, 假设输入均为正数(或负数),那么对w的导数总是正数(或负数),这样在反向传播过程中要么都往正方向更新,要么都往负方向更新,导致有一种捆绑效果,使得收敛缓慢。

(3)幂函数计算复杂:Sigmoid函数虽然形式简单,但是涉及到幂运算,相对于简单的加减法运算或者赋值运算,计算还是相对比较复杂的。


B tanh

tanh函数也叫双曲正切函数,是双曲函数的一种。tanh函数跟sigmoid还是很像的,我们可以理解为tanh是sigmoid的变形,是在sigmoid基础上的改进,tanh函数将压缩范围调整为(-1,1)。


tanh函数定义如下:

tanh函数导数如下:

tanh函数及导数图像如下:

优点

(1)上面有的我都有:我们知道tanh函数是Sigmoid函数的变体,求导一样方便,也便于数据压缩,适合前向传播。唯一不同就是数据压缩得到的范围不同。

(2)0均值:tanh是0均值的,所以tanh的优点是相对于Sigmoid函数说的,tanh函数是0均值的更加有利于提高训练效率,解决上面提到的非0均值的问题。


缺点

tanh只解决了Sigmoid函数的第二个缺点,但另外两个缺点也依然是存在的。

(1)容易饱和:我们发现,这个函数图像在x的取值非常大或者非常小的时候,我们发现导数几乎是趋于0的,也就是说梯度是几乎趋于0的,那我们在使用梯度下降算法的时候,由于梯度太小,权重更新太慢,甚至几乎没有更新,也就是所谓的梯度消失(gradient vanishing)问题。

(2)幂函数计算复杂:tanh函数虽然形式简单,但是涉及到指数运算,相对于简单的加减法运算或者赋值运算,计算还是相对比较复杂的。

C arctan

arctan函数也叫反正切函数,是tan函数的反函数,是三角函数的一种。arctan函数跟sigmoid和tanh函数长得很像,tanh函数将压缩范围调整为(-π/2,π/2)。


arctan函数定义如下:

arctan函数导数如下:

arctan函数及导数图像如下:

优点

(1)上面有的我都有:我们知道arctan函数与上面的两个函数是类似的,并且arctan也是0均值的,所以arctan函数有tanh函数的所有优点。

(2)导趋于0速度更慢:tanh是的导数在趋于0的速度相比较上面两个更慢了,这意味着当数据量比较大或者比较小的时候学习的计算效率更高。


缺点

tanh只解决了Sigmoid函数的第二个缺点,但另外两个缺点也依然是存在的。

(1)较易饱和:虽然在x值较大的时候,导数趋于0的速度更慢,但是当x非常大的时候,导数也是逐步趋于0的,还是会在很大的时候,梯度太小,梯度消失(gradient vanishing)问题依然存在。

(2)计算昂贵:很多地方都这样说,抄过来超过去,但没有一个说,为啥会计算昂贵。我在这里说一下我的理解,上面说arctan函数比tanh函数趋于0的速度慢,所以在前期,tanh函数的导数值更大,梯度更加,计算速度就更快,梯度下降速度更快,arctan函数因为趋于0的速度慢,前期导数小,梯度下降速度慢,所以计算比较昂贵。

D ReLU

ReLU函数是比较经典的激活函数了,它的全称是:Rectified Linear Unit,就是说它是一个线性整流函数,也称为修正线性单元,它可以对线性函数做修正,将所有的负数值变为0,这种对数据的处理方式是最简单,最直接的线性整流方式。ReLU自从被提出来,就成为了王者的存在,成为王者的主要原因在于计算复杂度极低,对于神经网络这种高复杂。高计算量的运算,这简直太棒了。但是ReLU 也不是百分之百完美的,数学告诉我们:这世界没有什么是百分百完美的。接下来,我们一起深入学习一下ReLU吧。


ReLU函数定义如下:

ReLU函数导数如下:

ReLU函数及导数图像如下:

优点

(1)计算复杂度低:ReLU实现,就是一个判断语句加上一个赋值语句,相对于上面提到的指数运算,幂运算,赋值运算的计算复杂度是极低的。这个特性是超棒的,对于神经网络这种大计算量的运算,一种能够简单,低计算量的激活函数能够极大的提高训练速度。

(2)梯度不会饱和:在x大于0的地方,梯度的恒定的,也就是说ReLU不会因为数据量的增大而使得梯度饱和,这完美解决了梯度消失问题。

第一个优点是主要优点,第二个优点算是强辅助,正是因为上面这两个个优点,再加上他的缺点不是很坑,所以是很多神经网络中最常用的激活函数,但是,ReLU不是无所不能的,当然没有百分百完美的激活函数,所以我们自己写神经网络的时候,先考虑ReLU函数,不适用,再换用其他的


所以,如果别人问你,你为什么要使用ReLU呢?你应该回答:


缺点

一个人有多大的优点,就有多大的缺点,激活函数也是如此,它的优点放在另外一个角度来看就是缺点了。

(1)处理暴力:处理方式太暴力了,凡是小于0的全部变为0,所以我们一旦输入中有大量负值,网络输入就会把它们都变为0,不分青红皂白啊,有可能负的也是特征,如果全部变为0之后,这些特征就大面积“坏死”了。

(2)不会数据压缩:ReLU不会对数据做幅度压缩,所以数据的幅度会随着模型层数的增加不断扩张。

注:ReLU的缺点还是有一些的,其实根源就是上面这两个,或者说就是因为第一个缺点,因为处理太暴力,所以它不会压缩数数据,暴力处理输入,容易造成特征大面积“坏死”,正数据没有操作,依然是线性等

E ReLU变异家族

ReLU函数优点太棒,但是也有一些问题,针对这些问题,提出了各种变形,这些变形的特点就是数据处理温柔一些,不直接暴力赋值为0了。ReLU函数通过损失一些计算量,来提升原始ReLU函数的性能。


ReLU函数家族定义如下:


ReLU家族


ReLU函数家族图像如下:


ReLU家族


介绍

(1)Leaky ReLU:全称为:带泄露修正线性单元(Leaky ReLU)的输出对负值输入有很小的坡度。由于导数总是不为零,这能减少静默神经元的出现,允许基于梯度的学习(虽然会很慢)看下图x左半轴的斜率,几乎感受不到变化,但是这也能很大程度上解决负值被暴力赋值为0,Leaky ReLU的提出是用来解决ReLU带来的神经元坏死的问题。

Leaky ReLU

特点:Leaky ReLU不是暴力赋值,不会出现神经元死亡的情况。对于所有的输入,不管是大于等于0还是小于0,神经元不会饱和。由于Leaky ReLU线性、非饱和的形式,在SGD中能够快速收敛。虽然比ReLU计算速度慢了一些,但不管在前向传播还是反向传播,计算速度都比sigmoid和tanh快很多。


(2)RReLU:全称为:随机带泄露的修正线性单元(Randomized Leaky Rectified Linear Unit,RReLU),是 Leaky ReLU 的一个变形,为负值输入添加了一个线性项。而最关键的区别是,这个线性项的斜率在每一个节点上都是随机分配的(通常服从均匀分布)。

特点:RReLU是Leaky ReLU的random版本,在训练过程中,α是从一个高斯分布中随机出来的,然后再测试过程中进行修正。灵活性更高。例如下图中的α是一个随机负值

RReLU


(3)PReLU:全称为:参数化修正线性单元(Parameteric Rectified Linear Unit,PReLU),它和 RReLU 以及 Leaky ReLU 有一些共同点,即为负值输入添加了一个线性项。而最关键的区别是,这个线性项的斜率不是随机生成的,而是在模型训练中学习到的。

PReLU


(4)ELU:全称为:指数线性单元(Exponential Linear Unit,ELU),和 PReLU 以及 RReLU 类似,为负值输入添加了一个非零输出。和其它修正类激活函数不同的是,它包括一个负指数项,从而防止静默神经元出现,导数收敛为零,从而提高学习效率

ELU


(5)SELU:全称为:扩展指数线性单元(Scaled Exponential Linear Unit,SELU)是激活函数指数线性单元(ELU)的一个变种。其中λ和α是固定数值(分别为 1.0507 和 1.6726)。这些值背后的推论(零均值/单位方差)构成了自归一化神经网络的基础(SNN)。

SELU


(6)SReLU:全称为:S 型整流线性激活单元(S-shaped Rectified Linear Activation Unit,SReLU),它由三个分段线性函数组成。其中两种函数的斜度,以及函数相交的位置会在模型训练中被学习。

SReLU


F 其他激活函数

除了上述激活函数,还有很多各种各样的激活函数,上面的激活函数是我们最常用的激活函数,基本原理,优缺点也讲的差不多了,剩下的 不过多赘述,大家有兴趣,可以看看这个网站中,每种激活函数的图像及特点:

https://dashee87.github.io/deep%20learning/visualising-activation-functions-in-neural-networks/

举个示例如下:

Soft Sign及其导数

4 为啥要求激活函数可导

前面我们说了好多,也经常提到,我们的这个激活函数是要可导,为什么一定要可导呢?


哦们做完激活操作之后,我们就要使用梯度下降算法,梯度下降算法,需要梯度,这个从名字就能看到,所以我们需要对激活函数求导,也就是我们要尽量满足,激活函数是可导的。



如果喜欢这篇文章

麻烦给我一个在看




本文分享自微信公众号 - AI与区块链技术(Math_AI_Blockchain)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!