一、项目简介

本项目使用 PyTorch 搭建了一个简单的卷积神经网络 CNN,用来完成 CIFAR-10 图片分类任务。

CIFAR-10 是一个经典图像分类数据集,一共有 10 个类别:

类别 英文名
飞机 airplane
汽车 automobile
bird
cat
鹿 deer
dog
青蛙 frog
horse
ship
卡车 truck

每张图片大小为 32 × 32,并且是 RGB 彩色图片,所以输入模型时可以理解成:

3 × 32 × 32

其中 3 表示 RGB 三个颜色通道。

本项目的完整流程是:

加载数据集 -> 数据预处理 -> 建立 CNN 网络 -> 声明损失函数和优化器 -> 训练模型 -> 测试模型 -> 可视化结果

二、什么是神经网络

神经网络可以简单理解为一个“可以学习规律的函数”。

普通程序通常需要人手动写规则,例如:

如果有尖耳朵、胡须、圆脸,那么可能是猫

但图片太复杂了,猫、狗、车、飞机在不同角度、颜色、背景下都会变化,很难靠人工写规则判断。

神经网络的做法是:

给模型大量图片和正确答案,让模型自己从数据中学习规律

比如我们给模型很多猫的图片和标签 cat,很多狗的图片和标签 dog,模型就会逐渐学会区分猫和狗。


三、神经网络的基本训练流程

训练神经网络主要包含四个核心步骤:

前向传播 -> 计算损失 -> 反向传播 -> 更新参数

可以把它理解成一次学习过程:

步骤 作用
前向传播 模型根据输入图片给出预测结果
计算损失 判断预测结果和真实答案差多少
反向传播 计算每个参数应该怎么调整
更新参数 优化器根据梯度修改模型参数

这个过程会重复很多次,模型的预测能力就会逐渐提升。


四、什么是前向传播

前向传播就是图片从输入端进入模型,一层一层经过神经网络,最后得到预测结果的过程。

在本项目中,一张 CIFAR-10 图片进入模型后,大致流程如下:

原始图片
-> 卷积层提取特征
-> 激活函数增强表达能力
-> 池化层压缩尺寸
-> Dropout 减少过拟合
-> 全连接层进行分类
-> 输出 10 个类别分数

项目中的前向传播函数非常简洁:

def forward(self, x):
    x = self.features(x)
    return self.classifier(x)

这里的 x 就是输入图片。它先经过 features 提取特征,再经过 classifier 输出分类结果。

模型最后不是直接输出“猫”或者“狗”,而是输出 10 个类别对应的分数。哪个类别分数最高,模型就认为图片属于哪个类别。

例如模型可能输出:

类别 分数
cat 2.8
dog 1.6
truck -0.4
ship 0.2

如果 cat 的分数最高,那么模型就预测这张图片是猫。


五、本项目 CNN 网络结构

本项目使用的是一个简单 CNN 网络,主要分成两部分:

features:负责提取图片特征
classifier:负责根据特征进行分类

也可以理解为:

卷积部分负责“看图”
全连接部分负责“做判断”

项目中模型的主体写法如下,只保留关键结构:

class SimpleCNN(nn.Module):
    def __init__(self, num_classes=10):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 32, kernel_size=3, padding=1),
            nn.BatchNorm2d(32),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2),

            nn.Conv2d(32, 64, kernel_size=3, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2),

            nn.Conv2d(64, 128, kernel_size=3, padding=1),
            nn.BatchNorm2d(128),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2),
        )

        self.classifier = nn.Sequential(
            nn.Flatten(),
            nn.Linear(128 * 4 * 4, 256),
            nn.ReLU(inplace=True),
            nn.Linear(256, num_classes),
        )

这段代码体现了 CNN 的基本思想:前半部分不断用卷积层提取图像特征,后半部分用全连接层完成分类。

1. 特征提取部分 features

特征提取部分主要由卷积层、归一化层、激活函数、池化层和 Dropout 组成。

整体结构可以概括为三组:

组别 通道变化 图片尺寸变化 作用
第一组 3 -> 32 32×32 -> 16×16 提取基础特征
第二组 32 -> 64 16×16 -> 8×8 提取更复杂的局部特征
第三组 64 -> 128 8×8 -> 4×4 提取更高级的图像特征

图片在卷积部分中的变化大致是:

3 × 32 × 32
-> 32 × 32 × 32
-> 32 × 16 × 16
-> 64 × 16 × 16
-> 64 × 8 × 8
-> 128 × 8 × 8
-> 128 × 4 × 4

可以看到,随着网络变深:

图片尺寸越来越小
特征通道越来越多

这说明模型正在把原始图片逐渐压缩成更抽象的特征。

2. 分类部分 classifier

卷积部分输出的是:

128 × 4 × 4

这个结果还不能直接分类,所以需要先展开成一维向量:

128 × 4 × 4 = 2048

然后通过全连接层进行分类:

2048 个特征 -> 256 个特征 -> 10 个类别分数

最后的 10 对应 CIFAR-10 的 10 个类别。


六、每种网络层的作用

1. Conv2d 卷积层

卷积层是 CNN 的核心。

它的作用是从图片中提取局部特征,例如:

边缘
纹理
颜色块
轮廓
局部形状

在本项目中,卷积层一共有 5 个,是网络中最重要的特征提取部分。

2. BatchNorm2d 批归一化层

BatchNorm2d 的作用是让训练过程更加稳定。

可以简单理解为:它会调整每一批数据的分布,让模型训练时不容易大幅波动。

3. ReLU 激活函数

ReLU 是激活函数,它会把负数变成 0,正数保持不变。

输入:[-2, 0.5, 3, -1]
输出:[0, 0.5, 3, 0]

它的作用是给网络加入非线性能力。如果没有激活函数,网络即使堆很多层,表达能力也会很有限。

这里要注意:ReLU 不是代码注释,也不是“解释上一层”,它本身就是网络中真实执行的一步操作。

4. MaxPool2d 池化层

池化层的作用是缩小特征图尺寸。

例如:

32 × 32 -> 16 × 16
16 × 16 -> 8 × 8
8 × 8 -> 4 × 4

这样可以减少计算量,同时保留比较明显的特征。

5. Dropout 随机失活

Dropout 会在训练时随机丢弃一部分神经元输出。

例如:

Dropout(0.30)

表示训练时随机丢弃 30% 的输出。

它的作用是防止模型过度依赖某些特征,从而减少过拟合。


七、这个网络到底有几层

如果只数主要可学习层,本项目网络有:

5 个卷积层
2 个全连接层

所以可以说:

这是一个 5 层卷积 + 2 层全连接的简单 CNN 网络。

如果把 BatchNorm、ReLU、池化、Dropout、Flatten 都算进去,层数会更多。但在介绍网络结构时,通常重点说卷积层和全连接层。


八、损失函数是什么

模型训练时需要知道自己预测得好不好。衡量预测错误程度的函数,就叫损失函数。

本项目使用的是:

CrossEntropyLoss

它是多分类任务中最常用的损失函数。

在项目中声明损失函数的代码是:

criterion = nn.CrossEntropyLoss()

比如真实答案是 cat,但是模型认为 dog 的分数最高,那么损失就会比较大。

训练的目标就是:

让损失函数的值越来越小

损失越小,说明模型预测结果和真实标签越接近。


九、反向传播是什么

前向传播之后,模型得到了预测结果。接着损失函数会告诉模型“错得有多离谱”。

但模型还需要知道:

到底应该修改哪些参数?
每个参数应该往哪个方向改?
应该改多少?

这就是反向传播要做的事情。

反向传播会从损失函数开始,沿着网络反方向计算每个参数对错误的影响,这个影响就叫梯度。

可以简单理解成:

反向传播 = 给每个参数计算修改建议

十、优化器是什么

反向传播只负责计算梯度,也就是告诉模型“应该怎么改”。

真正修改参数的是优化器。

本项目使用的是:

Adam 优化器

对应代码如下:

optimizer = torch.optim.Adam(model.parameters(), lr=LEARNING_RATE)

优化器会根据梯度调整模型参数,让下一次预测更接近正确答案。

其中学习率 learning rate 控制每次参数更新的步子大小。

学习率太大,模型可能训练不稳定;学习率太小,模型训练会很慢。

本项目使用:

学习率 = 0.001

十一、一次训练循环发生了什么

训练时,模型会一批一批读取图片。每一批图片都会经历下面的过程:

1. 读取一批图片和标签
2. 把图片和标签放到 GPU
3. 前向传播,得到预测结果
4. 计算损失
5. 清空旧梯度
6. 反向传播,计算新梯度
7. 优化器更新参数
8. 统计 loss 和 accuracy

在代码中,对应的核心逻辑是:

清空梯度 -> 前向传播 -> 计算损失 -> 反向传播 -> 更新参数

这就是神经网络训练中最核心的一套流程。

对应到项目代码,就是下面这几行:

optimizer.zero_grad()
logits = model(images)
loss = criterion(logits, labels)
loss.backward()
optimizer.step()

逐行理解:

代码 作用
optimizer.zero_grad() 清空上一轮梯度
logits = model(images) 前向传播,得到预测分数
loss = criterion(logits, labels) 计算预测和真实标签之间的损失
loss.backward() 反向传播,计算梯度
optimizer.step() 优化器更新模型参数

十二、训练模式和评估模式的区别

训练时使用:

model.train()

评估时使用:

model.eval()

原因是有些层在训练和测试时行为不同,例如:

训练时 评估时
Dropout 随机丢弃部分输出 不再随机丢弃
BatchNorm 使用当前 batch 统计信息 使用训练得到的统计信息

所以训练和评估时要切换模式。

另外,评估时不需要反向传播,因为我们只是测试模型效果,不需要更新参数。


十三、为什么要画训练曲线

训练曲线可以帮助我们判断模型是否真的在学习。

一般会观察:

train_loss
test_loss
train_acc
test_acc

正常情况下:

loss 会逐渐下降
accuracy 会逐渐上升

如果训练准确率很高,但测试准确率很低,说明模型可能过拟合。


十四、混淆矩阵有什么用

准确率只能告诉我们模型整体对了多少,但不能告诉我们具体错在哪里。

混淆矩阵可以显示模型把哪些类别认错了。

例如:

cat 被预测成 dog
automobile 被预测成 truck
deer 被预测成 horse

这些类别本身外观比较相近,所以容易混淆。

本项目会生成混淆矩阵:

image/confusion_matrix.png

十五、结合本项目总结

本项目实现了一个完整的 CIFAR-10 图片分类流程:

1. 使用 torchvision 自动下载 CIFAR-10 数据集
2. 使用 transforms 做图片预处理和数据增强
3. 使用 CNN 提取图片特征
4. 使用全连接层输出 10 类分类结果
5. 使用 CrossEntropyLoss 计算分类损失
6. 使用 Adam 优化器更新参数
7. 使用 GPU 加速训练
8. 输出训练曲线、混淆矩阵和预测结果

项目中的 CNN 网络虽然不算复杂,但已经包含了深度学习图像分类任务中最核心的部分:

卷积特征提取
非线性激活
池化降采样
Dropout 防止过拟合
全连接分类
前向传播
反向传播
参数更新

通过这个项目,可以比较完整地理解一个神经网络是如何从图片输入开始,经过层层计算,最终输出分类结果,并通过训练不断提升准确率的。


十六、个人理解

一开始看神经网络代码时,最容易困惑的是每一层到底在做什么。

比如:

Conv2d 后面接 BatchNorm2d、ReLU、MaxPool2d、Dropout

可以这样记:

Conv2d:提取特征
BatchNorm2d:稳定训练
ReLU:增加非线性
MaxPool2d:缩小尺寸
Dropout:减少过拟合
Linear:根据特征分类

神经网络训练也可以用一句话概括:

前向传播负责预测,损失函数衡量错误,反向传播计算梯度,优化器更新参数。

结合 CIFAR-10 项目后,这些概念就不再抽象。图片从 3 × 32 × 32 输入网络,经过卷积层逐渐变成 128 × 4 × 4 的高级特征,最后通过全连接层输出 10 个类别分数。训练过程中,模型会根据预测错误不断调整参数,最终学会区分不同类别的图片。

Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐