PyTorch卷积神经网络图像分类实战:从模型构建到训练优化
2026/9/7 7:01:58 网站建设 项目流程

在深度学习项目中,图像分类可以说是最基础也最经典的任务之一。之前用 PyTorch 做过几次图像分类项目,最深的感受是:资料虽然多,但比较零散,尤其是从Dataset构建到模型训练、再到评估和保存,完整串起来的教程并不多。这篇文章结合 PyTorch 框架,整理一套使用卷积神经网络执行图像分类的完整实战流程,覆盖环境配置、数据读取、模型构建、训练验证、常见报错和工程优化建议,新手照着做能跑通,有基础的开发者也能直接复用里面的代码片段。

1. 图像分类与卷积神经网络

1.1 图像分类要解决什么问题

图像分类的目标是让计算机根据图像内容自动判断它属于哪个类别。比如给一张猫的照片,模型输出“猫”的标签;给一张手写数字图片,模型输出对应的数字类别。它是目标检测、图像分割、人脸识别等更复杂视觉任务的基础。

传统方法依赖人工设计的特征,比如颜色直方图、纹理特征、边缘检测等,再配合 SVM、决策树等分类器。这类方法在简单场景下有效,但面对复杂背景、光照变化、物体姿态差异时,泛化能力非常有限。

卷积神经网络(Convolutional Neural Network,CNN)通过大量数据自动学习图像中的层次化特征:浅层卷积核学习边缘、纹理等低级特征,深层卷积核学习部件、语义等高级特征。整个过程端到端完成,不需要人工设计特征,这也是 CNN 在图像分类领域占据主导地位的核心原因。

1.2 CNN 的核心组成

一个典型的图像分类 CNN 模型包含以下几个关键结构:

结构作用常见形式
卷积层提取局部特征Conv2d、激活函数
池化层降低空间尺寸,保留主要特征MaxPool2d、AvgPool2d
全连接层将特征映射到类别概率Linear、Softmax
损失函数衡量预测与真实标签差距CrossEntropyLoss

1.3 PyTorch 在图像分类中的优势

PyTorch 是目前科研和工程中常用的深度学习框架之一。它采用动态计算图,调试直观;内置torchvision提供了丰富的数据集、预训练模型和数据增强工具;同时 GPU 训练和分布式训练生态完善,非常适合做图像分类实战。

2. 环境准备与版本说明

在开始实战之前,先确认环境是否满足要求。本文示例以常见环境为例,重点演示配置思路,具体版本需要根据你的项目实际情况调整。

2.1 安装环境要求

环境项推荐配置
操作系统Windows 10/11、Ubuntu 20.04 及以上
Python3.8 及以上
PyTorch2.x 或 1.13 均可,建议 2.0+
GPU可选,有 Nvidia 显卡时配置 CUDA
开发工具VS Code 或 PyCharm
依赖库torchvision、matplotlib、numpy、pillow

2.2 PyTorch 安装要点

安装 PyTorch 前,先确认自己的 CUDA 版本。在命令行执行:

nvidia-smi

输出中会显示 CUDA Version,例如CUDA Version: 12.1。然后到 PyTorch 官网选择对应的安装命令。CPU 环境直接安装 CPU 版本即可:

pip install torch torchvision torchaudio

GPU 环境示例(以 CUDA 12.1 为例):

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

需要注意,PyTorch 版本、CUDA 版本、显卡驱动三者要匹配。如果驱动版本过旧,即使安装了对应 CUDA 版本的 PyTorch,也会出现CUDA unavailable或类似警告。

2.3 验证安装结果

在 Python 环境中执行:

import torch print("PyTorch版本:", torch.__version__) print("CUDA是否可用:", torch.cuda.is_available()) if torch.cuda.is_available(): print("GPU名称:", torch.cuda.get_device_name(0))

如果torch.cuda.is_available()返回True,说明 GPU 环境配置成功;返回False时,文章后续会提供排查思路。

3. CNN 核心原理与代码对应关系

这一节把 CNN 的概念和 PyTorch 代码对应起来,方便后面写模型时心里更有数。

3.1 卷积层:如何提取特征

卷积层通过一个可学习的卷积核在图像上滑动,每次计算一个小区域内的加权和,从而提取局部特征。PyTorch 中使用nn.Conv2d实现:

import torch.nn as nn # 输入通道=3(RGB图像),输出通道=16,卷积核大小=3,padding=1 conv_layer = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, padding=1)

关键参数:

  • in_channels:输入通道数,RGB 图像为 3,灰度图为 1。
  • out_channels:卷积核数量,决定输出特征图的通道数。
  • kernel_size:卷积核大小,常见 3x3、5x5。
  • stride:滑动步长,默认 1。
  • padding:边缘填充,padding=1配合kernel_size=3可以保持特征图尺寸不变。

3.2 激活函数:引入非线性

卷积操作本质是线性运算,如果不加激活函数,无论堆叠多少层,整个网络仍然等价于一个线性模型。ReLU 是图像分类中最常用的激活函数,计算简单、能缓解梯度消失问题。

activation = nn.ReLU(inplace=True)

3.3 池化层:降低特征图尺寸

池化层对局部区域进行下采样,减少计算量并保留主要特征。最大池化在图像分类中更常用:

pool_layer = nn.MaxPool2d(kernel_size=2, stride=2)

2x2的最大池化会把特征图宽高各缩小一半。

3.4 全连接层与分类输出

卷积和池化层将原始图像逐步变换为特征图,全连接层负责把特征图展平后映射到类别数量。假设最后输出的类别数为 10:

fc_layer = nn.Linear(in_features=512, out_features=10)

配合CrossEntropyLoss,模型输出的 10 个数值可以视为每个类别的打分。

3.5 直观理解特征提取过程

可以把 CNN 的前面部分理解为一个“自动特征提取器”,后面全连接层理解为一个“分类器”。训练过程中,两者同时优化。这也是为什么 CNN 不需要单独设计特征,只需要准备好标注好的图像数据即可。

4. 完整实战:PyTorch 实现图像分类模型

下面进入核心内容,使用 PyTorch 从零构建一个卷积神经网络,完成图像分类任务。为了演示完整流程,本文使用 CIFAR-10 数据集(10 类彩色小图像,包含飞机、汽车、鸟、猫、鹿、狗、青蛙、马、船、卡车)。该数据集在torchvision中可以直接下载,适合验证模型效果。

4.1 创建项目结构

项目文件结构如下:

pytorch_image_classification/ ├── data/ # 数据集存放目录 ├── models/ │ └── cnn_model.py # CNN 模型定义 ├── utils/ │ └── dataset_utils.py # 数据读取与增强工具 ├── train.py # 训练脚本 ├── evaluate.py # 评估脚本 └── requirements.txt # 依赖清单

4.2 添加依赖

requirements.txt中写入以下内容:

torch>=1.13.0 torchvision>=0.14.0 numpy>=1.21.0 matplotlib>=3.5.0 pillow>=9.0.0

安装依赖:

pip install -r requirements.txt

4.3 定义 CNN 模型

models/cnn_model.py中定义一个用于图像分类的卷积神经网络。这个模型包含两组“卷积 + 激活 + 池化”结构,再接两层全连接层。

# 文件路径:models/cnn_model.py import torch.nn as nn class SimpleCNN(nn.Module): """ 一个简单的卷积神经网络,适用于 CIFAR-10 这类小尺寸图像分类。 结构说明: Conv2d(3, 32, 3) -> ReLU -> MaxPool2d(2) Conv2d(32, 64, 3) -> ReLU -> MaxPool2d(2) Flatten -> Linear(64*8*8, 512) -> ReLU -> Dropout -> Linear(512, 10) """ def __init__(self, num_classes=10): super(SimpleCNN, self).__init__() # 第一个卷积块 self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=1) self.relu1 = nn.ReLU(inplace=True) self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2) # 第二个卷积块 self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1) self.relu2 = nn.ReLU(inplace=True) self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2) # 全连接层 # CIFAR-10 图像尺寸为 32x32 # 经过两次池化后,特征图尺寸为 8x8,通道数为 64 self.fc1 = nn.Linear(in_features=64 * 8 * 8, out_features=512) self.relu3 = nn.ReLU(inplace=True) self.dropout = nn.Dropout(p=0.5) self.fc2 = nn.Linear(in_features=512, out_features=num_classes) def forward(self, x): # 卷积块1 x = self.conv1(x) x = self.relu1(x) x = self.pool1(x) # 卷积块2 x = self.conv2(x) x = self.relu2(x) x = self.pool2(x) # 展平 x = x.view(x.size(0), -1) # 全连接层 x = self.fc1(x) x = self.relu3(x) x = self.dropout(x) x = self.fc2(x) return x def create_model(num_classes=10): """创建模型实例,方便训练脚本调用。""" return SimpleCNN(num_classes=num_classes) if __name__ == "__main__": # 简单的模型测试 import torch model = create_model(num_classes=10) fake_input = torch.randn(2, 3, 32, 32) output = model(fake_input) print("模型输入形状:", fake_input.shape) print("模型输出形状:", output.shape)

这里的forward方法定义了数据在模型中的流向。调用模型时直接执行model(x)就会自动调用forward,这也是 PyTorch 动态计算图的体现,调试时可以直接打印中间张量形状。

4.4 准备数据读取与增强

utils/dataset_utils.py中封装数据加载逻辑。这里使用了torchvision.datasets.CIFAR10自动下载数据集,并对训练集应用随机翻转和标准化。

# 文件路径:utils/dataset_utils.py import torch from torch.utils.data import DataLoader from torchvision import datasets, transforms def get_transforms(train: bool = True): """ 构建数据预处理流程。 训练时使用随机水平翻转增强数据多样性;验证/测试时只做标准化。 """ if train: transform = transforms.Compose([ transforms.RandomHorizontalFlip(p=0.5), transforms.RandomCrop(32, padding=4), transforms.ToTensor(), transforms.Normalize( mean=[0.4914, 0.4822, 0.4465], std=[0.2023, 0.1994, 0.2010] ) ]) else: transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize( mean=[0.4914, 0.4822, 0.4465], std=[0.2023, 0.1994, 0.2010] ) ]) return transform def get_dataloader(batch_size=64, num_workers=2, train=True, download=True): """ 返回 CIFAR-10 数据集的 DataLoader。 """ transform = get_transforms(train=train) dataset = datasets.CIFAR10( root="./data", train=train, transform=transform, download=download ) dataloader = DataLoader( dataset, batch_size=batch_size, shuffle=train, num_workers=num_workers, pin_memory=True ) return dataloader

注意几个细节:

  • RandomCrop(32, padding=4)可以扩大训练样本的多样性,提升模型泛化能力。
  • Normalize使用的均值和标准差是 CIFAR-10 数据集的统计值,不是随意指定的。
  • pin_memory=True在 GPU 训练时能略微提升数据从内存拷贝到显存的速度。

4.5 编写训练脚本

train.py中完成训练逻辑。该脚本会完成以下任务:

  1. 加载训练数据和验证数据。
  2. 创建模型、损失函数、优化器。
  3. 循环训练多个 epoch。
  4. 每个 epoch 结束后输出训练精度和验证精度。
# 文件路径:train.py import torch import torch.nn as nn import torch.optim as optim from models.cnn_model import create_model from utils.dataset_utils import get_dataloader def train_one_epoch(model, dataloader, criterion, optimizer, device): """训练一个 epoch,返回平均 loss 和训练准确率。""" model.train() running_loss = 0.0 correct = 0 total = 0 for images, labels in dataloader: images = images.to(device) labels = labels.to(device) # 梯度清零 optimizer.zero_grad() # 前向传播 outputs = model(images) loss = criterion(outputs, labels) # 反向传播与参数更新 loss.backward() optimizer.step() # 统计 running_loss += loss.item() * images.size(0) _, predicted = torch.max(outputs, 1) total += labels.size(0) correct += (predicted == labels).sum().item() epoch_loss = running_loss / total epoch_acc = correct / total return epoch_loss, epoch_acc def evaluate(model, dataloader, criterion, device): """在验证集上评估模型,不计算梯度。""" model.eval() running_loss = 0.0 correct = 0 total = 0 with torch.no_grad(): for images, labels in dataloader: images = images.to(device) labels = labels.to(device) outputs = model(images) loss = criterion(outputs, labels) running_loss += loss.item() * images.size(0) _, predicted = torch.max(outputs, 1) total += labels.size(0) correct += (predicted == labels).sum().item() epoch_loss = running_loss / total epoch_acc = correct / total return epoch_loss, epoch_acc def main(): # 设备选择 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") print("使用设备:", device) # 超参数 batch_size = 64 learning_rate = 0.001 num_epochs = 10 num_classes = 10 # 数据加载 train_loader = get_dataloader( batch_size=batch_size, num_workers=2, train=True, download=True ) val_loader = get_dataloader( batch_size=batch_size, num_workers=2, train=False, download=True ) # 模型、损失函数、优化器 model = create_model(num_classes=num_classes).to(device) criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=learning_rate) # 训练循环 for epoch in range(1, num_epochs + 1): train_loss, train_acc = train_one_epoch( model, train_loader, criterion, optimizer, device ) val_loss, val_acc = evaluate(model, val_loader, criterion, device) print( f"Epoch [{epoch}/{num_epochs}] " f"训练Loss: {train_loss:.4f} 训练Acc: {train_acc:.4f} " f"验证Loss: {val_loss:.4f} 验证Acc: {val_acc:.4f}" ) # 保存训练好的模型 torch.save(model.state_dict(), "models/cnn_cifar10.pth") print("模型已保存到 models/cnn_cifar10.pth") if __name__ == "__main__": main()

4.6 运行与验证

在项目根目录执行:

python train.py

首次运行时,torchvision会自动下载 CIFAR-10 数据集到./data目录,耗时取决于网络情况。训练过程中会输出类似下面的日志:

Epoch [1/10] 训练Loss: 1.5876 训练Acc: 0.4245 验证Loss: 1.2734 验证Acc: 0.5478 Epoch [2/10] 训练Loss: 1.1548 训练Acc: 0.5882 验证Loss: 1.0412 验证Acc: 0.6384 Epoch [5/10] 训练Loss: 0.7693 训练Acc: 0.7301 验证Loss: 0.8123 验证Acc: 0.7165 Epoch [10/10] 训练Loss: 0.4452 训练Acc: 0.8432 验证Loss: 0.7421 验证Acc: 0.7503

以上数字是示例输出,实际结果会因随机种子、数据增强、训练轮数等因素略有差异。整体趋势是训练 Loss 不断下降,验证准确率逐步上升。

4.7 编写评估脚本并预测单张图片

训练完成后,编写evaluate.py加载训练好的模型,并在验证集上重新计算准确率,同时展示单张图片的预测结果。

# 文件路径:evaluate.py import torch import matplotlib.pyplot as plt from models.cnn_model import create_model from utils.dataset_utils import get_dataloader # CIFAR-10 类别名称 CLASS_NAMES = [ "airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", "ship", "truck" ] def predict_image(model, image_tensor, device): """输入一张图像的张量,返回预测类别名称和置信度。""" model.eval() with torch.no_grad(): image_tensor = image_tensor.unsqueeze(0).to(device) # 增加 batch 维度 outputs = model(image_tensor) probabilities = torch.softmax(outputs, dim=1) confidence, predicted_idx = torch.max(probabilities, dim=1) class_name = CLASS_NAMES[predicted_idx.item()] confidence = confidence.item() return class_name, confidence def main(): device = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 加载模型 model = create_model(num_classes=10).to(device) model.load_state_dict(torch.load("models/cnn_cifar10.pth", map_location=device)) print("模型加载完成") # 加载验证集 val_loader = get_dataloader( batch_size=64, num_workers=2, train=False, download=True ) # 计算整体准确率 correct = 0 total = 0 model.eval() with torch.no_grad(): for images, labels in val_loader: images = images.to(device) labels = labels.to(device) outputs = model(images) _, predicted = torch.max(outputs, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print(f"验证集准确率: {correct / total:.4f}") # 对验证集第一张图进行预测 data_iter = iter(val_loader) images, labels = next(data_iter) image_tensor = images[0].cpu() true_label = CLASS_NAMES[labels[0].item()] predicted_label, confidence = predict_image(model, image_tensor, device) print(f"真实标签: {true_label}, 预测标签: {predicted_label}, 置信度: {confidence:.4f}") # 显示图片 # 注意需要反标准化才能正常显示 mean = torch.tensor([0.4914, 0.4822, 0.4465]).view(3, 1, 1) std = torch.tensor([0.2023, 0.1994, 0.2010]).view(3, 1, 1) img_show = image_tensor * std + mean img_show = img_show.permute(1, 2, 0).numpy() plt.imshow(img_show) plt.title(f"真实: {true_label}\n预测: {predicted_label} ({confidence:.2f})") plt.axis("off") plt.show() if __name__ == "__main__": main()

执行:

python evaluate.py

预期输出包含整体验证集准确率、单张图片的真实标签和预测标签,并弹出图片显示窗口。

4.8 训练过程可视化

为了更直观地观察训练过程,可以在训练脚本中记录每个 epoch 的 Loss 和准确率,然后绘制曲线。这里给出一个简单的扩展示例。

# 文件路径:utils/plot_utils.py import matplotlib.pyplot as plt def plot_training_history(history): """绘制训练和验证的 Loss、准确率曲线。 history 示例: { "train_loss": [1.5, 1.2, 0.9], "val_loss": [1.4, 1.1, 0.8], "train_acc": [0.4, 0.5, 0.6], "val_acc": [0.45, 0.55, 0.65] } """ epochs = range(1, len(history["train_loss"]) + 1) plt.figure(figsize=(12, 4)) plt.subplot(1, 2, 1) plt.plot(epochs, history["train_loss"], label="Train Loss") plt.plot(epochs, history["val_loss"], label="Val Loss") plt.xlabel("Epoch") plt.ylabel("Loss") plt.title("Loss Curve") plt.legend() plt.subplot(1, 2, 2) plt.plot(epochs, history["train_acc"], label="Train Acc") plt.plot(epochs, history["val_acc"], label="Val Acc") plt.xlabel("Epoch") plt.ylabel("Accuracy") plt.title("Accuracy Curve") plt.legend() plt.tight_layout() plt.show()

如果想在训练过程中启用该可视化,只需要在train.py中用字典记录每个 epoch 的指标,训练结束后调用plot_training_history即可。

5. 常见问题与排查思路

在实际运行 PyTorch 图像分类代码时,环境、版本、数据格式都可能引发报错。以下整理了几个高频问题。

问题现象常见原因解决思路
torch.cuda.is_available()返回 False显卡驱动版本过旧、PyTorch 与 CUDA 版本不匹配运行nvidia-smi查看驱动支持的 CUDA 版本,更换对应版本的 PyTorch
训练时报CUDA out of memorybatch size 过大、输入图像尺寸过大、其他进程占用显存减小 batch size、降低图像分辨率、释放无用缓存、缩小模型通道数
RuntimeError: Expected input batch_size to match target模型输出类别数与标签类别数不一致检查num_classes是否和数据集类别数一致
FileNotFoundError下载数据集失败网络问题或数据集下载地址无法访问手动下载数据集放到./data目录,或调整download=False后指定本地路径
训练 Loss 不下降学习率过大或过小、数据没有标准化、模型结构有问题调整学习率、检查数据预处理、确认模型输出后接 CrossEntropyLoss
num_workers设置过大导致报错Windows 系统下多进程数据加载不稳定num_workers改为 0 或 2
加载模型报错Missing key(s) in state_dict保存的是state_dict而不是完整模型,或者模型结构不一致保存时使用torch.save(model.state_dict()),加载时先创建同结构模型再load_state_dict

5.1 CUDA 不可用的排查顺序

如果你遇到torch.cuda.is_available()False,按照以下顺序排查:

第一步,确认机器有 Nvidia 显卡,并运行nvidia-smi,如果命令不存在或报错,说明没有安装显卡驱动或驱动异常。

第二步,确认 PyTorch 是否为 GPU 版本。CPU 版本的 PyTorch 无法使用 CUDA,需要通过安装命令确认。

第三步,检查 PyTorch 编译时的 CUDA 版本是否与驱动兼容。通常驱动版本较新时,兼容性更好。

5.2 数据集下载失败的处理方式

CIFAR-10 数据集因为托管在国外服务器,部分地区下载可能非常慢或失败。可以手动从数据集官网下载cifar-10-python.tar.gz,放在./data目录下,并确保文件名称正确。也可以使用镜像源下载后替换,但要注意解压后的目录结构必须和torchvision期望的一致。

6. 最佳实践与工程建议

训练一个图像分类模型只是第一步,真正在项目中稳定运行,还需要考虑数据、模型、训练、部署等多个方面。

6.1 数据层面的建议

  • 数据增强尽量丰富。随机裁剪、翻转、色彩抖动、MixUp 等技巧都可以提升模型泛化能力,但要注意增强强度不能改变语义信息。
  • 训练集和验证集的数据分布要尽量一致。如果训练数据来自网络图片、验证数据来自手机拍摄图片,准确率往往会明显下降。
  • 使用标准化时,均值和标准差最好从训练集统计得到,而不是随意指定。

6.2 模型层面的建议

  • 优先选择成熟的预训练模型。在数据量较小时,使用torchvision.models.resnet18等预训练权重做迁移学习,效果通常优于从零训练的小网络。
  • 记录每次实验的配置。包括随机种子、学习率、batch size、数据增强策略、模型结构。建议在代码中固定随机种子,方便复现。
import random import numpy as np import torch def set_seed(seed=42): random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) torch.cuda.manual_seed_all(seed) torch.backends.cudnn.deterministic = True torch.backends.cudnn.benchmark = False

6.3 工程层面的建议

  • 使用 TensorBoard 或torch.utils.tensorboard记录训练曲线,比终端打印日志更适合长周期训练。
  • 保存模型时同时保存训练配置、标签映射关系和字典信息,方便部署时使用。
  • 训练中途定期保存 checkpoint(包含模型参数、优化器状态、epoch 数),避免因断电或显存异常导致训练白跑。
# 示例:保存 checkpoint checkpoint = { "epoch": epoch, "model_state_dict": model.state_dict(), "optimizer_state_dict": optimizer.state_dict(), "best_val_acc": best_val_acc, } torch.save(checkpoint, f"checkpoints/checkpoint_epoch_{epoch}.pth")

6.4 安全与生产环境注意事项

  • 在生产环境使用模型做推理时,要先验证输入图像的尺寸、通道数、像素范围是否符合预处理要求。
  • 涉及敏感数据或私有数据的模型训练,要遵守数据合规要求,不要使用未授权的数据。
  • 如果需要更新模型,建议先在验证集和测试集上评估新模型效果,再通过灰度发布逐步替换线上模型,避免直接全量上线导致业务波动。
  • 在服务器上训练时,尽量使用虚拟环境隔离依赖,避免多个项目之间因为 PyTorch 版本不同产生冲突。

6.5 性能优化建议

  • 如果数据集很大,可以先用小数据集跑通代码,再全量训练,减少调试时间。
  • GPU 训练时,尽量把数据加载做成异步,DataLoadernum_workers按 CPU 核心数合理设置,避免 GPU 等待数据。
  • 混合精度训练可以在部分场景下加速并节省显存,PyTorch 提供torch.cuda.amp可以简化实现。

7. 总结与扩展方向

使用卷积神经网络执行图像分类,本质上包含数据准备、模型构建、训练评估、部署推理几个环节。本文通过一个完整示例,演示了使用 PyTorch 加载 CIFAR-10 数据集、构建 CNN 模型、训练并评估的完整流程,同时整理了环境配置和常见报错的排查思路。

如果想把图像分类效果进一步提升,可以从以下几个方向继续学习:

  • 使用 ResNet、DenseNet、EfficientNet 等更深的网络结构。
  • 使用迁移学习,加载 ImageNet 预训练权重,将最后一个全连接层替换为自定义分类头。
  • 引入学习率调度器(如CosineAnnealingLRReduceLROnPlateau),让训练收敛更稳定。
  • 使用更复杂的数据增强策略,如 AutoAugment、RandAugment。
  • 学习模型解释性工具(如 Grad-CAM),可视化模型关注区域,辅助分析误分类原因。

动手实践是掌握深度学习的最佳方式。建议先跑通本文代码,再尝试修改模型结构和训练策略,相信你会对 CNN 的图像分类原理有更深的理解。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询