前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深度学习基础知识(一)--激活函数

深度学习基础知识(一)--激活函数

原创
作者头像
languageX
发布2022-05-04 16:16:09
发布2022-05-04 16:16:09
4.4K1
举报
文章被收录于专栏:计算机视觉CV

激活函数的意义

在神经网络中加入激活函数存在的意义就是为网络增加非线性因素,比如全卷积神经网络,不加入激活函数,就是一堆线性操作矩阵运算,对于复杂任务仅用线性操作而不用复杂的函数表示肯定效果不会好。

最常用来举例的图

上图中的分类问题,左图可以用线性函数解决,中间靠线性函数就不能解决,需要右图的非线性函数来解决。这就是我们要在网络中加入激活函数增加非线性因素的原因,解决线性模型无法解决的问题。

在分析具体激活函数前,我们先了解一些基础概念。

梯度消失(vanishing gradient)和爆炸(exploding gradient)

根据深度学习中参数更新,采用梯度下降策略会运用反向传播,而由于深度学习中网络层数肯定不止一层,根据链式求导法则,我们对浅层参数的求导会有一个连乘操作,前面层的梯度是来自于后面层梯度的乘积。

如果网络层中多层的梯度均大于1,穿过多层后求出的梯度更新会以指数形式增加(前面层的更新速度远远快于后面层)就属于梯度爆炸现象;反之如果多层梯度均小于1,前面层的更新速度远低于后面层,更新特缓慢,那么就属于梯度消失现象。

梯度消失和梯度爆炸均会引起训练不稳定。

zero-centered

很多地方会提出希望网络层的输入是zero-centered零均值化的,包括数据预处理我们也通常会讲输入数据进行一个归一化,那么数据以0为中心有什么好处呢?

为了加速参数收敛。

假设我们的网络定义为:

代码语言:txt
复制
                                                     `$f(x;w,b) = f(w_0 x_0+w_1 x_1+b)$` 

假设,参数 w_0, w_1 的最优解 w_0^∗, w_1^* 需要满足条件

\begin {cases}w_0 < w_0^* \\w_1 >=w_1^* &\end{cases}

也就是希望参数的梯度是反方向,也就是x0和x1符号相反。如果数据是零均值化,就能走下图中蓝色快速收敛方向;否则如果同大于0或者同小于0就出现了zig zag path,一个折线图,收敛缓慢。

常用激活函数

下面来介绍常用的各种激活函数以及优缺点~

sigmoid

sigmoid目前在网络层中使用的比较少,但是在分类问题特别是二分类,多标签分类的输出层是还是会经常使用的。

sigmoid函数:

sigmoid求导:

具体求导过程不详细介绍了:https://www.jianshu.com/p/0182ae2ad5f5

sigmoid曲线图
sigmoid曲线图

通过函数曲线看出,sigmoid取值范围是0,1,所以他可以在分类问题的输出层使用。

现在在网络中间层不太使用sigmoid作为激活函数主要原因是存在如下几个缺点:

  1. 计算量大,公式内有个指数函数,反向传播求导数还带个除法
  2. 容易出现梯度消失,从曲线看在左右端导数很平缓趋于0,学不到深层网络层的信息
  3. 输出不是zero-centered,因为sigmoid的输出一直都是正值,会让本层的输出均为正或者均为负,在寻找最优解时会走一个折线(zigzag现象),降低了收敛速度。所以在训练过程中对输入最好时能zero-centered。

softmax

softmax也是将输出归一化到0,1之间,所有元素的和累加起来等于1。可以直接当作概率对待,一般用在分类问题的输出层。

softmax公式,i分量的向量z_i的softmax公式为:

偏导数不详细介绍,可参考https://zhuanlan.zhihu.com/p/105722023

softmax曲线
softmax曲线

tanh

tanh 其实算sigmoid的变形

公式为:

导数公式:

tanh曲线
tanh曲线

通过曲线可以看出,tanh解决了sigmoid的zero-centered问题,但是梯度消失和计算量的问题还存在。

relu(rectifier linear unit)

relu目前是比较主流的激活函数,扔掉一部分神经元的输出,让网络稀疏,可以一定程度防止过拟合。而且计算简单(relu并不是处处可导,0点有特殊处理)。

relu公式:

relu的优势是计算很简单,不存在梯度消失的问题。而且从生物学角度,通常神经元真正被激活在同一时间大概只有4%,relu可以抑制激活。

relu的缺点是它并不是zero-centered的,而且单侧抑制对于某些神经元可能一直都不会被激活,如果初始化不好或者恰好输入都到了负数部分,可能导致网络均不被激活参数无法学习。这种现象叫Dead ReLU Problem。

有两个主要原因可能导致这种情况产生: (1) 非常不幸的参数初始化,这种情况比较少见 (2) learning rate太高导致在训练过程中参数更新太大,不幸使网络进入这种状态。解决方法是可以采用Xavier初始化方法,以及避免将learning rate设置太大或使用adagrad等自动调节learning rate的算法。

relu曲线
relu曲线

relu6

如果对relu不加限制,其输出值就是0到正无穷大。relu6就是在relu的基础上增加一个抑制最大值,当x>6时,其导数也为0.

公式:

relu6曲线
relu6曲线

leaky relu

leaky relu和relu的区别是,relu是将所有的负值都设为零,Leaky ReLU是给负值赋予一个非零斜率。

leaky relu公式:

leaky relu的好处就是可以解决relu的神经元死亡问题,在反向传播时,对于输入小于零的部分,也可以计算得到梯度。

leaky_relu曲线
leaky_relu曲线

R-Relu和P-Relu

R-Relu(随机修正线性单元)和P-Relu(参数化修正线性单元)都是leaky relu的变体。RRelu是对leaky relu的\ $``$\alpha参数进行随机取值,随机取值能够对优化带来一定的随机性,随机噪声能够帮助参数取值跳出局部最优;而PPelu时将\alpha作为学习参数,通过数据进行学习得到。

elu(exponential linear unit)

ELU融合了sigmoid和relu。它的输出均值接近于零,所以收敛速度更快。左侧单边饱和,可以更好的收敛。但是elu也有个缺点就是,计算量较大,包含了指数计算。

elu公式:

elu求导:

softplus

softplus公式

按照论文的说法,一开始想要使用一个指数函数(天然正数)作为激活函数来回归,但是到后期梯度实在太大,难以训练,于是加了一个log来减缓上升趋势。加了1是为了保证非负性。和relu一样不会有梯度饱和问题,缺点是和sigmoid一样计算量大。

softplus曲线
softplus曲线

swish

swish是谷歌大脑提出的,其公式:

求导公式

和 ReLU 一样,Swish 无上界有下界。与 ReLU 不同的是,Swish 是平滑且非单调的函数。

swish曲线
swish曲线

h-swish

通过公式可以看出swish的计算量也很大,h-swish是使用relu6来近似swish,如下图

h-swish公式
h-swish公式
hswish曲线
hswish曲线

代码实现

最后列举下常用激活函数的代码实现:

代码语言:python
代码运行次数:0
复制
def linear(x,k=1):
    """
    linear activation

    公式: y = kx

    """
    y = k*x
    return y


def sigmoid(x, derivative=False):
    """
    sigmoid activation

    公式: y = \frac{1}{e^(-x) + 1} = \frac{e^x}{e^x + 1}
    导数公式: sigmoid*(1-sigmoid)

    """
    y =  1/(1+np.exp(-x))
    if derivative:
        return y*(1-y)
    return y



def tanh(x, derivative=True):
    """
    tanh activation

    公式: y =  {{e^{2x} - 1} \over {e^{2x} + 1}}.

    """
    y =  (np.exp(2*x)-1)/(np.exp(2*x)+1)
    if derivative:
        return 1-y*y
    return y


def softmax(x):
    """
    relu activation

    公式: y = \frac{e^x}{sum(e^x)}

    """
    exp_x = np.exp(x)

    y = exp_x / np.sum(exp_x)
    return y


def relu(x):
    """
    relu activation

    公式: y = max(0,x)

    """
    y = np.where(x > 0, x, 0)
    return y

def relu6(x):
    """
    relu activation

    公式: `{\rm min}({\rm max}(x, 0), 6)`

    """
    maxx = np.where(x > 0, x, 0)
    return np.where(maxx < 6, maxx, 6)

def leaky_relu(x, alpha=0.5):
    """
    leaky relu activation

    公式: y = max(alpha * x, x)

    """
    y =  np.where(x < 0, alpha * x, x)
    return y


def elu(x):
    """
    leaky elu activation

    公式:  y = \left\{ {\begin{array}{*{20}{c}}{x,\;\;\;\;\;\;\;\;\;x \ge 0}\\{{e^x} - 1,\;\;\;x < 0}\end{array}} \right..

    """
    return np.where(x < 0, np.exp(x) - 1, x)
    return y

def swish(x, beta=1.0):
    """
    swish
    x * sigmoid(beta*x)

    公式: :`y = x\cdot {\rm sigmoid}(\beta x) = {e^{(\beta x)} \over {e^{(\beta x)} + 1}} \cdot x`

    """

    ex = np.exp(beta * x)

    return (ex / (ex + 1)) * x

def softplus(x):
    """
    swish: `log(exp(x) + 1)`.

    公式: `{\rm log}(e^x + 1)`

    """

    return np.log(np.exp(x) + 1)

def hswish(x):
    """
    h-swish:

    公式: x*relu6(x+3)/6

    """

    return x*(relu6(x+3))/6

后续持续更新...

参考:

https://liam.page/2018/04/17/zero-centered-active-function/

https://zhuanlan.zhihu.com/p/25110450

https://www.cnblogs.com/shiliuxinya/p/12244519.html

https://zhuanlan.zhihu.com/p/172254089

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 激活函数的意义
  • 梯度消失(vanishing gradient)和爆炸(exploding gradient)
  • zero-centered
  • 常用激活函数
    • sigmoid
      • softmax
        • tanh
          • relu(rectifier linear unit)
            • relu6
              • leaky relu
                • R-Relu和P-Relu
                  • elu(exponential linear unit)
                    • softplus
                      • swish
                        • h-swish
                        • 代码实现
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档