课程视频链接

CNN卷积神经网络算法原理

全神经网络的整体结构

输入层(x1, x2, x3…)->隐藏层(全连接)->输出层,整体就类似于一个函数,输入x,经过函数module(x)得到输出y的过程,图像可以看成一个矩阵例如128 * 128的图片就是一个128 * 128的矩阵作为输入x,这就是全连接神经网络,他是深度学习的基础。后面讲的卷积神经网络和他类似,主要将隐藏层换成卷积核
在这里插入图片描述
在这里插入图片描述

全连接神经网络的结构单元

深度学习一般是从单元到整体,然后搭建一个基础模型model,这个model可能由许多model进行排列组合构成,例如:1 * model1 + 2 * model2 + 5 * model3等等,然后通过这个model,输入x,得到y,如果发现y的结果很好,则可以根据这个model写一篇论文,这就是创新的地方。任何一个单元结构都是通过组合而成的。

输入(x1, x2, x3…)已经确定,所以优化模型的突破点在于改变w1, w2, w3…以及z,也就是找到一组最优的参数(w和b,它们都是矩阵)使得结果最优,所谓结果最优,就是最接近我们所希望的输出。
在这里插入图片描述

为什么要加入非线性激活函数

激活函数一般为非线性函数(非直线)。下图解释了,当激活函数为线性函数的时候出现的问题,多层的神经网络并没有起到效果,等价于一个参数,相当于只有一层,就不能发挥层数的作用。深度学习中,往往层数越多,效果越好,例如ResNet在保证深度的同时,又不会过拟合
在这里插入图片描述

Sigmoid激活函数

主要记忆函数图像以及导数的图像,因为导数是用来求参数(w和b)
在这里插入图片描述

Tanh激活函数

导数值越大,找参数(w和b)就会更快,当导数趋近为0的时候,w和b也就趋于确定
在这里插入图片描述

ReLu激活函数

在这里插入图片描述

Leaky ReLU函数

没有最优的模型,只有最合适的模型
加粗样式
在这里插入图片描述
在这里插入图片描述

神经网络前向传播(从左往右)

对模型(modle)输入内容x(音频图形等等,一般都是矩阵),得到输出y的过程就是神经网络前向传播
在这里插入图片描述
取中间的一条线,来看具体是如何计算的
在这里插入图片描述
训练、推理、验证、测试,这些过程都会设计导前向传播的过程。

神经网络的损失函数

损失函数就是计算前项传播,和实际希望之间的误差。利用损失函数可以说明,模型经过若干轮之后收敛了(就是loss值不断下降,区域稳定)。
f ( x i ) f(x_{i}) f(xi)是正向传播之后得到的结果, y i y_{i} yi是希望的结果,计算其均方误差的结果就是损失函数。通过损失函数反向传播(由梯度下降法实现)更新w, b,使得每一轮的效果越来越好。总结一下,训练过程中,前向传播计算误差,反向传播更新w,b。
在这里插入图片描述

  • 回归问题:输出的值是连续的,例如:预测明天的天气是多少度?
  • 分类问题:输出的值是离散的,例如:是猫还是狗?是猫为0,是狗为1。

训练模型的过程中,一开始误差会非常大,后面的误差会越来越小

梯度下降法(反向传播)-更新w 和 b

举一个下山的例子,来直观感受梯度下降法
在这里插入图片描述
因为x(输入的内容已经确定),所以实际 f ( x ) f(x) f(x)可以表示为 f ( w , b ) f(w, b) f(w,b),利用其求均方误差。 a a a是超参数(这里是学习率),为什么是偏导,因为w包含 w 1 , w 2 . . . w_{1}, w_{2}... w1,w2...因此,轮次越多,找到最优的w,b的参数几率越大。我们这里理解这个公式就可以了,这是梯度下降法最本质的内容。
在这里插入图片描述

反向传播计算样例

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

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

基础知识的总结

  1. 1000份数据(作为输入x),得到对应的输出1000份对应的y,得到1000份(x, y)
  2. 搭建模型model
  3. 开始训练,需要设置一些超参数,例如学习率,学习训练轮数等等,然后进行前向传播y,计算误差,反向传播更新w,n,直到训练轮次结束,最后产生model(w,b更新结束)
  4. 开始测试给定x,看是否符合预期的输出y
  5. 应用

图像在神经网络中的表示

CNN卷积神经网络,输入往往是图像或者视频(一帧一帧的图像)
图像在计算机中的本质,一般是像素矩阵(每个位置上的数字都在0-255之间)。
灰度图:单通道
彩色图:多通道(这里的通道指的是,每个特征值提取的特征)

全连接神经网络

全连接神经网络会破坏空间信息,如下图所示,需要先将图片矩阵展开,卷积神经网络(CNN)不会破坏
在这里插入图片描述

卷积运算过程

卷积是一种计算,卷积神经网络包含卷积运算和池化运算,可以没有池化运算,但是不能没有卷积运算。
输入x,这里是图像矩阵,卷积核就是w,卷积核的大小不会因为输入的大小改变而改变。卷积核的大小就是参数的数量。
在这里插入图片描述
在这里插入图片描述
卷积核(w)可以通过梯度下降法更新,偏置b和w的公式类似。
在这里插入图片描述
计算公式:输入 * 卷积核 + 偏置 ,通过激活函数得到输出

步符

这里每次移动两个单位,步符是2,最后得到的输出是2 * 2,步符和输出的大小是有一定关系的,如果步符是1,那么得到的输出结果是1 * 1
在这里插入图片描述

填充

步符和填充操作一起来帮助控制下一层输出特征图的大小,避免卷积块不断变小,导致后序不能运算的问题。
在这里插入图片描述

输入特征图和输出特征图的计算公式

前面讲解的都是单通道的,但是在实际中,多通道的才是比较常见的。来了解一下多通道输入的情况,其中每个特征图和对应的卷积核进行运算,最后将得到的若干结果进行同位置的相加。
在这里插入图片描述
这里c表示通道数,
在这里插入图片描述
卷积核的数量可以设置,比如说FN个,如下所示。
在这里插入图片描述
再加上偏置
在这里插入图片描述

池化操作(没听明白)

池化操作不带有参数,不会改变通道数

卷积神经网络的整体结构

在这里插入图片描述
卷积神经网络(Convolutional Neural Networks,简称CNN)是一种深度学习模型,它在图像和视频识别、分类和分割等领域表现出色。CNN的核心思想是利用卷积层来自动、逐层地提取特征,而不需要人为设计特征。下面是卷积神经网络的基本结构和一些关键组件:

  1. 输入层(Input Layer)

    • 这是网络的入口,通常接收原始图像数据。
  2. 卷积层(Convolutional Layer)

    • 包含多个卷积核(或滤波器),每个卷积核负责提取输入数据中的特定特征(如边缘、纹理等)。
    • 卷积操作通过滑动窗口(卷积核)在输入数据上进行,生成特征图(feature maps)。
  3. 激活函数(Activation Function)

    • 通常在卷积层之后使用,如ReLU(Rectified Linear Unit),它可以帮助网络学习非线性特征。
  4. 池化层(Pooling Layer)

    • 用于降低特征图的空间维度,减少参数数量和计算量,同时提高特征的不变性(如平移不变性)。
    • 最常见的池化操作是最大池化(Max Pooling)。
  5. 归一化层(Normalization Layer)

    • 可选,用于归一化特征图,减少内部协变量偏移(Internal Covariate Shift)。
  6. 全连接层(Fully Connected Layer)

    • 也称为密集层,它将前面层提取的特征映射到最终的输出空间,如类别标签。
  7. 输出层(Output Layer)

    • 最后一层,根据任务的不同,可以是Softmax层(用于分类任务)或其他类型的层。
  8. 损失函数(Loss Function)

    • 用于评估模型的预测与真实标签之间的差异,常见的损失函数包括交叉熵损失(Cross-Entropy Loss)。
  9. 优化器(Optimizer)

    • 用于更新网络权重,以最小化损失函数,常见的优化器包括SGD(随机梯度下降)、Adam等。

一个典型的CNN可能包含多个卷积层、激活层、池化层和全连接层的组合,每一层都有助于提取和抽象图像特征。随着网络的深入,特征图的深度会增加,而空间维度会减小,直到最终通过全连接层输出预测结果。

CNN的结构可以根据具体任务进行调整,例如,对于图像分割任务,可能需要使用特殊的结构如U-Net或FCN(全卷积网络)。对于视频处理,可能需要在时间维度上添加额外的卷积层来捕捉时间序列信息。

LeNet原理与实战

搭建卷积神经网络的流程

  • 搭建模型
  • 处理数据,并将数据送给模型
  • 对模型进行测试,评估模型的性能

涉及到的文件

  • model.py:网络模型的代码
  • train.py:训练的代码
  • test..py:测试的代码
    其中 train.py以及test..py几乎是不变的,只是导入的模型变换了,所以这两部分代码是很重要的。

LeNet-5诞生的背景

LeNet-5中的5表示这个网络有5层神经网络,其中每次卷积操作是一层,但是池化操作不算,因为该操作不涉及参数。
在这里插入图片描述
经验之谈:处理数据+训练要占到80%的时间,而搭建模型只占到20%的时间

LeNet网络结构如下:

在这里插入图片描述

AlexNet诞生背景

从大规模数据集中抽取部分作为训练集对模型进行训练,再抽取其他部分作为测试集,看模型训练的效果,再比赛中,AlexNet表现良好。
在这里插入图片描述

AlexNet网络结构

“深的多”可以理解为卷积层多了一些
在这里插入图片描述

AlexNet网络参数(没听懂)

基于输出公式
在这里插入图片描述
在这里插入图片描述

DropOut操作

在这里插入图片描述

代码实战先导

深度学习代码的组成

  • model:代码量最少
  • train:数据处理以及模型训练,他们往往会产生权重(w),权重包含模型结构以及训练好的w和b的数值,一般用80%的数据进行训练,10%的数据进行验证,10%的数据进行测试,将测试的结果和label进行比对,得到精度(accurate)
  • test

所以,写代码的流程,一般为,搭建模型(model.py),训练(train.py),以及测试(test.py),刚开始的时候,除了关注模型的搭建,还要学习训练以及测试,因为,训练和测试一旦写完,对于后序实验一般可以直接使用,不同的实验只是模型不一样。

LeNet-5模型搭建

class类

  • 初始化:
  • 网络层:
  • 激活函数:
  • def:搭建网络模型(前向传播的过程),反向传播是train代码中的内容
import torch
from torch import nn # nn中包含一些需要的层:全连接层,卷积层,池化层
from torchsummary import summary # 用来输出一些参数

class LeNet(nn.Module):
    # 模型的初始化
    def __init__(self):
        super(LeNet).__init__()
        self.c1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5, padding=2)
        self.sig = nn.Sigmoid() # 调用激活函数
        self.s2 = nn.AvgPool2d(kernel_size=2, stride= 2)
        self.c3 = nn.Conv2d(in_channels=6, out_channels= 16, kernel_size=5)
        self.s4 = nn.AvgPool2d(kernel_size=2, stride=2)

        self.flatten = nn.Flatten() # 展平操作
        self.f5 = nn.Linear(400, 120)
        self.f5 = nn.Linear(120, 84)
        self.f5 = nn.Linear(84, 10)

LeNet-5前向传播的定义和测试

import torch
from torch import nn # nn中包含一些需要的层:全连接层,卷积层,池化层
from torchsummary import summary # 用来输出一些参数

class LeNet(nn.Module):
    # 模型的初始化
    def __init__(self):
        super(LeNet, self).__init__()

        self.c1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5, padding=2)
        self.sig = nn.Sigmoid() # 调用激活函数
        self.s2 = nn.AvgPool2d(kernel_size=2, stride= 2)
        self.c3 = nn.Conv2d(in_channels=6, out_channels= 16, kernel_size=5)
        self.s4 = nn.AvgPool2d(kernel_size=2, stride=2)

        self.flatten = nn.Flatten() # 展平操作
        self.f5 = nn.Linear(400, 120)
        self.f6 = nn.Linear(120, 84)
        self.f7 = nn.Linear(84, 10)

    ## 前向传播,搭建网络,按照逻辑来
    def forward(self, x):
        x = self.sig((self.c1(x))) # 卷积-》激活函数
        x = self.s2(x) # 池化

        x = self.sig(self.c3(x)) # 卷积-》激活
        x = self.s4(x) # 池化

        x = self.flatten(x) #平展
        x = self.f5(x)
        x = self.f6(x)
        x = self.f7(x)
        return x

# 书写主函数,测试搭建的模型
if __name__ == "__main__":
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu") #如果有GPU返回cuda,否则返回cpu
    print(device)
    model = LeNet().to(device) # 将模型实例化,并将其放入GPU
    print(summary(model,(1, 28, 28)))

控制台输出

cuda
----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
            Conv2d-1            [-1, 6, 28, 28]             156
           Sigmoid-2            [-1, 6, 28, 28]               0
         AvgPool2d-3            [-1, 6, 14, 14]               0
            Conv2d-4           [-1, 16, 10, 10]           2,416
           Sigmoid-5           [-1, 16, 10, 10]               0
         AvgPool2d-6             [-1, 16, 5, 5]               0
           Flatten-7                  [-1, 400]               0
            Linear-8                  [-1, 120]          48,120
            Linear-9                   [-1, 84]          10,164
           Linear-10                   [-1, 10]             850
================================================================
Total params: 61,706
Trainable params: 61,706
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.00
Forward/backward pass size (MB): 0.11
Params size (MB): 0.24
Estimated Total Size (MB): 0.35
----------------------------------------------------------------
None

Process finished with exit code 0

Fashion_MNIST数据集介绍

不用传统的手写数字识别(十分类)数据集,是因为它在每一个网络模型上都有不错的效果,采用Fashion_MNIST数据集识别衣服和鞋子等物品,这样实验效果具有区分度。
创建plot.py文件
打印标签

from torchvision.datasets import FashionMNIST # torchvision中包含许多数据集
from torchvision import transforms
import torch.utils.data as Data
import numpy as np

train_data = FashionMNIST(root='./data',
                          train=True,
                          transform=transforms.Compose([transforms.Resize(size=224), transforms.ToTensor()]),
                          download=True) #(下载路径,只下载数据集,归一化处理)

train_loader = Data.DataLoader(dataset=train_data,
                               batch_size=64,
                               shuffle=True,
                               num_workers=0)

# 获得一个Batch的数据
for step, (b_x, b_y) in enumerate(train_loader):
    if step > 0:
        break
batch_x = b_x.squeeze().numpy() # 将四维张量移除第一维,并转换为Numpy数组
batch_y = b_y.numpy() # 将张量转换为Numpy数组
class_label = train_data.classes # 训练集的标签
print(class_label)

控制台输出

['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

可视化一个Batch的图像

from torchvision.datasets import FashionMNIST # torchvision中包含许多数据集
from torchvision import transforms
import torch.utils.data as Data
import numpy as np
import matplotlib.pyplot as plt

train_data = FashionMNIST(root='./data',
                          train=True,
                          transform=transforms.Compose([transforms.Resize(size=224), transforms.ToTensor()]),
                          download=True) #(下载路径,只下载数据集,归一化处理)

train_loader = Data.DataLoader(dataset=train_data,
                               batch_size=64,
                               shuffle=True,
                               num_workers=0)

# 获得一个Batch的数据
for step, (b_x, b_y) in enumerate(train_loader):
    if step > 0:
        break
batch_x = b_x.squeeze().numpy() # 将四维张量移除第一维,并转换为Numpy数组
batch_y = b_y.numpy() # 将张量转换为Numpy数组
class_label = train_data.classes # 训练集的标签
# print(class_label)

# 可视化一个Batch的图像
plt.figure(figsize=(12, 5))
for ii in np.arange(len(batch_y)):
    plt.subplot(4, 16, ii + 1)
    plt.imshow(batch_x[ii, :, : ],  cmap=plt.cm.gray)
    plt.title(class_label[batch_y[ii]], size = 10)
    plt.axis('off')  # 关闭坐标轴
    plt.subplots_adjust(wspace=0.05)
plt.show()

在这里插入图片描述
主要就是学习一下数据的展示

训练模版代码

import copy
import time
import torch
from torchvision.datasets import FashionMNIST # torchvision中包含许多数据集
from torchvision import transforms
import torch.utils.data as Data
import numpy as np
import matplotlib.pyplot as plt
import torch.nn as nn
from model import LeNet # 从model.py中导入网络模型
import pandas as pd
# 加载数据集
def train_val_data_process():
    train_data = FashionMNIST(root = './data',
                              train= True,
                              transform=transforms.Compose([transforms.Resize(size=28),transforms.ToTensor()]),
                              download=True)
    # 80%用来训练,20%用来验证
    train_data, val_data = Data.random_split(train_data, [round(0.8*len(train_data)), round(0.2 * len(train_data))])

    train_dataloader = Data.DataLoader(dataset=train_data,
                                       batch_size=64, # 如果报虚拟内存错误,可以改小一点
                                       shuffle=True,
                                       num_workers=2) # 将数据分为128个批次

    val_dataloader = Data.DataLoader(dataset=val_data,
                                       batch_size=64,
                                       shuffle=True,
                                       num_workers=2)

    return train_dataloader, val_dataloader


# 初始化值定义
def train_model_process(model, train_dataloader, val_dataloader, num_epochs):
    # 设定训练所用到的设备,有GPU用GPU,没有Gpu用CPU
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    # 使用Adam优化器, 学习率为0.001
    optimizer = torch.optim.Adam(model.parameters(), lr=0.001) # 优化器 本质都是梯度下降法
    # 损失函数为交叉熵函数
    criterion = nn.CrossEntropyLoss()

    # 将模型放到训练设备当中
    model = model.to(device)

    # 复制当前模型的参数
    best_model_wts = copy.deepcopy(model.state_dict())

    # 初始化参数
    # 最高精确度
    best_acc = 0.0
    # 训练集损失函数列表
    train_loss_all = []
    # 验证集损失函数列表
    val_loss_all = []
    # 训练集精度列表
    train_acc_all = []
    # 验证精度列表
    val_acc_all = []
    # 当前时间
    since = time.time()

    # 训练反向传播
    # 模型的轮次
    for epoch in range(num_epochs):
        print("Epoch {}/{}".format(epoch, num_epochs - 1)) # ephoch从0开始
        print("-"*10)

        # 初始化参数
        # 训练集损失函数
        train_loss = 0.0
        # 训练集准确度
        train_correct = 0

        # 验证集损失函数
        val_loss = 0.0
        # 验证集准确度
        val_correct = 0

        # 训练集的样本数量
        train_num = 0
        # 验证集的样本数量
        val_num = 0

        # 取出训练集特征和标签
        for step, (b_x, b_y) in enumerate(train_dataloader):
            # 将特征放入到训练设备中
            b_x = b_x.to(device)
            # 将标签放入到训练设备中
            b_y = b_y.to(device)

            # 设置模型为训练模式
            model.train()

            # 进行前向传播,输入为一个batch,输出为一个batch中对应的预测
            output = model(b_x)

            # 查找每一行中最大值对应的行标
            pre_lab = torch.argmax(output, dim=1)

            # 计算每一个batch的损失函数
            loss = criterion(output, b_y)

            # 将梯度初始化为0
            optimizer.zero_grad()

            # 反向传播
            loss.backward()

            # 根据反向传播的梯度信息更新网络参数,以起到降低loss函数计算值的作用
            optimizer.step()

            # 对损失函数进行累加
            train_loss += loss.item() * b_x.size(0)

            # 如果预测正确,则准确度train_correct+1
            train_correct += torch.sum(pre_lab == b_y.data)

            # 当前用于训练的样本数量
            train_num += b_x.size(0)

        # 验证代码
        for step, (b_x, b_y) in enumerate(val_dataloader):
            # 将特征放入到验证设备中
            b_x = b_x.to(device)

            # 将标签放入到验证设备中
            b_y = b_y.to(device)

            # 设置模型为评估模式
            model.eval()

            # 前向传播过程,输入为一个batch,输出为一个batch中对应的预测
            output = model(b_x)

            # 查找每一行中最大值对应的行标
            pre_lab = torch.argmax(output, dim=1)

            # 计算每一个batch的损失函数
            loss = criterion(output, b_y)

            # 对损失函数进行累加
            val_loss += loss.item() * b_x.size(0)

            # 如果预测正确,则准确度train_correct+1
            val_correct += torch.sum(pre_lab == b_y.data)

            # 当前用于训练的样本数量
            val_num += b_x.size(0)

        # 计算并保存每一次迭代的loss值和准确率
        # 计算并保存训练集的loss值
        train_loss_all.append(train_loss / train_num) # 平均loss值
        # 计算并保存训练集的准确率
        train_acc_all.append(train_correct.double().item() / train_num)

        # 计算并保存验证集的loss值
        val_loss_all.append(val_loss / val_num)
        # 计算并保存验证集的准确率
        val_acc_all.append(train_correct.double().item() / val_num)

        print("{} train loss:{:.4f} train acc: {:.4f}".format(epoch, train_loss_all[-1], train_acc_all[-1]))
        print("{} val loss:{:.4f} val acc: {:.4f}".format(epoch, val_loss_all[-1], val_acc_all[-1]))

        # 寻找最高准确度的权重
        if val_acc_all[-1] > best_acc:

            best_acc = val_acc_all[-1] # 将最高确度更新为当前准确度

            best_model_wts = copy.deepcopy(model.state_dict())

        # 训练耗费时间
        time_use  = time.time() - since
        print("训练和验证耗费的时间{:.0f}m{:.0f}s".format(time_use//60, time_use%60))

    # 加载最优参数
    # 加载最高准确率的模型参数
    model.load_state_dict(best_model_wts)
    # 保存权重文件到指定地址
    torch.save(model.load_state_dict(best_model_wts), "E:/桌面/LeNet/best_model.pth")

    train_process = pd.DataFrame(data={ "epoch" : range(num_epochs),
                                        "train_loss_all":train_loss_all,
                                        "val_loss_all":val_loss_all,
                                        "train_acc_all":train_acc_all,
                                            "val_acc_all":val_acc_all})
    return train_process

def matplot_acc_loss(train_process):
    plt.figure(figsize=(12, 4))
    # 绘制损失
    plt.subplot(1, 2, 1)
    plt.plot(train_process["epoch"], train_process["train_loss_all"], 'ro-', label="train loss")
    plt.plot(train_process["epoch"], train_process["val_loss_all"], 'bs-', label="val loss")
    plt.legend()
    plt.xlabel("epoch")
    plt.ylabel("loss")
    plt.show()
    # 绘制准确率
    plt.subplot(1, 2, 2)
    plt.plot(train_process["epoch"], train_process["train_acc_all"], 'ro-', label="train acc")
    plt.plot(train_process["epoch"], train_process["val_acc_all"], 'bs-', label="val acc")
    plt.legend()
    plt.xlabel("epoch")
    plt.ylabel("accuracy")

    plt.show()

# 编写主函数,运行代码
if __name__ == "__main__":
    # 将模型实例化
    LeNet = LeNet()
    train_dataloader, val_dataloader = train_val_data_process();
    train_process=train_model_process(LeNet, train_dataloader, val_dataloader, 20)
    matplot_acc_loss(train_process)

AlexNet的原理与实战

LeNet5适合小数据集,2012年,AlexNet首次引入深度卷积神经网络,在大规模视觉挑战赛中脱颖而出。两个模型相比,不同之处在于:

  • ALexNet更深,它由八层组成,五个卷积层,两个全连接隐藏层
  • AlexNet使用ReLu而不是sigmoid作为激活函数
    在这里插入图片描述

Alex网络参数

在这里插入图片描述

知识积累

激活函数

激活函数是神经网络中用于引入非线性因素的重要组成部分。它在每个神经元的输出上应用,以决定是否以及如何传递信息到下一层。不同的激活函数对模型的学习和表现有不同的影响。

常见的激活函数包括:

  1. Sigmoid(S形函数)

    • 公式: σ ( x ) = 1 1 + e − x \sigma(x) = \frac{1}{1 + e^{-x}} σ(x)=1+ex1
    • 输出范围:0 到 1
    • 应用:多用于二分类问题,特别是最后一层。
    • 缺点:容易出现梯度消失问题。
  2. Tanh(双曲正切函数)

    • 公式: tanh ⁡ ( x ) = 2 1 + e − 2 x − 1 \tanh(x) = \frac{2}{1 + e^{-2x}} - 1 tanh(x)=1+e2x21
    • 输出范围:-1 到 1
    • 应用:相比于 Sigmoid,Tanh 的输出更加中心对称,因此在某些应用中表现更好。
    • 缺点:同样存在梯度消失问题。
  3. ReLU(Rectified Linear Unit,修正线性单元)

    • 公式: R e L U ( x ) = max ⁡ ( 0 , x ) ReLU(x) = \max(0, x) ReLU(x)=max(0,x)
    • 输出范围:0 到正无穷
    • 应用:非常常用的激活函数,特别是在深度神经网络中。
    • 优点:计算简单,收敛速度快。
    • 缺点:当输入为负值时,梯度为零,可能导致“神经元死亡”问题。
  4. Leaky ReLU

    • 公式: L e a k y R e L U ( x ) = max ⁡ ( α x , x ) Leaky ReLU(x) = \max(\alpha x, x) LeakyReLU(x)=max(αx,x),其中 α \alpha α 是一个很小的正数(如 0.01)。
    • 应用:是 ReLU 的改进版,解决了 ReLU 的神经元死亡问题。
  5. Softmax

    • 公式: s o f t m a x ( x i ) = e x i ∑ j e x j softmax(x_i) = \frac{e^{x_i}}{\sum_{j}e^{x_j}} softmax(xi)=jexjexi
    • 输出范围:0 到 1,且所有输出的和为 1。
    • 应用:通常用于多分类问题的最后一层,生成概率分布。
  6. ELU(Exponential Linear Unit)

    • 公式: ELU ( x ) = x \text{ELU}(x) = x ELU(x)=x x ≥ 0 x \geq 0 x0 ELU ( x ) = α ( e x − 1 ) \text{ELU}(x) = \alpha(e^x - 1) ELU(x)=α(ex1) x < 0 x < 0 x<0
    • 应用:减少了 ReLU 函数中负输入部分的“神经元死亡”问题。

每种激活函数都有其特定的应用场景,根据模型的架构和任务的需求,选择合适的激活函数能够显著提升神经网络的表现。

更多推荐