深度学习基础教程(一):常见激活函数篇

在这里插入图片描述

解码深度学习:神经元与激活函数共舞,开启AI智能密码探索之旅!📌别忘了点赞关注哦~

一、深度学习介绍

1.1 什么是深度学习

在介绍深度学习之前,我们先看下人工智能、机器学习和深度学习之间的关系:

  • 人工智能 (Artificial Intelligence)
    • 机器学习 (Machine Learning)
      • 深度学习 (Deep Learning)
        • 大语言模型 (Large Language Model)
  • 层级关系:人工智能 > 机器学习 > 深度学习,核心逻辑:所有应用神经网络技术的机器学习,都可称为深度学习

在这里插入图片描述

图 1. AI 层级关系

  • 机器学习是实现人工智能的一种途径,深度学习是机器学习的一个子集,也就是说深度学习是实现机器学习的一种方法。与机器学习算法的主要区别如下图所示:

在这里插入图片描述

图 2. ML和DL 的对比

  • 传统机器学习算法依赖人工设计特征,并进行特征提取,而深度学习方法不需要人工,而是依赖算法自动提取特征。深度学习模仿人类大脑的运行方式,从经验中学习获取知识。这也是深度学习被看做黑盒子,可解释性差的原因。

  • 随着计算机软硬件的飞速发展,现阶段通过深度学习来模拟人脑来解释数据,包括图像,文本,音频等内容。目前深度学习的主要应用领域有:语音识别、机器翻译、计算机视觉、自然语言处理、推荐系统、医疗健康、 自动驾驶

1.2 发展历史

  • 深度学习其实并不是新的事物,深度学习所需要的神经网络技术起源于20世纪50年代,叫做感知机。当时也通常使用单层感知机,尽管结构简单,但是能够解决复杂的问题。后来感知机被证明存在严重的问题,因为只能学习线性可分函数,连简单的异或(XOR)等线性不可分问题都无能为力,1969年Marvin Minsky写了一本叫做《Perceptrons》的书,他提出了著名的两个观点:

  • 1.单层感知机没用,我们需要多层感知机来解决复杂问题 2.没有有效的训练算法
    在这里插入图片描述

    图 3. Marvin Minsky先生

  • 20世纪80年代末期,用于人工神经网络的反向传播算法 (也叫Back Propagation算法或者BP算法)的发明,给机器学习带来了希望,掀起了基于统计模型的机器学习热潮。这个热潮一直持续到今天。人们发现,利用BP算法可以让一个人工神经网络模型从大量训练样本中学习统计规律,从而对未知事件做预测。这种基于统计的机器学习方法比起过去基于人工规则的系统,在很多方面显出优越性。这个时候的人工神经网络,虽也被称作多层感知机 (Multi-layer Perceptron),但实际是种只含有一层隐层节点的浅层模型

  • 2006年,杰弗里·辛顿以及他的学生鲁斯坦·萨拉赫丁诺夫正式提出了深度学习的概念

  • 2012年,在著名的ImageNet图像识别大赛中,杰弗里·辛顿领导的小组采用深度学习模型AlexNet一举夺冠。AlexNet采用ReLU激活函数,从根本上解决了梯度消失问题,并采用GPU极大的提高了模型的运算速度

  • 同年,由斯坦福大学著名的吴恩达教授和世界顶尖计算机专家Jeff Dean共同主导的深度神经网络——DNN技术在图像识别领域取得了惊人的成绩,在ImageNet评测中成功的把错误率从26%降低到了15%

  • 2016年,随着谷歌公司基于深度学习开发的AlphaGo以4:1的比分战胜了国际顶尖围棋高手李世石,深度学习的热度一时无两。后来,AlphaGo又接连和众多世界级围棋高手过招,均取得了完胜。这也证明了在围棋界,基于深度学习技术的机器人已经超越了人类
    在这里插入图片描述

    图 3. AlphaGo围棋对决

二、神经网络

2.1 什么是神经网络

  • 人工神经网络(Artificial Neural Network,简写为ANN)也简称为神经网络(NN),是一种模仿生物神经网络结构和功能的计算模型。人脑可以看做是一个生物神经网络,由众多的神经元连接而成。各个神经元传递复杂的电信号,树突接收到输入信号,然后对信号进行处理,通过轴突输出信号。下图是生物神经元示意图:
    在这里插入图片描述
    图 4. 神经元示意图
  • 当电信号通过树突进入到细胞核时,会逐渐聚集电荷。达到一定的电位后,细胞就会被激活,通过轴突发出电信号

2.2 人工神经网络

  • 那怎么构建人工神经网络中的神经元呢?
    在这里插入图片描述
图 5. 神经元与神经网络
  • 这个流程就像,来源不同树突 (树突都会有不同的权重) 的信息,进行的加权计算,输入到细胞中做加和,再通过激活函数输出细胞值

  • 接下来,我们使用多个神经元来构建神经网络,相邻层之间的神经元相互连接,并给每一个连接分配一个强度,如下图所示:
    在这里插入图片描述

    图 6. 神经网络

  • 神经网络中信息只向一个方向移动,即从输入节点向前移动,通过隐藏节点,再向输出节点移动。 其中的基本部分是:

    • 输入层: 即输入x的那一层
    • 输出层: 即输出y的那一层
    • 隐藏层: 输入层和输出层之间都是隐藏层
  • 特点是N-1层的所有神经相连 (这就是full connected的含义),第N层神经元的输出就是第N层神经元的输入。每个连接都有一个权值

三、激活函数

3.1 网络非线性因素的理解

  • 激活函数用于对每层的输出数据进行变换,进而为整个网络结构注入了非线性因素。此时,神经网络就可以拟合各种曲线🚁
    在这里插入图片描述

  • 如果不使用激活函数,整个网络虽然看起来复杂,其本质还相当于一种线性模型,如下公式所示:
    f c 1 = w 0 c 1 x 0 + w 1 c 1 x 1 + b c 1 f c 2 = w 0 c 2 x 0 + w 1 c 2 x 1 + b c 2 f o u t = w 0 o u t f c 1 + w 1 o u t f c 2 + b o u t = w 0 o u t ( w 0 c 1 x 0 + w 1 c 1 x 1 + b c 1 ) + w 1 o u t ( w 0 c 2 x 0 + w 1 c 2 x 1 + b c 2 ) + b o u t = ( w 0 o u t w 0 c 1 + w 1 o u t w 0 c 2 ) x 0 + ( w 0 o u t w 1 c 1 + w 1 o u t w 1 c 2 ) x 1 + ( w 0 o u t b c 1 + w 1 o u t b c 2 + b o u t ) 令  k 0 = w 0 o u t w 0 c 1 + w 1 o u t w 0 c 2 , k 1 = w 0 o u t w 1 c 1 + w 1 o u t w 1 c 2 , c = w 0 o u t b c 1 + w 1 o u t b c 2 + b o u t , 则  f o u t = k 0 x 0 + k 1 x 1 + c \begin{align*} f_{c1} &= w_0^{c1}x_0 + w_1^{c1}x_1 + b^{c1} \\ f_{c2} &= w_0^{c2}x_0 + w_1^{c2}x_1 + b^{c2} \\ f_{out} &= w_0^{out}f_{c1} + w_1^{out}f_{c2} + b^{out} \\ &= w_0^{out}(w_0^{c1}x_0 + w_1^{c1}x_1 + b^{c1}) + w_1^{out}(w_0^{c2}x_0 + w_1^{c2}x_1 + b^{c2}) + b^{out} \\ &= (w_0^{out}w_0^{c1} + w_1^{out}w_0^{c2})x_0 + (w_0^{out}w_1^{c1} + w_1^{out}w_1^{c2})x_1 + (w_0^{out}b^{c1} + w_1^{out}b^{c2} + b^{out}) \\ \text{令 } k_0 &= w_0^{out}w_0^{c1} + w_1^{out}w_0^{c2}, \\ k_1 &= w_0^{out}w_1^{c1} + w_1^{out}w_1^{c2}, \\ c &= w_0^{out}b^{c1} + w_1^{out}b^{c2} + b^{out}, \\ \text{则 } f_{out} &= k_0x_0 + k_1x_1 + c \end{align*} fc1fc2fout k0k1c fout=w0c1x0+w1c1x1+bc1=w0c2x0+w1c2x1+bc2=w0outfc1+w1outfc2+bout=w0out(w0c1x0+w1c1x1+bc1)+w1out(w0c2x0+w1c2x1+bc2)+bout=(w0outw0c1+w1outw0c2)x0+(w0outw1c1+w1outw1c2)x1+(w0outbc1+w1outbc2+bout)=w0outw0c1+w1outw0c2,=w0outw1c1+w1outw1c2,=w0outbc1+w1outbc2+bout,=k0x0+k1x1+c

  • 核心结论

    • 没有引入非线性因素的网络 等价于使用一个线性模型 来拟合
    • 通过给网络输出端添加激活函数,引入非线性因素,使得网络模型可以逼近任意函数,提升对复杂问题的拟合能力

📌 通过图像可视化的形式理解
📌https://playground.tensorflow.org/

在这里插入图片描述

图 7. Neural Network 可视化界面
  • 我们发现增加激活函数之后,对于线性不可分的场景,神经网络的拟合能力更强

3.2 常见的激活函数

  • 激活函数主要用来向神经网络中加入非线性因素,以解决线性模型表达能力不足的问题,它对神经网络有着极其重要的作用。我们的网络参数在更新时,使用的反向传播算法(BP),这就要求我们的激活函数必须可微

3.2.1 sigmoid 激活函数

  • sigmoid 其公式如下:
    f ( x ) = 1 1 + e − x f(x) = \frac{1}{1 + e^{-x}} f(x)=1+ex1

  • sigmoid 激活函数的函数图像如下:

在这里插入图片描述

图 8. sigmoid 激活函数及其导数

  • 从 sigmoid 函数图像可以得到,sigmoid 函数可以将任意的输入映射到 (0, 1) 之间,当输入的值大致在 <-6 或者 >6 时,意味着输入任何值得到的激活值都是差不多的,这样会丢失部分的信息。比如:输入 100 和输出 10000 经过 sigmoid 的激活值几乎都是等于 1 的,但是输入的数据之间相差 100 倍的信息就丢失了

  • 对于 sigmoid 函数而言,输入值在 [-6, 6] 之间输出值才会有明显差异,输入值在 [-3, 3] 之间才会有比较好的效果

  • 通过上述导数图像,我们发现导数数值范围是 (0, 0.25),当输入 <-6 或者 >6 时,sigmoid 激活函数图像的导数接近为 0,此时网络参数将更新极其缓慢,或者无法更新

  • 一般来说,sigmoid 网络在 5 层之内就会产生梯度消失现象。而且,该激活函数并不是以 0 为中心的,所以在实践中这种激活函数使用的很少。sigmoid 函数一般只用于二分类的输出层

  • 在 PyTorch 中使用 sigmoid 函数的示例代码如下:

import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F

# ========== 关键配置:解决中文显示问题 ==========
plt.rcParams['font.sans-serif'] = ['SimSun']  
# 指定默认字体(如 SimSun 宋体,Windows 系统默认存在)
plt.rcParams['axes.unicode_minus'] = False     
# 解决负号 '-' 显示为方块的问题
# ==============================================

def test():
    _, axes = plt.subplots(1, 2)
    # 函数图像
    x = torch.linspace(-20, 20, 1000)
    y = F.sigmoid(x)
    axes[0].plot(x, y)
    axes[0].grid()
    axes[0].set_title('Sigmoid 函数图像')
    
    # 导数图像
    x = torch.linspace(-20, 20, 1000, requires_grad=True)
    torch.sigmoid(x).sum().backward()
    
    axes[1].plot(x.detach(), x.grad)
    axes[1].grid()
    axes[1].set_title('Sigmoid 导数图像')
    
    plt.show()

if __name__ == "__main__":
    test()

3.2.2 tanh 激活函数

  • Tanh 叫做双曲正切函数,其公式如下:
    f ( x ) = 1 − e − 2 x 1 + e − 2 x f(x) = \frac{1 - e^{-2x}}{1 + e^{-2x}} f(x)=1+e2x1e2x

  • Tanh 的函数图像、导数图像如下:
    在这里插入图片描述

    图 9. Tanh 激活函数及其导数

  • 由上面的函数图像可以看到,Tanh 函数将输入映射到 (-1, 1) 之间,图像以 0 为中心,在 0 点对称,当输入大概 <-3 或者 >3 时将被映射为 -1 或者 1,其导数值范围 (0, 1),当输入的值大概 <-3 或者 >3 时,其导数近似 0

  • 与 Sigmoid 相比,它是以 0 为中心的,使得其收敛速度要比 Sigmoid 快,减少迭代次数。然而,从图中可以看出,Tanh 两端的导数也为 0,同样会成梯度消失

  • 若使用时可在隐藏层使用 tanh 函数,在输出层使用 sigmoid 函数

import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F

def test():
    _, axes = plt.subplots(1, 2)
    # 函数图像
    x = torch.linspace(-20, 20, 1000)
    y = F.tanh(x)
    axes[0].plot(x, y)
    axes[0].grid()
    axes[0].set_title('Tanh 函数图像')
    
    # 导数图像
    x = torch.linspace(-20, 20, 1000, requires_grad=True)
    F.tanh(x).sum().backward()
    
    axes[1].plot(x.detach(), x.grad)
    axes[1].grid()
    axes[1].set_title('Tanh 导数图像')
    
    plt.show()

if __name__ == "__main__":
    test()

3.2.4 ReLU 激活函数

  • ReLU 激活函数公式如下:
    f ( x ) = max ⁡ ( 0 , x ) f(x) = \max(0, x) f(x)=max(0,x)

  • ReLU 的函数图像、导数图像如下:
    在这里插入图片描述

    图 10. ReLU 激活函数及其导数

  • 从上述函数图像可知,ReLU 激活函数将小于 0 的值映射为 0,而大于 0 的值则保持不变,它更加重视正信号,而忽略负信号,这种激活函数运算更为简单,能够提高模型的训练效率。

  • 但是,如果我们网络的参数采用随机初始化时,很多参数可能为负数,这就使得输入的正值会被舍去,而输入的负值则会保留,这可能在大部分的情况下并不是我们想要的结果。

📌ReLU 是目前最常用的激活函数。从图中可以看到,当 x<0 时,ReLU 导数为 0,而当 x>0 时,则不存在饱和问题。所以,ReLU 能够在 x>0 时保持梯度不衰减,从而缓解梯度消失问题。然而,随着训练的推进,部分输入会落入小于 0 区域,导致对应权重无法更新。这种现象被称为 “神经元死亡”

📌与 Sigmoid 相比,ReLU 的优势是:

  • 采用 sigmoid 激活函数,计算量大(指数运算),反向传播求误差梯度时,求导涉及除法,计算量相对大,而采用 ReLU 激活函数,整个过程的计算量节省很多。sigmoid 函数反向传播时,很容易就会出现梯度消失的情况,从而无法完成深层网络的训练。ReLU 会使一部分神经元的输出为 0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发生
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F

def test():
    _, axes = plt.subplots(1, 2)
    # 函数图像
    x = torch.linspace(-5, 5, 1000)  # ReLU在正负区间特性明显,缩小范围更合适
    y = F.relu(x)
    axes[0].plot(x, y)
    axes[0].grid()
    axes[0].set_title('ReLU 函数图像')
    
    # 导数图像
    x = torch.linspace(-5, 5, 1000, requires_grad=True)
    F.relu(x).sum().backward() 
    axes[1].plot(x.detach(), x.grad)
    axes[1].grid()
    axes[1].set_title('ReLU 导数图像')

    plt.show()

if __name__ == "__main__":
    test()

3.2.4 LeakyReLU 激活函数

  • LeakyReLU(带泄漏的ReLU)是ReLU激活函数的改进版本,其数学公式如下:

LeakyReLU ( x ) = { x if  x ≥ 0 α ⋅ x if  x < 0 \text{LeakyReLU}(x) = \begin{cases} x & \text{if } x \geq 0 \\ \alpha \cdot x & \text{if } x < 0 \end{cases} LeakyReLU(x)={xαxif x0if x<0

  • 其中, α \alpha α 是一个很小的常数(通常取 0.01),用于在输入为负值时提供一个微小的梯度,避免ReLU的"死亡神经元"问题
  • LeakyReLU的函数图像、导数图像如下:
    在这里插入图片描述
图 11. LeakyReLU激活函数及其导数
  • 📌ReLU在输入 x < 0 x < 0 x<0 时输出恒为0,导致对应神经元的梯度始终为0,无法更新参数(即"死亡")。而LeakyReLU在 x < 0 x < 0 x<0 时保留一个微小的斜率 α \alpha α,确保神经元即使在输入为负时仍能获得梯度,维持参数更新能力。

  • 由于LeakyReLU在整个定义域内都有非零梯度,反向传播时梯度流更连续,减少了因梯度突然消失导致的训练波动,尤其在深层网络中表现更稳定。

  • ReLU完全忽略负输入信息,而LeakyReLU对负输入保留了一定的响应(尽管微弱),这有助于模型捕捉更多潜在的特征模式,尤其在处理包含负值的输入数据(如图像中的边缘对比)时可能更有效。

3.2.5 SoftMax 激活函数

  • softmax 用于多分类过程中,它是二分类函数 sigmoid 在多分类上的推广,目的是将多分类的结果以概率的形式展现出来

  • 计算方法如下图示:
    s o f t m a x ( z i ) = e z i ∑ j e z j softmax(z_i) = \frac{e^{z_i}}{\sum_j e^{z_j}} softmax(zi)=jezjezi

  • Softmax 直白来说就是将网络输出的 logits 通过 softmax 函数,就映射成为 (0,1) 的值,而这些值的和为 1(满足概率的性质),那么我们将它理解成概率,选取概率最大(也就是对应值最大的)节点,作为我们的预测目标类别。

import torch

if __name__ == "__main__":
    scores = torch.tensor([0.2, 0.02, 0.15, 0.15, 1.3, 0.5, 0.06, 1.1, 0.05, 3.75])
    probabilities = torch.softmax(scores, dim=0)
    print(probabilities)

程序输出结果:

tensor([0.0212, 0.0177, 0.0262, 0.0262, 0.0638, 0.0927, 
0.0185, 0.0552, 0.0183, 0.7392])

3.2.6 激活函数大汇总

  • 在计算网络中, 一个节点的激活函数定义了该节点在给定的输入或输入的集合下的输出。标准的计算机芯片电路可以看作是根据输入得到开(1)或关(0)输出的数字电路激活函数。这与神经网络中的线性感知机的行为类似。然而,只有非线性激活函数才允许这种网络仅使用少量节点来计算非平凡问题。 在人工神经网络中,这个功能也被称为传递函数 [维基百科]
  • 本小节了解了常见的激活函数,以及对应的 API的使用。除了上述的激活函数,还存在很多其他的激活函数,如下图所示:
  • 🚁单变量输入激活函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 🚁多变量输入激活函数
    在这里插入图片描述

3.3 梯度消失与梯度爆炸

  • 在训练层数较深的神经网络时,容易出现 梯度消失(gradient vanishing problem)梯度爆炸(gradient exploding problem) 问题,且这两类问题的影响通常会随网络层数增加而愈发显著

  • 以包含3个隐藏层的网络为例(假设隐藏层的层级关系为:Hidden1(靠近输入层) → Hidden2 → Hidden3(靠近输出层)

在这里插入图片描述

图 12. 含有三个隐藏层的神经网络

📌两者的核心表现与内在机理可拆解如下:

3.3.1 梯度消失的本质与表现

  • 反向传播过程中,梯度从输出层向输入层逐层传递。若激活函数(如Sigmoid、Tanh)的导数绝对值小于1,经过多层链式求导后,靠近输入层的Hidden1 的梯度会因连续“乘法衰减”而趋近于0。这直接导致:
  • Hidden1的权值更新步长极小(甚至接近停滞),权值几乎维持初始化状态
  • Hidden1退化为“静态映射层”,仅对输入做固定函数变换,网络的学习能力实际集中在靠近输出的后几层(如Hidden3、Hidden2),深度结构的优势无法充分发挥

3.3.2 梯度爆炸的本质与表现

  • 梯度爆炸的本质是 反向传播中,层间梯度因子(权重矩阵与激活函数导数的乘积)的累积绝对值持续大于1 ,使梯度呈指数级放大:
      1. 学习率过大:参数更新幅度过激,引发“梯度→参数震荡→梯度更大”的恶性循环;
      1. 网络过深:靠近输入层的梯度需经更多层乘积放大,层数越多,指数增长效应越显著;
      1. 参数-激活不匹配:如sigmoid导数最大1/4,权重绝对值超4则梯度因子破1;ReLU配大权重也易让因子>1,多层累积后突破数值范围,导致训练崩溃

3.4 激活函数选择

📌这么多激活函数,我们应该如何选择呢?

🚩对于隐藏层:

  1. 优先选择ReLU激活函数
  2. 如果ReLU效果不好,那么尝试其他激活,如Leaky ReLU等
  3. 如果你使用了ReLU,需要注意一下Dead ReLU问题,避免出现大的梯度从而导致过多的神经元死亡
  4. 不要使用sigmoid激活函数,可以尝试使用tanh激活函数

🚩对于输出层

  1. 二分类问题选择sigmoid激活函数
  2. 多分类问题选择softmax激活函数
  3. 回归问题选择identity激活函数

激活函数是模型的 “灵魂开关”,掌握选择逻辑,让深度学习之旅更顺畅!

📌关注小编,带你解锁更多知识~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值