动手学深度学习 03 | 卷积神经网络实现手写数字识别

目录

前言

一、多层感知机的缺陷

二、从全连接层到卷积

1、什么是卷积

2、卷积核

3、感受野和特征映射

4、池化层(汇聚层)

三、卷积神经网络整体结构构建

[1. 特征提取模块](#1. 特征提取模块)

[2. 全连接分类模块](#2. 全连接分类模块)

四、代码分步实现与逐段讲解

[1. 导入依赖库 和 数据加载](#1. 导入依赖库 和 数据加载)

[2. 搭建 CNN 卷积神经网络模型](#2. 搭建 CNN 卷积神经网络模型)

[3. 设备、损失函数与优化器配置](#3. 设备、损失函数与优化器配置)

[4. 模型训练函数](#4. 模型训练函数)

[5. 模型测试函数](#5. 模型测试函数)

[6. 主程序入口](#6. 主程序入口)

五、实验总结


前言

上一节我们使用简单的多层感知机(MLP)完成了手写数字识别,但多层感知机存在明显缺陷。本节课我们引入卷积神经网络(CNN),用更适配图像任务的方案重新实现手写数字识别,理解 CNN 核心特性与图像任务的设计思路。

一、多层感知机的缺陷

  1. 丢失空间局部信息: 多层感知机接收图像数据时,全连接层会把二维图像矩阵展平成一维向量。这一操作破坏图片原生的二维空间结构,像素之间原本相邻的位置关系被打乱,丢失图像局部空间信息。模型无法感知局部像素组合构成的特征,不具备局部性,很难提取图像里边缘、轮廓这类局部特征。
  2. 缺少平移不变性 :图像识别任务期望:同一个数字,出现在图片左上角或是右下角,模型都能正确识别。但 MLP 不具备平移不变性,物体在画面中位置发生偏移,展平之后向量完全改变,模型识别效果会大幅下降。

为了解决局部性、平移不变性这两个核心需求,卷积神经网络应运而生。

二、从全连接层到卷积

1、什么是卷积

图像本质是由像素构成的二维矩阵。我们定义一个固定大小窗口(例如 3×3),这个窗口就是卷积核

卷积核从图像左上角开始,和对应区域 3×3 像素矩阵做互相关运算,计算得到一个新像素值,这个值就代表该局部区域的图像特征。卷积核按照设定步长,从左到右、从上到下滑动,持续做互相关运算,最终生成新的像素矩阵,以此捕获图像局部特征,满足局部性需求。

2、卷积核

卷积核的尺寸、滑动步长均可自定义,会直接改变输出特征图尺寸。

直接滑动卷积核会造成图片边缘像素被利用不足,为解决该问题引入填充(padding):在原图四周补充像素,让边缘区域也可以完整参与卷积运算。

彩色图像具备多通道,卷积核通道数需要和输入图像通道数保持一致。每个通道单独做互相关运算,再将各通道结果相加,得到单张输出特征图。

我们可以设置多个卷积核 ,每个卷积核负责提取一类特征,一个卷积核对应一张特征图。好比从不同视角观察物体,让网络能够学习边缘、纹理等多种图像特征,这一层即为卷积层

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 卷积输出特征图的尺寸由输入尺寸、卷积核大小、步长、填充共同决定,标准计算公式如下: 参数说明:输入特征图的高、宽 :卷积核尺寸 :边缘填充层数 :卷积滑动步长 :向下取整运算 本文网络验证 :MNIST 输入尺寸为,设置 ,代入公式计算:,卷积后尺寸保持不变,完美契合代码设计。 |

3、感受野和特征映射

堆叠多层卷积层后,特征图上单个像素,对应回原始输入图像的区域范围就是感受野

类比:在高楼中,楼层越高,视野覆盖地面范围越大。浅层卷积感受野小,捕捉边缘、线条这类基础特征;深层卷积感受野更大,可以捕获轮廓、整体结构等高层特征。

特征映射:图像原始局部特征,经过卷积运算,最终浓缩为特征图上单个像素值。

4、池化层(汇聚层)

在图像网络中,我们希望逐步降低特征图的空间分辨率,聚合局部信息。随着网络层数加深,神经元对应的感受野不断扩大。图像分类任务最终需要基于整张图片全局信息判断,池化层用来逐步聚合信息,生成更粗粒度的特征,同时保留卷积层提取特征的优势。

池化两大作用:降低卷积层对特征位置的敏感度,实现空间降采样。

  • 最大池化 :在指定池化窗口内,选取最大像素值作为输出结果,核心作用是保留区域内最显著的纹理、轮廓特征,弱化位置偏差干扰。
    举例 :设定 2×2 池化窗口,窗口内像素值为 \[1, 3, 2, 6],最大池化会选取最大值 6 作为该区域的输出特征。
  • 平均池化 :计算池化窗口内所有像素值的平均值作为输出结果,能够平滑区域特征、弱化局部噪声,保留整体灰度信息。
    举例 :沿用上述 2×2 窗口像素 \[1, 3, 2, 6],平均值计算为 (1+3+2+6)÷4=3,最终输出结果为 3

三、卷积神经网络整体结构构建

相较于传统多层感知机,卷积神经网络针对图像任务做了专属结构优化,整体可划分为特征提取模块全连接模块两大核心部分,分工明确、各司其职,共同完成图像特征提取与分类预测。

1. 特征提取模块

该模块是CNN的核心核心组件,由卷积层、非线性激活函数、池化层交替堆叠组成。通过多层卷积运算自动提取图像浅层纹理、边缘及深层轮廓、全局特征,搭配池化层完成特征降维、去除冗余信息,在保留关键特征的同时大幅降低计算参数量。

2. 全连接分类模块

经过特征提取模块得到的多维特征图,会通过展平操作转换为一维特征向量,再输入多层全连接网络。该模块负责对提取到的优质特征进行融合与映射,最终输出对应类别的预测结果,完成手写数字的多分类任务。

四、代码分步实现与逐段讲解

本节将完整 CNN 手写数字识别代码进行模块化拆分,分为数据处理、网络搭建、参数配置、训练测试、程序入口五大模块,逐段解析功能逻辑,方便理解卷积网络的完整训练流程。

1. 导入依赖库 和 数据加载

首先导入 PyTorch 核心工具库,加载 MNIST 官方数据集,并通过 DataLoader 实现批量数据加载,为后续网络训练提供数据支撑。

python 复制代码
# 导入所需工具库
import torch
from torch import nn                         # 搭建神经网络模块
from torch.utils.data import DataLoader      # 批量数据加载器
from torchvision import datasets             # 官方视觉数据集
from torchvision.transforms import ToTensor  # 图像转张量
加载MNIST训练集:60000张28*28手写数字图像
training_data = datasets.MNIST(
root='./data',
train=True,
download=True,
transform=ToTensor(),
)
加载MNIST测试集:10000张28*28手写数字图像
test_data = datasets.MNIST(
root='./data',
train=False,
download=True,
transform=ToTensor(),
)
批量加载数据,批次大小64,训练集打乱数据,测试集不打乱
train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True)
test_dataloader = DataLoader(test_data, batch_size=64, shuffle=False)

MNIST 数据集无需手动预处理,框架自动完成灰度化、归一化。通过 DataLoader 分批读取数据,避免一次性加载全部数据导致显存溢出,同时打乱训练集数据可以有效防止模型过拟合。

2. 搭建 CNN 卷积神经网络模型

本次网络分为两大模块:特征提取层(卷积+激活+池化) + 分类输出层(全连接网络)。卷积层负责提取图像局部特征,池化层降维去冗余,全连接层完成最终分类。

python 复制代码
# 自定义CNN网络模型
class cnnnet(nn.Module):
    def __init__(self):
        super().__init__()
        # 特征提取模块:多层卷积+激活+池化,提取图像深层特征
        self.features = nn.Sequential(
            # 第一层卷积:输入1通道(灰度图),输出16通道,5*5卷积核,补边2,步长1
            # 输出尺寸:28*28,尺寸不变,提取浅层边缘、纹理特征
            nn.Conv2d(1,16,kernel_size = 5,stride = 1,padding = 2),
            nn.ReLU(),        # 非线性激活函数
            nn.MaxPool2d(kernel_size = 2), # 最大池化降维:16*14*14
        # 第二层卷积:输入16通道,输出32通道,提取中层组合特征
        nn.Conv2d(16, 32, kernel_size = 5,stride = 1,padding = 2),
        nn.ReLU(),
        nn.MaxPool2d(kernel_size=2),   # 再次降维:32*7*7
    # 第三、四层卷积:进一步升维,提取高层全局特征
    nn.Conv2d(32, 64,kernel_size = 5,stride = 1,padding = 2),
    nn.ReLU(),
    nn.Conv2d(64, 128, kernel_size=5, stride=1, padding=2),
    nn.ReLU()
)
全连接模块:将卷积特征展平,通过全连接层输出分类结果
self.classifier = nn.Sequential(
nn.Flatten(),                 # 多维特征展平为一维向量
nn.Linear(12877, 128),      # 第一层全连接
nn.ReLU(),
nn.Linear(128,256),           # 第二层全连接
nn.ReLU(),
nn.Linear(256, 10)            # 输出10个数字类别的预测分值
)
前向传播逻辑
def forward(self,x):
x = self.features(x)    # 卷积提取特征
y = self.classifier(x)  # 全连接分类
return y

网络通过多次卷积升维提取丰富特征,搭配池化层压缩特征尺寸、降低计算量。区别于 MLP,CNN 全程保留图像二维空间结构,完美利用图像局部特征与平移不变性,大幅提升识别精度。

3. 设备、损失函数与优化器配置

python 复制代码
# 自动适配设备:优先GPU(cuda)、苹果MPS、最后CPU
device = torch.device('cuda' if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu" )
model = cnnnet()      # 实例化网络
model.to(device)      # 模型迁移至运算设备
losser = nn.CrossEntropyLoss()                     # 多分类专用交叉熵损失
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)  # Adam自适应优化器

使用 Adam 优化器替代 SGD,具备自适应学习率特性,收敛速度更快、效果更稳定。交叉熵损失专门适配多分类任务,是图像分类的标准配置。

4. 模型训练函数

python 复制代码
# 模型训练函数
def train(model,device,train_dataloader,loss_fn,optimizer):
    length = len(train_dataloader.dataset)   # 训练集总样本数
    num_batches = len(train_dataloader)       # 训练集总批次
    model.train()                             # 开启训练模式
    sum_loss = 0.0                            # 累计总损失
    correct = 0                               # 累计正确样本数
# 逐批次训练
for X,y in train_dataloader:
    X=X.to(device)
    y=y.to(device)
    y_pred = model(X)                    # 前向传播预测
    loss = loss_fn(y_pred,y)             # 计算损失
optimizer.zero_grad()                # 清空历史梯度
loss.backward()                      # 反向传播求梯度
optimizer.step()                    # 优化器更新参数
sum_loss += loss.item()
correct += (y_pred.argmax(1) == y).sum().item()
输出本轮训练指标
print(f"平均准确率{correct / length:.4f},平均损失{sum_loss / num_batches:.4f} ")

严格遵循深度学习四大训练流程:前向传播、计算损失、反向求导、参数更新。自动统计每轮训练的准确率与损失,直观监控模型收敛状态。

5. 模型测试函数

python 复制代码
# 模型测试函数
def test(model,device,test_dataloader,loss_fn):
    length = len(test_dataloader.dataset)
    num_batches = len(test_dataloader)
    model.eval()                              # 开启评估模式
    sum_loss =0.0
    correct = 0
# 关闭梯度计算,节省显存、提升推理速度
with torch.no_grad():
    for X,y in test_dataloader:
        X=X.to(device)
        y=y.to(device)
        y_pred = model(X)
        loss = loss_fn(y_pred,y)
        sum_loss += loss.item()
        correct += (y_pred.argmax(1) == y).sum().item()
print(f"测试集平均准确率{correct/length:.4f},测试平均损失{sum_loss/num_batches:.4f}")

模型测试阶段需开启评估模式并关闭梯度计算,既可以节省显存资源、加快推理速度,又能避免模型参数发生更新。该阶段仅执行前向推理,通过输入测试数据完成预测,计算测试集损失与分类准确率,客观衡量模型的泛化能力。

6. 主程序入口

python 复制代码
if __name__ == "__main__":
    epochs = 100  # 迭代训练100轮
    print("开始训练")
    for i in range(epochs):
        print(f"第{i + 1}轮训练")
        train(model, device, train_dataloader, losser, optimizer)
    print("开始测试")
    test(model, device, test_dataloader, losser)

从训练结果可以直观体现卷积神经网络的优异性能,模型仅经过首轮训练,准确率便已突破90%,收敛速度十分可观。

模型最终测试准确率为99.41%,相较于传统MLP模型,识别精度与稳定性均实现大幅提升,充分验证了CNN在图像分类任务中的优越性。

五、实验总结

本文针对传统多层感知机在图像任务上的缺陷,引入卷积神经网络完成 MNIST 手写数字识别任务。CNN 依靠局部感知、权值共享、平移不变性三大核心优势,有效保留图像二维空间特征,解决了 MLP 展平图像丢失空间信息、位置敏感的问题。通过卷积层逐层提取浅层纹理与深层语义特征,配合池化层降维去冗余,结合全连接层完成特征融合与分类,构建了完整的图像识别网络链路。

从实验结果可以看出,相较于传统 MLP 模型,本次搭建的 CNN 网络收敛速度更快、识别精度大幅提升,最终测试准确率可达 99% 以上,充分证明了卷积神经网络在计算机视觉任务中的绝对优势。本次实验重在梳理卷积神经网络的基础原理与完整训练流程,暂不开展超参数调优、网络结构优化等进阶操作。

相关推荐
VL——MOESR1 小时前
【具身智能】Cosmos Policy论文阅读随笔
论文阅读·人工智能·机器学习·具身智能·cosmospolicy
北京晶数信息科技1 小时前
加油机数据采集设备加油机数据采集器加油机智能采集器液位仪数据采集设备原厂成品油流通数智化综合监管平台技术原理与落地应用解决方案
大数据·人工智能·物联网·需求分析
NineData1 小时前
NineData智能数据管理平台新功能发布|2026年8月
数据库·人工智能·oracle·中间件·agent·数据库开发·ninedata
凌风的跨境分享1 小时前
Temu店群运维提效:定时策略自动化任务全场景实操指南
大数据·运维·前端·人工智能·架构·自动化
又見山1 小时前
Codex 实战:用 AI 写运维脚本
运维·人工智能
海带紫菜菠萝汤1 小时前
开源大模型出海开始收费:许可证里的三条路线与真实影响
人工智能·ai·开源·大模型
A hao1 小时前
LED视频处理器中帧率与刷新率的区别
大数据·图像处理·人工智能·音视频
AgentMaster1 小时前
数据治理工具选型指南:一套可复用的四阶段决策框架
大数据·数据结构·人工智能·算法
数融智域1 小时前
2026年获客智能体排行榜top前五
大数据·人工智能