掌握激活函数(一):深度学习的成功之源

文章目录

  • 引言
  • 基本概念
  • 常用激活函数举例
    • Sigmoid激活函数
      • 公式
      • Sigmoid函数的数学特性
      • 示例
        • 基于NumPy和PyTorch实现Sigmoid函数
        • 将Sigmoid函数应用于二分类任务
      • Sigmoid激活函数的局限性举例
    • ReLU激活函数
      • 公式
      • ReLU函数的数学特性
      • ReLU函数的特点
      • 示例
        • 基于NumPy和PyTorch实现ReLU函数
        • 搭建基于ReLU函数的卷积神经网络(CNN)
  • 结束语

引言

深度学习作为人工智能领域的一颗璀璨之星,其背后的神经网络模型是无数智能应用的基石。而在这些神经网络中,激活函数担任了不可或缺的角色。它们如同魔法一般,为神经网络带来了非线性特性,使其能够学习和模拟复杂的现实世界模式。没有激活函数,深度学习模型充其量只是一堆线性回归的堆叠。本文将带您逐渐深入掌握激活函数的原理、类型以及在深度学习中的应用,让您真正领略这背后的“魔法”之源。


基本概念

激活函数,也称为非线性激活函数,是神经网络中每一层的输出函数。在神经网络的构建中,激活函数发挥着至关重要的作用。它不仅赋予了神经元非线性特性,使得神经网络能够学习和模拟复杂的、非线性的数据模式,更是神经网络表达能力的核心驱动力。没有激活函数,神经网络将仅能执行线性的计算,极大地限制了其应用范围和表达能力。


常用激活函数举例

Sigmoid激活函数

Sigmoid函数是一种非常常用的激活函数,它可以将任何输入值映射到0到1之间。这个特性使得Sigmoid函数在二分类问题中特别受欢迎,因为输出可以被解释为属于某一类的概率

公式

Sigmoid函数的数学特性

特性描述
非线性Sigmoid函数可以将输入映射到0-1之间的任意值,允许神经网络学习和模拟复杂的非线性模式。
饱和性当输入值远离0时,Sigmoid函数的输出会非常接近0或1,这种现象称为饱和。
可微分性Sigmoid函数是连续且可微的,这意味着基于梯度的优化算法(如反向传播)能够有效地用于训练神经网络。

示例

基于NumPy和PyTorch实现Sigmoid函数
# 基于NumPy实现Sigmoid函数
import numpy as npdef sigmoid(x):# 将输入值转换为浮点数x = np.float32(x)# 计算sigmoid值return 1 / (1 + np.exp(-x))# 基于PyTorch实现Sigmoid函数(使用PyTorch的内置函数torch.sigmoid())
import torch  # 创建一个张量  
x = torch.tensor([-1.0, 0.0, 1.0])  # 应用sigmoid函数  
y = torch.sigmoid(x)  print(y)# 基于PyTorch实现Sigmoid函数(手动实现)
import torch  def sigmoid(x):  return 1 / (1 + torch.exp(-x))# 创建一个张量  
x = torch.tensor([-1.0, 0.0, 1.0])# 应用sigmoid函数  
y = sigmoid(x)  
将Sigmoid函数应用于二分类任务
import torch  
import torch.nn as nn  
import torchvision.transforms as transforms  
import torchvision.datasets as datasets  # 定义超参数  
input_size = 784       # 输入图像的维度(28*28)  
hidden_size = 100       # 隐藏层的大小  
num_epochs = 10           # 训练周期数  
batch_size = 100           # 批处理大小  
learning_rate = 0.001       # 学习率  # 加载数据集并进行预处理  
transform = ... # 待定
train_dataset = ... # 待定
test_dataset = ... # 待定
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True)  
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=False)  # 定义模型结构  
class NeuralNetwork(nn.Module):  def __init__(self, input_size, hidden_size):  super(NeuralNetwork, self).__init__()  self.fc1 = nn.Linear(input_size, hidden_size)   self.relu = nn.ReLU()  self.fc2 = nn.Linear(hidden_size, 1)    self.sigmoid = nn.Sigmoid()  # 添加Sigmoid激活函数  def forward(self, x):  out = self.fc1(x)  out = self.relu(out)  out = self.fc2(out)  out = self.sigmoid(out)  # 在输出层使用Sigmoid激活函数  return out  # 实例化模型、损失函数和优化器  
model = NeuralNetwork(input_size, hidden_size)  
criterion = ... # 待定
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)  # 使用Adam优化器  # 训练模型  
for epoch in range(num_epochs):  for i, (images, labels) in enumerate(train_loader):  # 遍历每个批次的数据  # 将图像张量转换为2D张量(矩阵)形式,并作为模型的输入  inputs = images.view(-1, input_size)  labels = labels.long()  # 将标签转换为长整数型张量  # 前向传播,计算输出结果  outputs = model(inputs)  loss = criterion(outputs, labels)  # 计算损失值  # 反向传播,更新权重参数  optimizer.zero_grad()  # 清空梯度缓存,以便计算新的梯度值  loss.backward()  # 计算梯度值并累积在模型参数上  optimizer.step()  # 更新模型参数  

Sigmoid激活函数的局限性举例

Sigmoid函数在深度学习模型中作为激活函数使用,其局限性主要表现在以下几个方面:

  1. 梯度消失问题:当输入值非常大或非常小时,Sigmoid函数的导数趋近于0。在深度神经网络中,误差反向传播时,梯度会逐层乘以激活函数的导数。当层数较深时,梯度的连乘可能导致梯度变得非常小,甚至接近于0,使得参数无法有效更新,这就是所谓的梯度消失问题
  2. 输出非0均值:Sigmoid函数的输出值恒大于0,不是0均值的。这会导致后层的神经元的输入是非0均值的信号,对梯度产生影响,进而影响网络的收敛速度(参考链接)。
  3. 容易饱和:Sigmoid函数在输入值较大或较小时容易进入饱和区,此时函数的输出对输入的变化不敏感,可能导致模型训练困难。

ReLU激活函数

和Sigmoid函数一样,ReLU(Rectified Linear Unit)函数也是非常常用的激活函数。它将负值映射为0,对于正值则直接输出其本身。

公式

ReLU函数的数学特性

特性描述
简单性ReLU函数仅需比较输入值和0的大小来确定输出值,计算效率高。
非线性ReLU函数实际上是非线性的,能够引入非线性因素,增强模型的表达能力。
激活稀疏性当输入值小于0时,ReLU函数的输出为0,只激活输入中的一部分神经元,增强模型的泛化能力和鲁棒性。
缓解梯度消失问题与传统的激活函数(如Sigmoid)相比,ReLU有助于缓解梯度消失问题,因为它的梯度在正区间为1,有助于更好地传播梯度。

ReLU函数的特点

  1. 线性与非线性:ReLU函数在输入值大于0时表现为线性函数,即f(x)=x,这有助于提高计算速度。而在输入值小于或等于0时,ReLU函数表现为非线性,即输出值为0。这种线性与非线性的结合使得ReLU函数在深度学习中具有很好的性能。

  2. 简单高效:ReLU函数的计算过程非常简单,只需要一次比较操作和一次赋值操作,因此计算速度非常快。这使得ReLU函数在训练深度神经网络时非常高效,可以显著加速模型的收敛速度。

  3. 缓解梯度消失问题:与Sigmoid等激活函数相比,ReLU激活函数的梯度在反向传播过程中不会消失,有助于提高训练速度和模型的收敛效果。

  4. 神经元"死亡"问题:与Sigmoid函数类似,ReLU函数也可能导致某些神经元在训练过程中始终处于"死亡"状态(即输出值一直为0),这可能会影响模型的性能。为了解决这个问题,一些变体的ReLU激活函数也被开发出来,如Leaky ReLU和Parametric ReLU等。

示例

基于NumPy和PyTorch实现ReLU函数
# 基于NumPy实现ReLU函数
import numpy as np  def relu(x):  return np.maximum(0, x)# 基于PyTorch实现ReLU函数(使用PyTorch的内置函数F.relu())
import torch.nn.functional as F# 创建一个张量  
x = torch.tensor([-1.0, 0.0, 1.0])  # 应用sigmoid函数  
y = F.relu(x)print(y)
搭建基于ReLU函数的卷积神经网络(CNN)
import torch  
import torch.nn as nn  # 定义一个简单的卷积神经网络  
class SimpleCNN(nn.Module):  def __init__(self):  super(SimpleCNN, self).__init__()  # 第一个卷积层,使用32个3x3的卷积核,输入通道数为1,输出通道数为32,ReLU激活函数  self.conv1 = nn.Conv2d(1, 32, 3, padding=1)  # 第二个卷积层,使用64个3x3的卷积核,输入通道数为32,输出通道数为64,ReLU激活函数  self.conv2 = nn.Conv2d(32, 64, 3, padding=1)  # 全连接层,输入节点数为64*7*7(假设输入图像大小为28x28),输出节点数为10(假设有10个类别)  self.fc = nn.Linear(64 * 7 * 7, 10)  # 输出层,全连接层的输出作为输入,输出节点数为10,使用softmax激活函数  self.out = nn.LogSoftmax(dim=1)  def forward(self, x):  # 通过第一个卷积层和ReLU激活函数  x = self.conv1(x)  x = nn.functional.relu(x)  # 通过第二个卷积层和ReLU激活函数  x = self.conv2(x)  x = nn.functional.relu(x)  # 将卷积层的输出展平,作为全连接层的输入  x = x.view(x.size(0), -1)  # 通过全连接层和softmax激活函数  x = self.fc(x)  x = self.out(x)  return x

在这个示例中:

  • 我们定义了一个名为SimpleCNN的类,继承自nn.Module。这是PyTorch中定义神经网络的标准方式。
  • __init__方法中,我们定义了网络中的各个层。首先有两个卷积层,每个卷积层后都使用了ReLU激活函数。然后是一个全连接层,最后是一个输出层。
  • forward方法中,我们定义了数据在网络中的前向传播过程。数据首先通过两个卷积层和ReLU激活函数,然后被展平以便输入全连接层,最后通过全连接层和输出层。
  • 我们使用了nn.functional模块中的函数来应用ReLU激活函数(nn.functional.relu)和Softmax激活函数(nn.functional.log_softmax)。注意,ReLU激活函数的参数默认为0,因此不需要额外指定。

结束语

  • 亲爱的读者,感谢您花时间阅读我们的博客。我们非常重视您的反馈和意见,因此在这里鼓励您对我们的博客进行评论。
  • 您的建议和看法对我们来说非常重要,这有助于我们更好地了解您的需求,并提供更高质量的内容和服务。
  • 无论您是喜欢我们的博客还是对其有任何疑问或建议,我们都非常期待您的留言。让我们一起互动,共同进步!谢谢您的支持和参与!
  • 我会坚持不懈地创作,并持续优化博文质量,为您提供更好的阅读体验。
  • 谢谢您的阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2659539.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

虚析构和纯虚析构

多态使用时,如果子类中有属性开辟到堆区,那么父类的指针在释放时无法调用到子类的析构代码 解决方式:将父类中的析构代码函数改为虚析构或者纯虚析构 虚析构和纯虚析构共性: 可以解决父类指针释放子类对象 都需要有具体的函数…

vu3-14

第一个需求是在用户登录成功之后,在主页显示用户的真实姓名和性别,这些信息要调用后端API获取数据库里面的信息,第二个需求是点击菜单1,在表单中修改用户信息之后,更新到后端数据库,然后在主页同步更新用户…

软件测试/测试开发丨接口测试学习笔记分享

一、Mock 测试 1、Mock 测试的场景 前后端数据交互第三方系统数据交互硬件设备解耦 2、Mock 测试的价值与意义 不依赖第三方数据节省工作量节省联调 3、Mock 核心要素 匹配规则:mock的接口,改哪些接口,接口哪里的数据模拟响应 4、mock实…

【基础篇】六、自定义类加载器打破双亲委派机制

文章目录 1、ClassLoader抽象类的方法源码2、打破双亲委派机制:自定义类加载器重写loadclass方法3、自定义类加载器默认的父类加载器4、两个自定义类加载器加载相同限定名的类,不会冲突吗?5、一点思考 1、ClassLoader抽象类的方法源码 ClassL…

【Python基础篇】【19.异常处理】(附案例,源码)

异常处理 异常处理常见异常elsefinallyraise获取异常信息sys.exc_info()traceback 处理异常基本原则assert断点调试两种方式Debugger窗口各图标的含义1.Show Execution Point (Alt F10)2.Step Over(F8)3.Step Into (F…

【线性代数】通过矩阵乘法得到的线性方程组和原来的线性方程组同解吗?

一、通过矩阵乘法得到的线性方程组和原来的线性方程组同解吗? 如果你进行的矩阵乘法涉及一个线性方程组 Ax b,并且你乘以一个可逆矩阵 M,且产生新的方程组 M(Ax) Mb,那么这两个系统是等价的;它们具有相同的解集。这…

k8s二进制部署2

部署 Worker Node 组件 //在所有 node 节点上操作 #创建kubernetes工作目录 mkdir -p /opt/kubernetes/{bin,cfg,ssl,logs} #上传 node.zip 到 /opt 目录中,解压 node.zip 压缩包,获得kubelet.sh、proxy.sh cd /opt/ unzip node.zip chmod x kubelet.…

CodeWhisperer——轻松使用一个超级强大的工具

CodeWhisperer 简介 CodeWhisperer是亚⻢逊云科技出品的一款基于机器学习的通用代码生成器,可实时提供代码建议。 CodeWhisperer有以下几个主要用途: 解决编程问题,提供代码建议,学习编程知识等等,并且CodeWhisper…

2022 年全国职业院校技能大赛高职组云计算正式赛卷第二场-容器云

2022 年全国职业院校技能大赛高职组云计算赛项试卷 云计算赛项第二场-容器云 目录 2022 年全国职业院校技能大赛高职组云计算赛项试卷 【赛程名称】云计算赛项第二场-容器云 【任务 1】容器云平台搭建[5 分] 【任务 2】容器云应用部署: Docker Compose 编排部署[7.0…

【ZYNQ】教你用 Vivado HLS 快速设计一个 IP

Xilinx 推出的 Vivado HLS 工具可以直接使用 C、C或 System C 来对 Xilinx 系列的 FPGA 进行编程,从而提高抽象的层级,大大减少了使用传统 RTL 描述进行 FPGA 开发所需的时间。 Vivado HLS 的功能简单地来说就是把 C、C 或 SystemC 的设计转换成 RTL 实…

Python自动化测试:选择最佳的自动化测试框架

在开始学习python自动化测试之前,先了解目前市场上的自动化测试框架有哪些? 随着技术的不断迭代更新,优胜劣汰也同样发展下来。从一开始工具型自动化,到现在的框架型;从一开始的能用,到现在的不仅能用&…

element el-table实现可进行横向拖拽滚动

【问题】表格横向太长,表格横向滚动条位于最底部,需将页面滚动至最底部才可左右拖动表格,用户体验感不好 【需求】基于elment的el-table组件生成的表格,使其可以横向拖拽滚动 【实现】灵感来源于这篇文章【Vue】表格可拖拽滚动&am…

每周一算法:区间覆盖

问题描述 给定 N N N个闭区间 [ a i , b i ] [a_i,b_i] [ai​,bi​],以及一个线段区间 [ s , t ] [s,t] [s,t],请你选择尽量少的区间,将指定线段区间完全覆盖。 输出最少区间数,如果无法完全覆盖则输出 − 1 -1 −1。 输入格式…

androj环境搭建_AS安装及运行源码

1、 jdk安装 安卓项目也是java开发的,运行在虚拟机上,安装jdk及运行的时候,就会自动生成虚拟机, jdk前面已经讲过,这里不在讲解 2、下载安装androj studio https://developer.android.google.cn/studio?hlzh-cn 下…

mysql原理---InnoDB统计数据是如何收集的

以下聚焦于 InnoDB 存储引擎的统计数据收集策略。 1.两种不同的统计数据存储方式 InnoDB 提供了两种存储统计数据的方式: (1). 永久性的统计数据 这种统计数据存储在磁盘上,也就是服务器重启之后这些统计数据还在。 (2). 非永久性的统计数据 这种统计数…

Java生态系统的进化:从JDK 1.0到今天

目录 前言 JDK 1.0:开启Java时代 JDK 1.1:Swing和内部类 JDK 1.2:Collections框架和JIT编译器 JDK 1.5:引入泛型和枚举 JDK 1.8:Lambda表达式和流 JDK 11以后:模块化和新特性 未来展望 总结 作者简…

Smartbi获工信部旗下赛迪网“2023行业信息技术应用创新产品”奖

近日,由工信部旗下的赛迪网、《数字经济》杂志共同主办的2023行业信息技术应用创新大会上,“信息技术应用创新成果名单”重磅揭晓,思迈特软件凭借“Smartbi 自然语言分析引擎”斩获“2023行业信息技术应用创新产品”大奖。 据了解&#xff0c…

JavaWeb——监听器Listener 过滤器Filter——韩顺平学习笔记

文章目录 JavaWeb 三大组件之监听器 ListenerListenerJavaWeb 的监听器ServletContextListener 监听器ServletContextAttributeListener 监听器其它监听器-使用较少HttpSessionListener 监听器HttpSessionAttributeListener 监听器ServletRequestListener 监听器ServletRequest…

YOLOv5算法进阶改进(8)— 引入GSConv + Slim Neck相结合的方式降低模型复杂性

前言:Hello大家好,我是小哥谈。在文章中,作者提出了一种新方法 GSConv 来减轻模型的复杂度并保持准确性。GSConv可以更好地平衡模型的准确性和速度。并且,提供了一种设计范式Slim Neck,以实现检测器更高的计算成本效益。实验过程中,与原始网络相比,改进方法获得了最优秀…

软件测试/测试开发丨Selenium的常用元素定位方法

Selenium是一个流行的开源框架,目前在 Web 自动化方面运用最为广泛的一个开源、无浏览器要求、可支持多语言、设计测试用例非常灵活的自动化测试框架。支持多种编程语言,并且能够模拟用户操作,例如点击、输入、提交等等。 在Selenium中&…