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

《深度学习》——CNN卷积神经网络模型及项目实例

文章目录

  • CNN卷积神经网络
    • 基本组成成分
    • 工作原理
    • 常见CNN模型
    • CNN优势
    • 应用领域
    • 局限性
  • CNN项目实例
    • 项目实现
        • 导入所需库
        • 下载训练集和测试集数据
        • 对训练和测试样本进行分批次
        • 判断pytorch是否支持GPU
        • 定义CNN卷积神经网络模型
        • 定义训练函数
        • 定义测试函数
        • 创建交叉熵损失函数和优化器
        • 通过多轮训练降低损失值得到最终结果

CNN卷积神经网络

卷积神经网络(Convolutional Neural Network,简称 CNN)是一种专门为处理具有网格结构数据(如图像、音频)而设计的深度学习模型,在计算机视觉、语音识别等领域有着广泛的应用。

基本组成成分

  • 卷积层:是 CNN 的核心层,通过卷积核在输入数据上滑动并进行卷积运算,提取数据的局部特征。不同的卷积核可以捕捉到不同类型的特征,例如边缘、纹理等。随着网络层数的增加,卷积层可以学习到越来越复杂的特征。
  • 池化层:通常紧随卷积层之后,主要作用是对数据进行下采样,降低数据的维度,减少计算量,同时还能在一定程度上防止过拟合。常见的池化操作有最大池化(Max Pooling)和平均池化(Average Pooling),最大池化是取池化窗口内的最大值,平均池化则是计算池化窗口内的平均值。
  • 全连接层:在经过多个卷积层和池化层的特征提取后,全连接层将前面提取到的特征进行整合,并映射到输出空间。全连接层的每一个神经元都与上一层的所有神经元相连,用于对提取到的特征进行分类或回归等任务。
  • 激活函数:为神经网络引入非线性因素,使得网络能够学习和表示复杂的非线性关系。常见的激活函数有 ReLU(Rectified Linear Unit)、Sigmoid、Tanh 等。以 ReLU 为例,其函数表达式为 f (x) = max (0, x),当输入大于 0 时,输出等于输入;当输入小于 0 时,输出为 0。

进行卷积处理:

请添加图片描述

工作原理

  • 输入数据(如图像)首先进入卷积层,卷积核与输入数据进行卷积运算,生成特征图。特征图中每个元素的值是卷积核与输入数据对应局部区域的加权和。
  • 经过卷积层后,特征图进入池化层进行下采样,池化操作在不改变特征图深度的情况下,减小其空间尺寸。
  • 经过多个卷积层和池化层的交替处理后,得到的特征图被展平成一维向量,输入到全连接层。全连接层对特征进行进一步的处理和变换,最终输出预测结果。
    在这里插入图片描述

常见CNN模型

  • LeNet-5(1998):首个成功应用于手写数字识别的CNN,包含卷积、池化和全连接层。

  • AlexNet(2012):在ImageNet竞赛中突破性表现,引入ReLU和Dropout。

  • VGGNet(2014):通过堆叠3×3小卷积核构建深层网络。

  • ResNet(2015):提出残差连接(Residual Block),解决深层网络梯度消失问题。

  • Transformer-based模型(如ViT):结合注意力机制,挑战传统CNN地位。

CNN优势

  • 自动特征提取:无需人工设计特征,直接从数据中学习。

  • 参数效率:局部连接和参数共享大幅减少参数量。

  • 平移不变性:池化操作使模型对目标位置变化更鲁棒。

  • 端到端学习:从原始输入到最终输出一体化训练。

应用领域

  • 图像分类(如ResNet、EfficientNet)

  • 目标检测(如YOLO、Faster R-CNN)

  • 图像分割(如U-Net、Mask R-CNN)

  • 人脸识别、医学影像分析、自动驾驶等。

局限性

  • 计算资源需求:深层CNN训练需要大量GPU资源。

  • 空间信息依赖:对输入尺寸敏感,需固定或动态调整。

  • 序列数据处理弱:长距离依赖建模不如RNN或Transformer灵活。

CNN项目实例

  • 项目需求:对手写数字进行识别。
  • 数据集:此项目数据集来自MNIST 数据集由美国国家标准与技术研究所(NIST)整理而成,包含手写数字的图像,主要用于数字识别的训练和测试。该数据集被分为两部分:训练集和测试集。训练集包含 60,000 张图像,用于模型的学习和训练;测试集包含 10,000 张图像,用于评估训练好的模型在未见过的数据上的性能。
    • 图像格式:数据集中的图像是灰度图像,即每个像素只有一个值表示其亮度,取值范围通常为 0(黑色)到 255(白色)。
    • 图像尺寸:每张图像的尺寸为 28x28 像素,总共有 784 个像素点。
    • 标签信息:每个图像都有一个对应的标签,标签是 0 到 9 之间的整数,表示图像中手写数字的值

项目实现

导入所需库
import torch
from torch import nn  # 导入神经网络模块
from torch.utils.data import DataLoader  # 数据包管理工具,打包数据
from torchvision import datasets  # 封装了很对与图像相关的模型,数据集
from torchvision.transforms import ToTensor  # 数据转换,张量,将其他类型的数据转换成tensor张量
下载训练集和测试集数据
'''下载训练数据集(包含训练集图片+标签)'''
training_data = datasets.MNIST(  # 跳转到函数的内部源代码,pycharm 按下ctrl+鼠标点击
    root='data',  # 表示下载的手写数字 到哪个路径。60000
    train=True,  # 读取下载后的数据中的数据集
    download=True,  # 如果你之前已经下载过了,就不用再下载了
    transform=ToTensor(),  # 张量,图片是不能直接传入神经网络模型
    # 对于pytorch库能够识别的数据一般是tensor张量
)

'''下载测试数据集(包含训练图片+标签)'''
test_data = datasets.MNIST(
    root='data',
    train=False,
    download=True,
    transform=ToTensor(),  # Tensor是在深度学习中提出并广泛应用的数据类型,它与深度学习框架(如pytorch,TensorFlow)
)  # numpy数组只能在cpu上运行。Tensor可以在GPU上运行,这在深度学习应用中可以显著提高计算速度。
print(len(training_data))
print(len(test_data))

打印训练集和测试集的数量:

在这里插入图片描述

对训练和测试样本进行分批次
# 创建训练数据的 DataLoader 对象
# DataLoader 是 PyTorch 中用于批量加载数据的实用工具类,它可以帮助我们更高效地处理大规模数据集。
train_dataloader = DataLoader(training_data, batch_size=64)  # 建议用2的指数当作一个包的数量
test_dataloader = DataLoader(test_data, batch_size=64)
判断pytorch是否支持GPU
'''判断是否支持GPU'''
device = 'cuda' if torch.cuda.is_available() else 'mps' if torch.backends.mps.is_available() else 'cpu'
print(f'Using {device} device')

定义CNN卷积神经网络模型
# 定义一个名为 CNN 的卷积神经网络类,继承自 nn.Module
class CNN(nn.Module):
    def __init__(self):
        # 调用父类 nn.Module 的构造函数
        super(CNN, self).__init__()
        # 定义第一个卷积层块
        # nn.Conv2d(1, 64, 5, 1, 2):输入通道数为 1(因为是灰度图),输出通道数为 64,卷积核大小为 5x5,步长为 1,填充为 2
        # nn.ReLU():使用 ReLU 激活函数增加模型的非线性
        # nn.MaxPool2d(kernel_size=2):使用 2x2 的最大池化层进行下采样
        self.conv1 = nn.Sequential(
            nn.Conv2d(1, 64, 5, 1, 2),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2),
        )
        # 定义第二个卷积层块
        # nn.Conv2d(64, 128, 5, 1, 2):输入通道数为 64,输出通道数为 128,卷积核大小为 5x5,步长为 1,填充为 2
        # nn.ReLU():使用 ReLU 激活函数增加模型的非线性
        # nn.MaxPool2d(2):使用 2x2 的最大池化层进行下采样
        self.conv2 = nn.Sequential(
            nn.Conv2d(64, 128, 5, 1, 2),
            nn.ReLU(),
            nn.MaxPool2d(2),
        )
        # 定义第三个卷积层块
        # 包含多个卷积层和 ReLU 激活函数
        # nn.Conv2d(128, 64, 5, 1, 2):输入通道数为 128,输出通道数为 64,卷积核大小为 5x5,步长为 1,填充为 2
        # nn.Conv2d(64, 32, 5, 1, 2):输入通道数为 64,输出通道数为 32,卷积核大小为 5x5,步长为 1,填充为 2
        # nn.Conv2d(32, 16, 5, 2, 4):输入通道数为 32,输出通道数为 16,卷积核大小为 5x5,步长为 2,填充为 4
        # nn.ReLU():使用 ReLU 激活函数增加模型的非线性
        # nn.MaxPool2d(2):使用 2x2 的最大池化层进行下采样
        self.conv3 = nn.Sequential(
            nn.Conv2d(128, 64, 5, 1, 2),
            nn.ReLU(),
            nn.Conv2d(64, 32, 5, 1, 2),
            nn.ReLU(),
            nn.Conv2d(32, 16, 5, 2, 4),
            nn.ReLU(),
            nn.MaxPool2d(2),
        )
        # 定义第四个卷积层块
        # nn.Conv2d(16, 8, 3, 2, 5):输入通道数为 16,输出通道数为 8,卷积核大小为 3x3,步长为 2,填充为 5
        # nn.ReLU():使用 ReLU 激活函数增加模型的非线性
        # nn.MaxPool2d(2):使用 2x2 的最大池化层进行下采样
        self.conv4 = nn.Sequential(
            nn.Conv2d(16, 8, 3, 2, 5),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )
        # 定义全连接层
        # 输入特征数为 8 * 3 * 3,输出特征数为 10(假设用于 10 分类任务)
        self.out = nn.Linear(8 * 3 * 3, 10)
    def forward(self, x):
        # 前向传播过程
        # 将输入 x 通过第一个卷积层块
        x = self.conv1(x)
        # 将第一个卷积层块的输出通过第二个卷积层块
        x = self.conv2(x)
        # 将第二个卷积层块的输出通过第三个卷积层块
        x = self.conv3(x)
        # 将第三个卷积层块的输出通过第四个卷积层块
        x = self.conv4(x)
        # 将卷积层的输出展平为一维向量,以便输入到全连接层
        # x.size(0) 表示批量大小,-1 表示自动计算其余维度的大小
        x = x.view(x.size(0), -1)
        # 将展平后的向量通过全连接层得到最终输出
        output = self.out(x)
        return output
# 创建 CNN 模型的实例,并将模型移动到指定设备(GPU 或 CPU)上
model = CNN().to(device)
定义训练函数
def train(dataloader,model,loss_fn,optimizer):
    model.train() # 告诉模型,要开始训练,模型中w进行随机化操作,已经更新w,在训练过程中w会被修改
    # pytorch提供两种方式来切换训练和测试的模式,分别是:model.train()和model.eval()
    # 一般用法:在训练之前写model.train(),在测试时写model.eval()
    batch_size_num = 1
    for x,y in dataloader: # 其中batch为每一个数据的编号
        x,y=x.to(device),y.to(device) # 将训练数据和标签传入gpu
        pred = model.forward(x) # .forward可以被省略,父类中已经对次功能进行了设置。自动初始化w权值
        loss = loss_fn(pred,y) # 通过交叉熵损失函数计算损失值loss
        # Backpropagation 进来个batch的数据,计算一次梯度,更新一次网络
        optimizer.zero_grad() #梯度值清零
        loss.backward() # 反向传播计算每一个参数的梯度值w
        optimizer.step() # 根据梯度更新网络w参数

        loss_value = loss.item() # 从tensor数据中提取数据出来,tensor获取损失值
        if batch_size_num % 100 == 0:
            print(f'loss:{loss_value:7f}  [number:{batch_size_num}]' )
        batch_size_num += 1

定义测试函数
def test(dataloader,model,loss_fn):
    size = len(dataloader.dataset) # 10000
    num_batches = len(dataloader) # 打包的数据
    model.eval() # 测试,w就不能再更新
    test_loss,correct = 0,0
    with torch.no_grad(): # 一个上下文管理器,关闭梯度计算。当你确定不会调用Tensor.backward()的时候。这可以减少计算内存
        for x,y in dataloader:
            x,y = x.to(device),y.to(device)
            pred = model.forward(x)
            test_loss += loss_fn(pred,y).item()#test_loss是会自动累加每一个批次的损失值
            correct  +=(pred.argmax(1) == y).type(torch.float).sum().item()
            a = (pred.argmax(1) == y)#dim=1表示每一行中的最大值对应的索引号,dim=0表示每一列中的最大值对应的索引号
            b = (pred.argmax(1) == y).type(torch.float)
    test_loss /=num_batches#能来衡量模型测试的好坏。
    correct /= size#平均的正确率

    print(f'Test result: \n Accuracy:{(100*correct)}%,Avg loss:{test_loss}')


创建交叉熵损失函数和优化器
loss_fn = nn.CrossEntropyLoss()#创建交叉熵损失函数对象,因为手写字识别中一共有10个数字,输出会有10个结果
#一会改成adam优化器
optimizer = torch.optim.Adam(model.parameters(),lr=0.001)#创建一个优化器,SGD为随机梯度下降算法
#params:要训练的参数,一般我们传入的都是model.parameters()
# #lr:learning_rate学习率,也就是步长。
通过多轮训练降低损失值得到最终结果
epochs = 20
for t in range(epochs):
    print(f'epoch{t+1}\n--------------------')
    train(train_dataloader,model, loss_fn, optimizer)
print('Done!')
test(test_dataloader,model, loss_fn)

结果:

在这里插入图片描述

可以看到在训练20轮过后的准确率为99.35%,损失值为0.0363。
与经典神经网络BP神经网络对数据的训练:https://blog.csdn.net/lou0720/article/details/145557286?spm=1001.2014.3001.5501
的结果:在这里插入图片描述
相比明显CNN的准确性更高,模型对数据的训练更加优秀。


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

相关文章:

  • 7.推荐系统的评价与优化
  • 第三届通信网络与机器学习国际学术会议(CNML 2025)
  • arcgis界址点编号工具开发原理(西北角顺时针)
  • Docker搭建redis集群
  • TCN时间卷积神经网络多变量多步光伏功率预测(Matlab)
  • DeepSeek本地部署详细指南
  • 【Prometheus】MySQL主从搭建,以及如何通过prometheus监控MySQL运行状态
  • FTP(File Transfer Protocol)-文件传输协议
  • C++引用深度详解
  • Unity做2D小游戏5------多个动画互相转换
  • docker配置国内源
  • 【unity实战】实现摄像机跟随效果
  • 【AI知识点】大模型开源的各种级别和 deepseek 的开源级别
  • Java 大视界 -- 5G 与 Java 大数据融合的行业应用与发展趋势(82)
  • ArcGIS Pro SDK (二十六)自定义配置
  • 基于 PyTorch 的树叶分类任务:从数据准备到模型训练与测试
  • 25考研电子信息复试面试常见核心问题真题汇总,电子信息考研复试没有项目怎么办?电子信息考研复试到底该如何准备?
  • 进阶版MATLAB 3D柱状图
  • 【系统架构设计师】操作系统 - 进程管理 ① ( 进程概念 | 进程组成 | 进程 与 程序 | 进程 与 线程 | 线程 可共享的资源 - ☆考点 )
  • 工具模块新增JSON格式化打印工具类
  • 什么是容器化,它有什么好处,对后端开发有什么影响?
  • 【2025-ICLR-未中】教授多模态大语言模型理解心电图图像
  • 【C#零基础从入门到精通】(五)——C# {n:format} 占位符
  • C#调用Python的函数(编译为pyd,避免源码泄露)
  • 朝天椒USB服务器:破解银企直连中Ukey管理难题
  • 算法-反转链表