神经网络中的激活函数

神经网络中的激活函数

1.什么是激活函数?

神经网络中,在隐藏层接一个线性变换后,再接一个非线性变换(sigmoid、tanh、ReLu等),这种非线性变换叫做激活函数(Activation Function)或者传递函数。
在这里插入图片描述

2.为什么要使用激活函数?

激活函数一般都是非线性函数,神经网络中的激活函数它的主要作用是提供网络的非线性建模能力。如果你的神经网络模型中,使用线性激活函数或者没有使用一个激活函数,那么无论多少层的神经网络模型一直在做的只是计算线性函数,不如去掉全部隐藏层。在实例中证明,在隐藏层使用线性激活函数,输出层用sigmoid函数,这个模型的复杂度和没有隐藏层的logistic回归是一样的。
在神经网络中,隐藏层使用线性激活函数几乎没啥用处,线性函数的组合本身就是线性函数。当引入非线性激活函数才会让模型变得有意义。

3.常用的激活函数

3.1 sigmoid函数/Logistic函数

sigmoid函数: a = g ( z ) = 1 1 + e − z a=g\left ( z \right )=\frac{1}{1+e^{-z}} a=g(z)=1+ez1
sigmoid函数的导数: g ( z ) ′ = d d z g ( z ) = α ( 1 − α ) g({z})'=\frac{d}{dz}g\left ( z \right )=\alpha (1-\alpha ) g(z)=dzdg(z)=α(1α)
在这里插入图片描述缺点:
1.sigmoid在定义域内处处可导,并且导数逐渐趋近于0。如果Z值很大或者很小的时候,函数的梯度(斜率)也就会非常小,在反向传播过程中,导致向底层传输的梯度也变得非常小,此时网络参数很难得到有效训练。这种现象称为梯度消失。
2.sigmoid的输出不是以0为中心。导致在反向传播过程中,要么都往正方向更新要么往负方向更新,使得收敛缓慢。
3.解析式中含有幂运算,计算求解比较耗时。

sigmoid代码实现如下:

def sigmoid(x):
    """sigmoid函数"""
    return 1 / (1 + np.exp(-x))
     
def der_sigmoid(x):
     """sigmoid函数的导数"""
    return sigmoid() * (1 - sigmoid(x))

3.2 tanh函数(双曲正切函数)

tanh函数: a = g ( z ) = t a n h ( z ) = e z − e − z e z + e − z a=g\left ( z \right )=tanh\left ( z \right )=\frac{e^{z}-e^{-z}}{e^{z}+e^{-z}} a=g(z)=tanh(z)=ez+ezezez
tanh函数的导数: g ( z ) ′ = d d z g ( z ) = 1 − ( t a n h ( z ) ) 2 g(z)'=\frac{d}{dz}g(z)=1-(tanh(z))^{2} g(z)=dzdg(z)=1(tanh(z))2
在这里插入图片描述优点:
tanh函数解决了sigmoid函数的不是zero-centered输出问题,输出均值是0。

缺点:
sigmoid函数和tanh函数两者共同的缺点:在𝑧特别大或者特别小的情况下,导数的梯度或者函数的斜率会变得特别小,最后就会接近于 0,导致降低梯度下降的速度。

tanh代码实现如下:

def tanh(x):
    """tanh函数"""
    return ((np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x)))
 
def der_tanh(x):
    """tanh函数的导数"""
    return 1 - tanh(x) * tanh(x)

3.3 ReLu函数(修正线性单元函数)

ReLu函数: a = m a x ( 0 , z ) a=max(0,z) a=max(0,z)
ReLu函数的导数: g ( z ) ′ = { 0 , i f z < 0 1 , i f z > 0 u n d e f i n e d , i f z = 0 } g(z)^{'}=\begin{Bmatrix} 0 ,& if z<0\\ 1,& if z>0\\ undefined,& if z=0 \end{Bmatrix} g(z)=0,1,undefined,ifz<0ifz>0ifz=0

在这里插入图片描述优点:
ReLu函数是目前最常用的默认选择激活函数。当x>0时,不存在饱和问题,在x>0时保持梯度不衰减,缓解梯度消失的问题。并且收敛速度远快于sigmoid和tanh。

缺点:
当x<0时,ReLu硬饱和,随着训练的推进,部分输入会落入到硬饱和区,导致权重无法更新。和sigmoid类似,ReLu的输出均值大于0,出现偏移现象。

ReLu代码实现如下:

def relu(x):
    """relu函数"""
    temp = np.zeros_like(x)
    if_bigger_zero = (x > temp)
    return x * if_bigger_zero
 
def der_relu(x):
    """relu函数的导数"""
    temp = np.zeros_like(x)
    if_bigger_equal_zero = (x >= temp)
    return if_bigger_equal_zero * np.ones_like(x)

3.4 Leaky-ReLu函数(PReLu)

PReLu函数: a = m a x ( α z , z ) a=max(αz,z) a=max(αz,z)
ReLu函数的导数: g ( z ) ′ = { α , i f z < 0 1 , i f z ≥ 0 } g(z)^{'}=\begin{Bmatrix} \alpha ,& if z<0\\ 1,& if z\geq 0 \end{Bmatrix} g(z)={α,1,ifz<0ifz0}
在这里插入图片描述PReLU也是针对ReLU的一个改进型,在负数区域内,PReLU有一个很小的斜率,这样也可以避免ReLU死掉的问题。相比于ELU,PReLU在负数区域内是线性运算,斜率虽然小,但是不会趋于0,这算是一定的优势吧。

我们看PReLU的公式,里面的参数α一般是取0~1之间的数,而且一般还是比较小的,如零点零几。当α=0.01时,我们叫PReLU为Leaky ReLU,算是PReLU的一种特殊情况吧。

PReLu代码实现如下:

def prelu(x):
    """prelu函数"""
    return np.where(x<0,alpha * x,x)

def der_prelu(x):
    """prelu函数的导数"""
    return np.where(x<0,alpha,1)

3.5 softmax函数

softmax用于多分类过程中,它将多个神经元的输出,映射到(0,1)区间内,可以看成概率来理解。
softmax函数公式:
S i = e i ∑ j e j S_{i}=\frac{e^{i}}{\sum _{j}e^{j}} Si=jejei
接下来对公式进行细分说明:

(1)非线性变换之前计算: z ( l ) = W ( l ) a ( l − 1 ) + b ( l ) z^{(l)}=W^{(l)}a^{(l-1)}+b^{(l)} z(l)=W(l)a(l1)+b(l)
(2)经过非线性变换,临时变量: t = e Z l t=e^{Z^{l}} t=eZl
(3)归一化: a l = t i ∑ j = 1 n t j a^{l}=\frac{t_{i}}{\sum_{j=1}^{n}t_{j}} al=j=1ntjti
(4) a l a^{l} al表示的就是第几个类别的概率值,这些概率值和为1.

举例如下:
在这里插入图片描述
softmax直白来说就是将原来输出是3,1,-3通过softmax函数一作用,就映射成为(0,1)的值,而这些值的累和为1(满足概率的性质),那么我们就可以将它理解成概率,在最后选取输出结点的时候,我们就可以选取概率最大(也就是值对应最大的)结点,作为我们的预测目标。

3.6 MaxOut函数

Maxout模型实际上也是一种新型的激活函数,我们要先知道什么是maxout。我们假设网络某一层的输入特征向量为:X=(x1,x2,……xd),也就是我们输入是d个神经元。Maxout隐藏层每个神经元的计算公式如下:
h i ( x ) = m a x ( Z i j ) j ∈ [ 1 , k ] h_{i}(x)=\underset{j\in \left [ 1,k \right ]}{max (Z_{ij})} hi(x)=j[1,k]max(Zij)

上面的公式就是maxout隐藏层神经元i的计算公式。其中,k就是maxout层所需要的参数了,由我们人为设定大小。就像dropout一样,也有自己的参数p(每个神经元dropout概率),maxout的参数是k。公式中Z的计算公式为:
z i j = x T W . . . i j + b i j z_{ij}=x^{T}W_{...ij} + b_{ij} zij=xTW...ij+bij
权重w是一个大小为(d,m,k)三维矩阵,b是一个大小为(m,k)的二维矩阵,这两个就是我们需要学习的参数。如果我们设定参数k=1,那么这个时候,网络就类似于以前我们所学普通的MLP网络。

我们可以这么理解,本来传统的MLP算法在第i层到第i+1层,参数只有一组,然而现在我们不怎么干了,我们在这一层同时训练n组参数,然后选择激活值最大的作为下一层神经元的激活值。下面还是用一个例子进行讲解,比较容易搞懂。

为了简单起见,假设我们网络第i层有2个神经元x1、x2,第i+1层的神经元个数为1个,如下图所示:
在这里插入图片描述
(1)以前MLP的方法。我们要计算第i+1层,那个神经元的激活值的时候,传统的MLP计算公式就是:
z = W ∗ X + b z=W*X + b z=WX+b
o u t = f ( z ) out=f(z) out=f(z)
其中f就是我们所谓的激活函数,比如Sigmod、Relu、Tanh等。

(2)Maxout 的方法。如果我们设置maxout的参数k=5,maxout层就如下所示:
在这里插入图片描述相当于在每个输出神经元前面又多了一层。这一层有5个神经元,此时maxout网络的输出计算公式为:
z1=w1*x+b1

z2=w2*x+b2

z3=w3*x+b3

z4=w4*x+b4

z5=w5*x+b5

out=max(z1,z2,z3,z4,z5)

也就是说第(i+1)层的激活值计算了5次,可我们明明只需要1个激活值,那么我们该怎么办?其实上面的叙述中已经给出了答案,取这5者的最大值来作为最终的结果。
总结一下,maxout明显增加了网络的计算量,使得应用maxout的层的参数个数成k倍增加,原本只需要1组就可以,采用maxout之后就需要k倍了。

再叙述一个稍微复杂点的应用maxout的网络,网络图如下:
在这里插入图片描述对上图做个说明,第i层有3个节点,红点表示,而第(i+1)层有4个结点,用彩色点表示,此时在第(i+1)层采用maxout(k=3)。我们看到第(i+1)层的每个节点的激活值都有3个值,3次计算的最大值才是对应点的最终激活值。我举这个例子主要是为了说明,决定结点的激活值的时候并不是以层为单位,仍然以节点为单位。

优点:
与常规激活函数不同的是,它是一个可学习的分段线性函数.然而任何一个凸函数,都可以由线性分段函数进行逼近近似。其实我们可以把以前所学到的激活函数:ReLU、abs激活函数,看成是分成两段的线性函数,如下示意图所示:
在这里插入图片描述实验结果表明Maxout与Dropout组合使用可以发挥比较好的效果。
那么,前边的两种ReLU便是两种Maxout,函数图像为两条直线的拼接。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值