当前位置: 首页 > article >正文

深度学习中常见的激活函数详解

文章目录

  • 激活函数概述
  • 常见的激活函数详解
    • Sigmoid激活函数
    • Tanh激活函数
    • ReLU激活函数
    • Leaky ReLU激活函数
    • ELU激活函数
    • Swish激活函数
  • 激活函数的选择
  • 总结
  • 参考文献

在深度学习领域的神经网络中,激活函数解锁了模型对复杂数据模式的捕捉能力。它们在神经元中发挥着至关重要的作用,将输入信号转换为输出信号,赋予网络非线性特性,使其能够学习和模拟各种复杂的函数关系。接下来本文将带你探索几种常见的激活函数,从公式、图例到PyTorch代码示例,以及它们的优缺点和使用场景等方面进行激活函数的介绍。

激活函数概述

激活函数是神经网络中不可或缺的组成部分。在神经元中,输入的信号经过一系列加权求和后,会作用于一个激活函数。这个函数决定了是否传递信号以及要发射给下一个神经元的内容。简单来说,激活函数就像是一个“开关”,控制着神经元的激活状态。

激活函数的主要作用是增加神经网络模型的非线性。如果没有激活函数,无论神经网络有多少层,其本质上仍然是一个线性模型,只能学习线性可分的数据。而激活函数的引入,使得神经网络可以任意逼近任何非线性函数,从而应用到众多的非线性模型中,如图像识别、自然语言处理等复杂任务。

常见的激活函数详解

Sigmoid激活函数

Sigmoid,这个名字来源于其函数图像的形状,呈现出一个"S"型曲线。

公式

f ( x ) = 1 1 + e − x f(x)=\frac{1}{1+e^{-x}} f(x)=1+ex1

图例

sigmoid

从图中可以看出,Sigmoid函数将输入映射到(0,1)区间内,随着输入值的增大,输出值逐渐接近1;随着输入值的减小,输出值逐渐接近0。

代码使用示例


import torch
import torch.nn as nn

# 创建Sigmoid激活函数对象
sigmoid = nn.Sigmoid()

# 生成一个随机输入张量
x = torch.randn(3)

# 应用Sigmoid激活函数
output = sigmoid(x)

print(output)
# 输出:tensor([0.6402, 0.5647, 0.4793])

优点

  • 平滑、易于求导:Sigmoid函数是一个平滑的曲线,其导数容易计算,这使得在反向传播过程中可以方便地求解梯度。
  • 输出范围有限:输出值被限制在(0,1)区间内,这使得模型的输出具有一定的稳定性,可以用作输出层,尤其是在二分类问题中。

缺点

  • 计算量大:Sigmoid函数含有幂运算和除法,计算相对复杂,这在大规模数据处理时可能会导致计算效率太低。
  • 梯度消失问题:在反向传播过程中,当输入的绝对值较大时,Sigmoid函数的导数会非常接近于0,这会导致梯度值变得非常小,从而使得权重更新缓慢,甚至停止更新,无法完成深层网络的训练。
  • 非零中心化:Sigmoid函数的输出值恒大于0,是非零中心化的。这会导致其后一层的神经元的输入发生偏置偏移,进一步使得梯度下降的收敛速度变慢。

使用场景

Sigmoid激活函数常用于二分类问题的输出层。例如,在垃圾邮件检测任务中,我们可以使用Sigmoid函数将模型的输出映射到(0,1)区间内,表示邮件为垃圾邮件的概率。

Tanh激活函数

Tanh,即双曲正切函数,其名称来源于数学中的双曲函数。

公式

f ( x ) = t a n h ( x ) = e x − e − x e x + e − x f(x)=tanh(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}} f(x)=tanh(x)=ex+exexex

图例

tanh

Tanh函数的图像呈现出双曲正切曲线的形状,输出范围为(-1,1)。

代码使用示例

import torch
import torch.nn as nn

# 创建Tanh激活函数对象
tanh = nn.Tanh()

# 生成一个随机输入张量
x = torch.randn(3)

# 应用Tanh激活函数
output = tanh(x)

print(output)
# 输出:tensor([ 0.9946,  0.1262, -0.3188])

优点

  • 零中心化:Tanh函数的输出范围为(-1,1),是零中心化的。这意味着其后一层的神经元的输入不会发生偏置位移,从而使得梯度下降的收敛速度更快,比Sigmoid函数收敛速度快。

缺点

  • 梯度消失问题:与Sigmoid函数类似,Tanh函数也存在梯度消失的问题。当输入的绝对值较大时,Tanh函数的导数会非常接近于0,这会导致梯度值变得非常小,从而使得权重更新缓慢,甚至停止更新,无法完成深层网络的训练。

使用场景

Tanh激活函数可用于隐藏层,但在深层网络中效果不佳。例如,在手写数字识别任务中,我们可以使用Tanh函数作为隐藏层的激活函数,以加速模型的收敛速度。

ReLU激活函数

ReLU,即Rectified Linear Unit,中文名为修正线性单元。

公式

f ( x ) = m a x ( 0 , x ) f(x)=max(0,x) f(x)=max(0,x)

图例

relu

ReLU函数的图像非常的简介,当输入值小于0时,输出为0;当输入值大于0时,输出等于输入值。

代码使用示例

import torch
import torch.nn as nn

# 创建ReLU激活函数对象
relu = nn.ReLU()

# 生成一个随机输入张量
x = torch.randn(3)

# 应用ReLU激活函数
output = relu(x)

print(output)
# 输出:tensor([0.2305, 0.0000, 0.0000])

优点

  • 无梯度消失问题:ReLU函数在 x > 0 x>0 x>0时为线性结构,其导数恒为1,因此不会出现梯度消失的问题。这使得ReLU函数在深层网络中表现出色,能够有效地加速模型的训练过程。
  • 稀疏激活:当输入值小于0时,ReLU函数的输出为0,这会导致一部分神经元在训练过程中“失活”。这种稀疏激活的特性可以减少参数间的相互依赖,缓解过拟合问题,提高模型的泛化能力。
  • 计算简单:ReLU函数的计算非常简单,只需要进行一次比较操作和一次取最大值操作,计算量小,速度快。

缺点

  • 神经元坏死问题:当输入值小于0时,ReLU函数的输出恒为0,这会导致这部分神经元在后续的训练过程中可能永远不会被激活,从而出现“神经元坏死”的问题。一旦神经元“死亡”,它将不再对模型的输出产生任何影响,这会降低模型的性能。

使用场景

ReLU激活函数是隐藏层的常用选择。例如,在图像分类任务中,我们可以使用ReLU函数作为隐藏层的激活函数,以加速模型的训练过程并提高模型的性能。

Leaky ReLU激活函数

Leaky ReLU,即泄露修正线性单元。

公式

f ( x ) = m a x ( α x , x ) f(x)=max(αx,x) f(x)=max(αx,x),其中 α α α是一个较小的常数,如0.01.

图例

leaky_relu

Leaky ReLU函数的图像与ReLU函数类似,但在负半轴上有一个较小的斜率 α α α,这使得Leaky ReLU函数在负半轴上也有非零的输出。

代码使用示例

import torch
import torch.nn as nn

# 创建Leaky ReLU激活函数对象,设置α为0.01
leaky_relu = nn.LeakyReLU(0.01)

# 生成一个随机输入张量
x = torch.randn(3)

# 应用Leaky ReLU激活函数
output = leaky_relu(x)

print(output)
# 输出:tensor([-0.0073,  0.0941,  1.3643])

优点

  • 解决神经元坏死问题:Leaky ReLU函数在负半轴上有一个较小的斜率 α α α,这使得即使输入值小于0,神经元也有非零的输出。因此,Leaky ReLU函数可以有效地缓解ReLU函数的“神经元坏死“问题,使得神经元在训练过程中始终保持活跃状态。

缺点

  • 超参数调参:Leaky ReLU函数引入了一个超参数 α α α,需要进行调参。不同的 α α α值可能会对模型的性能产生不同的影响,因此需要根据具体任务和数据进行多次实验,以找到最优的 α α α值。

使用场景

Leaky ReLU激活函数可用于隐藏层,尤其适用于一些ReLU容易出现“神经元坏死”的场景。例如,在语音识别任务中,我们可以使用Leaky ReLU函数作为隐藏层的激活函数,以避免神经元“死亡”并提高模型的性能。

ELU激活函数

ELU,即Exponential Linear Unit,中文名为指数线性单元。

公式

f ( x ) = x , x > 0 α ( e x − 1 ) , x ≤ 0 f(x)=\begin{align} x, x>0\\ α(e^x-1),x\leq0 \end{align} f(x)=x,x>0α(ex1),x0,其中 α α α是一个超参数。

图例

elu

ELU函数的图像在 x > 0 x>0 x>0时为线性结构,输出等于输入值;在 x ≤ 0 x\leq0 x0时为指数函数结构,输出为 α ( e x − 1 ) α(e^x-1) α(ex1)。这使得ELU函数在负半轴上有一个平滑的过渡。

代码使用示例

import torch
import torch.nn as nn

# 创建ELU激活函数对象
elu = nn.ELU()

# 生成一个随机输入张量
x = torch.randn(3)

# 应用ELU激活函数
output = elu(x)

print(output)
# 输出:tensor([ 0.4182,  0.4470, -0.5287])

优点

  • 缓解神经元坏死问题:ELU函数在负半轴上有一个非零的输出,这使得神经元在训练过程中不会“死亡”,从而环节了ReLU函数的“神经元坏死”问题。
  • 增强非线性表达能力:ELU函数在负半轴上引入了指数函数结构,这使得网络的非线性表达能力更强,能够更好地学习复杂的函数关系。

缺点

  • 计算复杂度高:ELU函数涉及到指数运算,计算相对复杂,这在大规模数据处理时可能会导致计算效率较低。

使用场景

ELU激活函数可用于隐藏层,尤其适用于一些需要在负半轴也有较好表达能力的场景。例如,在自然语言处理任务中,我们可以使用ELU函数作为隐藏层的激活函数,以增强模型的非线性表达能力并提高模型的性能。

Swish激活函数

Swish,这个名字来源于其函数的自门控特性,就像一个”开关“一样。

公式

f ( x ) = x ⋅ σ ( β x ) f(x)=x·\sigma(\beta x) f(x)=xσ(βx),其中 σ \sigma σ是sigmoid函数, β \beta β是一个超参数。

图例

swish

Swish函数的图像呈现出平滑的曲线,具有非线性和自门控特性。当输入值较小时,Swish函数的输出接近于0;当输入值较大时,Swish函数的输出接近于与输入值。

代码使用示例

import torch
import torch.nn as nn

# 定义Swish激活函数类
class Swish(nn.Module):
    def __init__(self, beta=1.0):
        super(Swish, self).__init__()
        self.beta = beta

    def forward(self, x):
        return x * torch.sigmoid(self.beta * x)

# 创建Swish激活函数对象,设置β为1.0
swish = Swish()

# 生成一个随机输入张量
x = torch.randn(3)

# 应用Swish激活函数
output = swish(x)

print(output)
# 输出:tensor([ 1.2576,  0.4483, -0.0575])

优点

  • 收敛性能好:Swish函数在深层网络中表现优于ReLU,具有更好的收敛性能。这使得Swish函数能够更快地训练深层网络,提高模型的训练效率。
  • 分类准确率高:Swish函数在分类任务中表现出色,能够提高模型的分类准确率。这使得Swish函数在图像分类、自然语言处理等任务中具有广泛的应用前景。

缺点

  • 计算复杂度高:Swish函数涉及到sigmoid函数的计算,计算相对复杂,这在大规模数据处理时可能会导致计算效率较低。

使用场景

Swish激活函数可用于深层网络的隐藏层。例如,在深层残差网络(ResNet)中,我们可以使用Swish函数作为隐藏层的激活函数,以提高模型的收敛性能和分类准确率。

激活函数的选择

在实际应用中,选择合适的激活函数对于构建高效深度学习模型至关重要。以下是一些激活函数的选择指南:

  • 隐藏层:一般来说,ReLU及其变体(如Leaky ReLU,ELU等)是隐藏层的常用选择。ReLU函数计算简单、、收敛速度块,但容易出现“神经元坏死”问题;Leaky ReLU函数可以解决ReLU函数的”神经元坏死“问题,但需要调参;ELU函数在负半轴上具有较好的表达能力,但计算复杂度较高。对于深层网络,Swish函数是一个不错的选择,它具有更好的收敛性能和分类准确率。
  • 输出层:输出层的激活函数选择取决于具体的任务类型。对于二分类问题,Sigmoid函数是一个不错的,它可以将模型的输出映射到(0,1)区间内,表示正类的概率;对于多分类问题,Softmax函数是常用的选择,它可以将模型的输出映射到一个概率分布上,表示每个类比的概率。
  • 结合Batch Normalization使用:Batch Normalization是一种常用的归一化技术,它可以加速模型的收敛速度并提高模型的性能。在使用激活函数时,建议结合Batch Normalization一起使用,以进一步提升模型的效果。例如,在使用ReLU函数时,可以在其前面添加Batch Normalization层,以缓解ReLU函数的“神经元坏死”问题并加速模型的收敛速度。

总结

激活函数在深度学习中扮演者至关重要角色,它们赋予了神经网络非线性特性,使其能够学习和模拟各种复杂的函数关系。本文详细介绍了几种常见的激活函数,包括Sigmoid、Tanh、ReLU、Leaky ReLU、ELU和Swish。通过对比它们的名称、公式、图例,PyTorch代码示例、优缺点以及使用场景,我们可以更好的理解它们的特点和适用范围。在实际应用中,我们需要根据具体任务和数据分布来选择合适的激活函数,并结合Batch Normalization等技术,构建高效、准确的深度学习网络模型。

希望本文能够对你有所帮助,如果你对激活函数还有其他疑问或间接,欢迎留言讨论。3

参考文献

  1. https://proceedings.mlr.press/v15/glorot11a/glorot11a.pdf

http://www.kler.cn/a/501172.html

相关文章:

  • 多模态论文笔记——CLIP
  • 贪心算法笔记
  • 六十九:基于openssl实战验证RSA
  • ansible 检查目录大小
  • VScode python 远程调试
  • 【opencv】第7章 图像变换
  • html使用css外部类选择器
  • Elasticsearch:使用 Playground 与你的 PDF 聊天
  • 使用正则表达式读取文本数据【Python】
  • 【记录基于Python tkinter的音乐播放器的实现过程】
  • NS3学习——fifth基础上运行tcpVegas算法(附完整源码)
  • Qt天气预报系统获取天气数据
  • STM32: 输入捕获基本结构
  • 阿里云-Centos9-安装Docker-配置镜像拉取加速地址-开机自启
  • 【深度学习】Pytorch:加载自定义数据集
  • java导出pdf文件
  • idea系列---【idea中的Debug常用功能】
  • 【漫话机器学习系列】046.弹性网络(Elastic Net)
  • 《拉依达的嵌入式\驱动面试宝典》—计算机网络篇(一)
  • 解读Linux Bridge中的东西流向与南北流向
  • MySQL教程之:常见查询示例
  • TCP 套接字 方法
  • 【Linux】Linux命令
  • wow-agent 学习笔记
  • Bytebase 3.1.2 - 在 SQL 编辑器中为表、列和 PG 的视图注释显示鼠标悬浮提示
  • 了解Node.js