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

深度学习 --- 激活函数

深度学习 — 激活函数


文章目录

  • 深度学习 --- 激活函数
  • 一,基础概念
    • 1.1 线性
    • 1.2 非线性可视化
    • 1.3总结
  • 二,常见的激活函数
    • 2.1 sigmoid
    • 2.2 tanh
    • 2.3 Relu
    • 2.4 LeakyRelu
    • 2.5 softmax


一,基础概念

激活函数的作用是在隐藏层引入非线性,使得神经网络能够学习和表示复杂的函数关系,使网络具备非线性能力,增强其表达能力。

1.1 线性

  • 核心观点:如果神经网络的隐藏层不使用激活函数,整个网络将表现为一个线性模型,无法捕捉数据中的非线性关系。
  • 数学推导
  • 单层网络:输出为线性变换,即

对于单层网络(输入层到输出层),如果没有激活函数,输出a(1)\mathbf{a}^{(1)}a(1) 可以表示为:
a(1)=W(1)x+b(1)\mathbf{a}^{(1)} = \mathbf{W}^{(1)} \mathbf{x} + \mathbf{b}^{(1)}a(1)=W(1)x+b(1)

  • 多层网络
    如果有L层,每层都没有激活函数,则第l层的输出为:a(l)=W(l)a(l−1)+b(l)\mathbf{a}^{(l)} = \mathbf{W}^{(l)} \mathbf{a}^{(l-1)} + \mathbf{b}^{(l)}a(l)=W(l)a(l1)+b(l)
  • 结论
    • 激活函数是引入非线性特性、使神经网络能够处理复杂问题的关键。
    • 没有激活函数的多层神经网络等价于一个单层线性模型。

1.2 非线性可视化

  • 工具:使用 TensorFlow Playground 进行可视化。
  • 可视化目的:通过可视化的方式理解非线性拟合能力。
  • 可视化工具的特点
    • 可以选择不同的数据集、调整训练与测试数据的比例。
    • 可以选择输入特征、调整权重和偏置。
    • 可以观察神经网络的输出,通过颜色显示数据点和预测值。
    • 提供了对网络结构(如隐藏层数量、激活函数等)的调整功能。
  • 可视化结果
    • 激活函数的使用使得神经网络能够捕捉数据中的非线性关系。
    • 不同的激活函数和网络结构对拟合能力有显著影响。
      在这里插入图片描述

1.3总结

  • 线性与非线性的重要性
    • 没有激活函数的神经网络只能处理线性问题,而现实世界中的许多问题是非线性的。
    • 激活函数是神经网络能够处理复杂非线性问题的关键。
  • 可视化工具的作用
    • TensorFlow Playground 提供了一个直观的方式来理解神经网络的非线性拟合能力。
    • 通过调整网络结构和激活函数,可以观察到不同的拟合效果,从而更好地理解神经网络的工作原理。

二,常见的激活函数

激活函数通过引入非线性来增强神经网络的表达能力,对于解决线性模型的局限性至关重要。由于反向传播算法(BP)用于更新网络参数,因此激活函数必须是可微的,也就是说能够求导的。

2.1 sigmoid

Sigmoid激活函数是一种常见的非线性激活函数,特别是在早期神经网络中应用广泛。它将输入映射到0到1之间的值,因此非常适合处理概率问题。

方面内容
公式f(x)=σ(x)=11+e−xf(x) = \sigma(x) = \frac{1}{1 + e^{-x}}f(x)=σ(x)=1+ex1
特征1. 将任意实数输入映射到 (0, 1) 之间,适合处理概率场景。
2. 一般用于二分类输出层。
3. 导数计算方便,可以用自身表达式表示:σ′(x)=σ(x)⋅(1−σ(x))\sigma'(x) = \sigma(x) \cdot (1 - \sigma(x))σ(x)=σ(x)(1σ(x))
优点1. 输出范围在 (0, 1) 之间,适合处理概率问题。
2. 导数计算简单,便于反向传播。
缺点1. 梯度消失:输入非常大或非常小时,梯度接近于0,导致早期层权重更新缓慢,训练速度变慢甚至停滞。
2. 信息丢失:输入值相差很大时,激活值几乎相同(如输入100和10000的激活值都接近1)。
3. 计算成本高:涉及指数运算,计算复杂度比ReLU等函数高。
import torch
import matplotlib.pyplot as plt# plt支持中文
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = Falsedef test001():# 一行两列绘制图像_, ax = plt.subplots(1, 2)# 绘制函数图像x = torch.linspace(-10, 10, 100)y = torch.sigmoid(x)# 网格ax[0].grid(True)ax[0].set_title("sigmoid 函数曲线图")ax[0].set_xlabel("x")ax[0].set_ylabel("y")# 在第一行第一列绘制sigmoid函数曲线图ax[0].plot(x, y)# 绘制sigmoid导数曲线图x = torch.linspace(-10, 10, 100, requires_grad=True)# y = torch.sigmoid(x) * (1 - torch.sigmoid(x))# 自动求导torch.sigmoid(x).sum().backward()ax[1].grid(True)ax[1].set_title("sigmoid 函数导数曲线图", color="red")ax[1].set_xlabel("x")ax[1].set_ylabel("y")# ax[1].plot(x.detach().numpy(), y.detach())# 用自动求导的结果绘制曲线图ax[1].plot(x.detach().numpy(), x.grad.detach().numpy())# 设置曲线颜色ax[1].lines[0].set_color("red")plt.show()if __name__ == "__main__":test001()

在这里插入图片描述

2.2 tanh

tanh(双曲正切)是一种常见的非线性激活函数,常用于神经网络的隐藏层。tanh 函数也是一种S形曲线,输出范围为(−1,1)(−1,1)(1,1)

方面内容
公式tanh(x)=ex−e−xex+e−x\text{tanh}(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}}tanh(x)=ex+exexex
特征1. 输出范围在 (−1,1)(-1, 1)(1,1) 之间,零中心化输出有助于加速收敛。
2. 是关于原点对称的奇函数,输入为0时输出也为0,有助于数据平衡。
3. 全局连续可微,导数公式为:ddxtanh(x)=1−tanh2(x)\frac{d}{dx} \text{tanh}(x) = 1 - \text{tanh}^2(x)dxdtanh(x)=1tanh2(x)
优点1. 输出零中心化,加速收敛。
2. 对称性有助于数据平衡。
3. 全局可微,适合梯度下降优化。
缺点1. 梯度消失:输入值非常大或非常小时,导数接近于0,深层网络中仍会导致训练缓慢甚至无法收敛。
2. 计算成本:涉及指数运算,计算复杂度较高,尽管与 Sigmoid 相比差异不大。
import torch
import matplotlib.pyplot as plt# plt支持中文
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = Falsedef test001():# 一行两列绘制图像_, ax = plt.subplots(1, 2)# 绘制函数图像x = torch.linspace(-10, 10, 100)y = torch.tanh(x)# 网格ax[0].grid(True)ax[0].set_title("tanh 函数曲线图")ax[0].set_xlabel("x")ax[0].set_ylabel("y")# 在第一行第一列绘制tanh函数曲线图ax[0].plot(x, y)# 绘制tanh导数曲线图x = torch.linspace(-10, 10, 100, requires_grad=True)# y = torch.tanh(x) * (1 - torch.tanh(x))# 自动求导:需要标量才能反向传播torch.tanh(x).sum().backward()ax[1].grid(True)ax[1].set_title("tanh 函数导数曲线图", color="red")ax[1].set_xlabel("x")ax[1].set_ylabel("x.grad")# ax[1].plot(x.detach().numpy(), y.detach())# 用自动求导的结果绘制曲线图ax[1].plot(x.detach().numpy(), x.grad.detach().numpy())# 设置曲线颜色ax[1].lines[0].set_color("red")plt.show()if __name__ == "__main__":test001()

在这里插入图片描述

2.3 Relu

ReLU(Rectified Linear Unit)是深度学习中最常用的激活函数之一,它的全称是修正线性单元。ReLU 激活函数的定义非常简单,但在实践中效果非常好。

方面内容
定义ReLU(x)=max⁡(0,x)\text{ReLU}(x) = \max(0, x)ReLU(x)=max(0,x)
特征1. 当 x>0x > 0x>0 时,ReLU(x) = x
2. 当 x≤0x \leq 0x0 时,ReLU(x) = 0
3. 导数是分段函数:ReLU′(x)={1,if x>00,if x≤0\text{ReLU}'(x) = \begin{cases} 1, & \text{if } x > 0 \\ 0, & \text{if } x \leq 0 \end{cases}ReLU(x)={1,0,if x>0if x0
4. 计算简单,只需要一次比较运算。
优点1. 计算简单:加速神经网络的训练。
2. 缓解梯度消失问题:在正半区导数恒为1,不存在饱和问题,有利于深层网络的梯度传播。
3. 稀疏激活:引入稀疏性,减少冗余信息,提高效率和泛化能力。
缺点1. 神经元死亡问题:当输入小于等于0时,神经元输出为0,且导数为0,可能导致神经元永远不再激活,降低模型的表达能力。
import torch
import torch.nn.functional as F
import matplotlib.pyplot as plt# 中文问题
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = Falsedef test006():# 输入数据xx = torch.linspace(-20, 20, 1000)y = F.relu(x)# 绘制一行2列_, ax = plt.subplots(1, 2)ax[0].plot(x.numpy(), y.numpy())# 显示坐标格子ax[0].grid()ax[0].set_title("relu 激活函数")ax[0].set_xlabel("x")ax[0].set_ylabel("y")# 绘制导数函数x = torch.linspace(-20, 20, 1000, requires_grad=True)F.relu(x).sum().backward()ax[1].plot(x.detach().numpy(), x.grad.numpy())ax[1].grid()ax[1].set_title("relu 激活函数导数", color="red")# 设置绘制线色颜色ax[1].lines[0].set_color("red")ax[1].set_xlabel("x")ax[1].set_ylabel("x.grad")plt.show()if __name__ == "__main__":test006()

在这里插入图片描述

2.4 LeakyRelu

Leaky ReLU是一种对 ReLU 函数的改进,旨在解决 ReLU 的一些缺点,特别是Dying ReLU 问题。Leaky ReLU 通过在输入为负时引入一个小的负斜率来改善这一问题。

方面内容
定义Leaky ReLU(x)={x,if x>0αx,if x≤0\text{Leaky ReLU}(x) = \begin{cases} x, & \text{if } x > 0 \\ \alpha x, & \text{if } x \leq 0 \end{cases}Leaky ReLU(x)={x,αx,if x>0if x0
其中,α\alphaα 是一个非常小的常数(如 0.01),控制负半轴的斜率。
特征1. 当 x>0x > 0x>0 时,Leaky ReLU(x) = x。
2. 当 x≤0x \leq 0x0 时,Leaky ReLU(x) = αx\alpha xαx,其中 α\alphaα 是一个小的负斜率。
3. 计算简单,与 ReLU 类似,只需简单的比较和线性运算。
优点1. 避免神经元死亡:通过在 x≤0x \leq 0x0 区域引入一个小的负斜率,即使输入值小于等于零,Leaky ReLU 仍然会有梯度,允许神经元继续更新权重,避免神经元在训练过程中完全“死亡”的问题。
2. 计算简单:与 ReLU 类似,计算开销低。
缺点1. 参数选择α\alphaα 是一个需要调整的超参数,选择合适的 α\alphaα 值可能需要实验和调优。
2. 可能出现负激活:如果 α\alphaα 设定得不当,仍然可能导致激活值过低,影响网络的性能。
import torch
import torch.nn.functional as F
import matplotlib.pyplot as plt# 中文设置
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = Falsedef test006():x = torch.linspace(-5, 5, 200)# 设置leaky_relu的负斜率超参数slope = 0.03y = F.leaky_relu(x, slope)# 一行两列_, ax = plt.subplots(1, 2)# 开始绘制函数曲线图ax[0].plot(x, y)ax[0].set_title("Leaky ReLU 函数曲线图")ax[0].set_xlabel("x")ax[0].set_ylabel("y")ax[0].grid(True)# 绘制leaky_relu的梯度曲线图x = torch.linspace(-5, 5, 200, requires_grad=True)F.leaky_relu(x, slope).sum().backward()ax[1].plot(x.detach().numpy(), x.grad)ax[1].set_title("Leaky ReLU 梯度曲线图", color="red")ax[1].set_xlabel("x")ax[1].set_ylabel("x.grad")ax[1].grid(True)# 设置线的颜色ax[1].lines[0].set_color("red")plt.show()if __name__ == "__main__":test006()

在这里插入图片描述

2.5 softmax

Softmax激活函数通常用于分类问题的输出层,它能够将网络的输出转换为概率分布,使得输出的各个类别的概率之和为 1。Softmax 特别适合用于多分类问题。

方面内容
定义Softmax(zi)=ezi∑j=1nezj\mathrm{Softmax}(z_i) = \frac{e^{z_i}}{\sum_{j=1}^n e^{z_j}}Softmax(zi)=j=1nezjezi
特征1. 将输出转化为概率分布,每个输出值在 (0, 1) 之间,且所有输出值之和为 1。
2. 突出差异,使得概率最大的类别的输出值更接近 1,其他类别更接近 0。
3. 常与交叉熵损失函数结合使用,用于多分类问题。
4. 导数计算:当 i=ji = ji=j 时,∂pi∂zi=pi(1−pi)\frac{\partial p_i}{\partial z_i} = p_i(1 - p_i)zipi=pi(1pi);当 i≠ji \neq ji=j 时,∂pi∂zj=−pipj\frac{\partial p_i}{\partial z_j} = -p_i p_jzjpi=pipj
优点1. 概率化输出:将网络输出转化为概率分布,便于分类决策。
2. 突出差异:放大差异,使得最大概率值更接近 1,其他值更接近 0。
3. 数学性质良好:导数计算简单,适合多分类问题。
缺点1. 数值不稳定性:当 ziz_izi 的数值过大时,ezie^{z_i}ezi 可能导致数值溢出。可以通过减去最大值 max⁡(z)\max(z)max(z) 来解决:Softmax(zi)=ezi−max⁡(z)∑j=1nezj−max⁡(z)\mathrm{Softmax}(z_i) = \frac{e^{z_i - \max(z)}}{\sum_{j=1}^n e^{z_j - \max(z)}}Softmax(zi)=j=1nezjmax(z)ezimax(z)
2. 计算开销大:在处理大量类别时(如大词汇表),计算开销较大。
import torch
import torch.nn as nn# 表示4分类,每个样本全连接后得到4个得分,下面示例模拟的是两个样本的得分
input_tensor = torch.tensor([[-1.0, 2.0, -3.0, 4.0], [-2, 3, -3, 9]])softmax = nn.Softmax()
output_tensor = softmax(input_tensor)
# 关闭科学计数法
torch.set_printoptions(sci_mode=False)
print("输入张量:", input_tensor)
print("输出张量:", output_tensor)
http://www.lryc.cn/news/595684.html

相关文章:

  • Datawhale 202507 夏令营:让AI学会数学推理
  • Ultralytics代码详细解析(四:engine->trainer.py 训练部分代码详解)
  • 架构演进核心路线:从离线仓库到实时湖仓一体
  • EMA《2025-2028年药品监管中的数据与AI 1.3版》信息分析
  • vscode不识别vsix结尾的插件怎么解决?
  • SQL 基础案例解析
  • Oracle RAC+ADG switchover 切换演练流程
  • 景区负氧离子监测设备:守护清新,赋能旅游
  • 操作符练习
  • 倍增算法与应用(倍增优化之ST表、LCA、功能图、树上差分、贪心、二分)
  • mybatis多对一一对多的关联及拼接操作以及缓存处理
  • 主流开源LLM架构对比与突破·
  • 【Qt开发】Qt的背景介绍(四)
  • 项目复盘核心要点
  • 网络安全基础作业三
  • 图论的整合
  • JS WebAPIs DOM节点概述
  • v0+claude+cursor构建初始脚手架
  • 北京养老金计算公式网页实现案例:从需求分析到架构设计
  • 在Python中操作Word
  • 滴滴0722 总结与优化方向
  • J2EE模式---前端控制器模式
  • es6中的symbol基础知识
  • Element Plus Table 组件扩展:表尾合计功能详解
  • UE5 UI ScrollBox 滚动框
  • .NET使用EPPlus导出EXCEL的接口中,文件流缺少文件名信息
  • 归并排序(Merge Sort)(递归写法)
  • 【前端】ikun-pptx编辑器前瞻问题一: pptx的xml样式, 使用html能100%还原么
  • vscode目录,右键菜单加入用VSCode打开文件和文件夹(快速解决)(含删除)(脚本)
  • 基于 KeepAlived + HAProxy 搭建 RabbitMQ 高可用负载均衡集群