非线性激活函数

目录

理论介绍

常见的激活函数

A. sigmoid函数

B. tanh

C.ReLu

Leaky Relu 函数

Parametric ReLU (PReLU)

Exponential Linear Unit (ELU)

实验结果及分析


理论介绍

    在神经网络的计算中,无非就是矩阵相乘,输入的是线性,不论输出层有多少,相当于n个矩阵相乘,和一层相乘所获取的信息差距不大,那我们无非是要引入非线性因素,使得神经网络可以任意逼近任何非线性函数,这样神经网络就可以应用到众多的非线性模型中,增加了神经网络模型泛化的特性。

    早期研究神经网络主要采用sigmoid函数或者tanh函数,输出有界,很容易充当下一层的输入。 近些年Relu函数及其改进型(如Leaky-ReLU、P-ReLU、ELU等),由于计算简单、效果好所以在多层神经网络中应用比较多。

常见的激活函数

# 下面内容都要有此片段  
import torch  
import torch.nn.functional as F  
import matplotlib.pyplot as plt  
import numpy as np  
x= torch.linspace(-10,10,60)  

A. sigmoid函数

gif.latex?a%3D%5Cfrac%7B1%7D%7B1+e%5E%7B-z%7D%7D

导数 :gif.latex?a%5E%5Cprime%20%3Da%281%20-%20a%29

在sigmoid函数中我们可以看到,其输出是在(0,1)这个开区间,它能够把输入的连续实值变换为0和1之间的输出,如果是非常大的负数,那么输出就是0;如果是非常大的正数输出就是1,起到了抑制的作用。

ax = plt.gca()  
ax.spines['right'].set_color('none')  
ax.spines['top'].set_color('none')  
ax.xaxis.set_ticks_position('bottom')  
ax.spines['bottom'].set_position(('data', 0))  
ax.yaxis.set_ticks_position('left')  
ax.spines['left'].set_position(('data', 0))  
plt.ylim((0, 1))  
sigmod=torch.sigmoid(x)  
plt.plot(x.numpy(),sigmod.numpy())  
plt.show()  

7 sigmod

但是sigmod由于需要进行指数运算(相比relu这个对于计算机来说是比较慢),再加上函数输出不是以0为中心的(这样会使权重更新效率降低),当输入稍微远离了坐标原点,函数的梯度就变得很小了(几乎为零)。在神经网络反向传播的过程中不利于权重的优化,这个问题叫做梯度饱和,也可以叫梯度弥散。这些不足,所以现在使用到sigmod基本很少了,基本上只有在做二元分类(0,1)时的输出层才会使用。

B. tanh

gif.latex?a%3D%5Cfrac%7Be%5Ez-e%5E%7B-z%7D%7D%7Be%5Ez+e%5E%7B-z%7D%7D

 导数:gif.latex?a%5E%5Cprime%20%3D1%20-%20a%5E2

    tanh是双曲正切函数,输出区间是在(-1,1)之间,而且整个函数是以0为中心的。

ax = plt.gca()  
ax.spines['right'].set_color('none')  
ax.spines['top'].set_color('none') 
ax.xaxis.set_ticks_position('bottom')  
ax.spines['bottom'].set_position(('data', 0))  
ax.yaxis.set_ticks_position('left')  
ax.spines['left'].set_position(('data', 0))  
plt.ylim((-1, 1))  
tanh=torch.tanh(x)  
plt.plot(x.numpy(),tanh.numpy())  
plt.show()  

7 sigmod

与sigmoid函数类似,当输入稍微远离了坐标原点,梯度还是会很小,但是好在tanh是以0为中心点,如果使用tanh作为激活函数,还能起到归一化(均值为0)的效果。

一般二分类问题中,隐藏层用tanh函数,输出层用sigmod函数,但是随着Relu的出现所有的隐藏层基本上都使用relu来作为激活函数了。

C.ReLu

Relu修正线性单元

a= max(0,z)

导数大于0时1,小于0时0。

也就是说: z>0时,梯度始终为1,从而提高神经网络基于梯度算法的运算速度。然而当 z<0时,梯度一直为0。 ReLU函数只有线性关系(只需要判断输入是否大于0)不管是前向传播还是反向传播,都比sigmod和tanh要快很多,当输入是负数的时候,ReLU是完全不被激活的,这就表明一旦输入到了负数,ReLU就会死掉。但是到了反向传播过程中,输入负数,梯度就会完全到0,这个和sigmod函数、tanh函数有一样的问题。 但是实际的运用中,该缺陷的影响不是很大。

ax = plt.gca()  
ax.spines['right'].set_color('none')  
ax.spines['top'].set_color('none')  
ax.xaxis.set_ticks_position('bottom')  
ax.spines['bottom'].set_position(('data', 0))  
ax.yaxis.set_ticks_position('left')  
ax.spines['left'].set_position(('data', 0))  
plt.ylim((-3, 10))  
relu=F.relu(x)  
plt.plot(x.numpy(),relu.numpy())  
plt.show()  

7 Relu

D.ReLU的变种

Leaky Relu 函数

为了解决relu函数z<0时的问题出现了 Leaky ReLU函数,该函数保证在z<0的时候,梯度仍然不为0。 ReLU的前半段设为αz而非0,通常

α=0.01,a=max(αz,z)

ax = plt.gca()  
ax.spines['right'].set_color('none')  
ax.spines['top'].set_color('none')  
ax.xaxis.set_ticks_position('bottom')  
ax.spines['bottom'].set_position(('data', 0))  
ax.yaxis.set_ticks_position('left')  
ax.spines['left'].set_position(('data', 0))  
plt.ylim((-3, 10))  
l_relu=F.leaky_relu(x,0.1) # 这里的0.1是为了方便展示,理论上应为0.01甚至更小的值  
plt.plot(x.numpy(),l_relu.numpy())  
plt.show()  

7 Leaky Relu

Parametric ReLU (PReLU)

PReLU是一种引入可学习参数的ReLU变种,它允许负数区域的斜率成为可学习的参数。这使得神经网络能够根据数据自适应地学习激活函数的形状。公式如下:

f(x) = max(ax, x)

p_relu = F.prelu(x, torch.tensor(0.25)) # 使用PReLU激活函数,参数为0.25  
plt.figure()  
ax = plt.gca()  
ax.spines['right'].set_color('none')  
ax.spines['top'].set_color('none')  
ax.xaxis.set_ticks_position('bottom')  
ax.spines['bottom'].set_position(('data', 0))  
ax.yaxis.set_ticks_position('left')  
ax.spines['left'].set_position(('data', 0))  
plt.ylim((-3, 10))  
plt.plot(x.numpy(), p_relu.numpy(), label='PReLU')  
plt.legend()  
plt.title('PReLU Activation')  
plt.show()  

8 Parametric Relu

Exponential Linear Unit (ELU)

ELU是在负数区域引入一个指数衰减的激活函数,以解决ReLU在负数区域的问题。它提供了一个平滑的曲线,并具有负饱和度,可以减少梯度消失的问题。公式如下:

f(x) = x                         if x > 0

alpha * (exp(x) - 1)        if x <= 0

其中,alpha是一个正数,控制ELU在负数区域的斜率。

9 Exponential Linear Unit

在实践中,ReLU和其变种的使用情况会因任务和数据的不同而有所变化。然而,目前来看,ReLU仍然是最常用的激活函数。

ReLU的主要优势是计算简单且有效,能够在许多深度学习任务中提供良好的性能。它具有线性增长的特性,在正数区域上不会饱和,可以避免梯度消失问题,并且在实践中被广泛使用。

在ReLU的变种中,Leaky ReLU是最常见的选择之一。它通过引入一个小的斜率来解决ReLU在负数区域的问题,提供了更好的负数响应。Leaky ReLU在某些情况下可能比传统的ReLU效果更好。PReLU和ELU等变种相对来说使用较少,但在某些特定任务或特定数据集上可能表现出更好的性能。PReLU通过引入可学习的参数,使激活函数能够自适应地调整形状,因此在一些复杂任务中可能更有优势。ELU通过引入指数衰减的负数响应,提供了平滑的非线性特性,对于一些需要更强鲁棒性和更低误差的任务可能更合适。

实验结果及分析

    当涉及到选择适当的激活函数时,我们有多个选项可供选择。ReLU及其变种、Sigmoid和Tanh是常见的激活函数,各自具有不同的特点和适用情况。以下是对它们的总结:

ReLU及其变种(Leaky ReLU、PReLU、ELU等):

  1. ReLU(Rectified Linear Unit)是最常用的激活函数之一。它在正数区域上表现良好,不会引起梯度消失问题,并且计算简单高效。然而,ReLU在负数区域会完全被抑制,可能导致神经元“死亡”问题。
  2. Leaky ReLU引入了一个小的斜率来解决ReLU的负数区域问题,以提供更好的负数响应。
  3. PReLU通过引入可学习的参数,使激活函数能够自适应地调整形状,适用于一些复杂任务。
  4. ELU在负数区域引入了指数衰减,提供平滑的非线性特性,并具有负饱和度,对于一些需要更强鲁棒性和更低误差的任务可能更合适。

Sigmoid函数:

  1. Sigmoid函数将输入值映射到介于0和1之间的范围,常用于二分类问题的输出层。它的平滑曲线使其在处理概率和概率分布时具有一定优势。
  2. 然而,Sigmoid函数存在梯度饱和的问题,导致在深度神经网络中容易发生梯度消失和梯度爆炸的现象。

Tanh函数:

  1. Tanh函数将输入值映射到介于-1和1之间的范围,是一种常见的激活函数。它相对于Sigmoid函数具有更大的动态范围,并且在零点附近对称,对于处理中心化数据更适用。
  2. 与Sigmoid函数类似,Tanh函数也存在梯度饱和的问题。
  3. 在实际应用中,我们需要根据任务和数据的特点来选择适当的激活函数。一般而言,ReLU及其变种在大多数情况下表现良好,尤其在深度神经网络中。Sigmoid函数和Tanh函数适用于特定的场景,如二分类问题或处理中心化数据。然而,我们也可以尝试不同的激活函数来优化神经网络的性能和收敛速度,因为最佳选择因任务而异。
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏天是冰红茶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值