# 导入PyTorch核心库用于构建和训练神经网络 import torch # 导入优化器模块用于更新模型参数 import torch.optim as optim # 导入神经网络层模块用于搭建网络结构 import torch.nn as nn # 导入激活函数、损失函数等功能性API import torch.nn.functional as F # 导入数据集和数据预处理工具 from torchvision import datasets, transforms # 导入数值计算库 import numpy as np # 导入绘图库用于绘制损失曲线 import matplotlib.pyplot as plt # 【超参数设置】 # 输入图像的尺寸MNIST数据集是28x28像素 input_size 28 # 分类类别数量0-9共10个数字 num_classes 10 # 训练轮数将整个训练集完整训练几遍 num_epochs 10 # 批次大小每次喂给模型多少张图片一起训练 batch_size 10 # 【加载MNIST数据集】 # 加载训练数据集 train_dataset datasets.MNIST( root./data, # 数据集存放路径 trainTrue, # True表示加载训练集 transformtransforms.ToTensor(), # 将图片转换为PyTorch张量 downloadTrue # 如果本地没有数据集自动从网上下载 ) # 加载测试数据集 test_dataset datasets.MNIST( root./data, # 数据集存放路径 trainFalse, # False表示加载测试集 transformtransforms.ToTensor() # 将图片转换为PyTorch张量 ) # 【构建数据加载器】 # 训练集加载器按批次加载数据并打乱顺序 train_loader torch.utils.data.DataLoader( datasettrain_dataset, # 指定要加载的数据集 batch_sizebatch_size, # 每个批次包含的样本数量 shuffleTrue # 打乱数据顺序提高模型泛化能力 ) # 测试集加载器 test_loader torch.utils.data.DataLoader( datasettest_dataset, batch_sizebatch_size, shuffleTrue ) # 【定义CNN神经网络模型】 class CNN(nn.Module): # 定义CNN类继承PyTorch的nn.Module def __init__(self): super(CNN, self).__init__() # 初始化父类固定写法 # 第一个卷积模块卷积激活池化 self.conv1 nn.Sequential( nn.Conv2d( in_channels1, # 输入通道数灰度图为1 out_channels16, # 输出通道数生成16张特征图 kernel_size5, # 卷积核大小5x5 stride1, # 卷积步长为1 padding2 # 填充2圈0保持输出尺寸不变 ), nn.ReLU(), # 激活函数增加非线性 nn.MaxPool2d(kernel_size2) # 最大池化尺寸缩小一半 ) # 第二个卷积模块 self.conv2 nn.Sequential( nn.Conv2d(16, 32, 5, 1, 2), # 输入16通道→输出32通道 nn.ReLU(), nn.MaxPool2d(2) # 尺寸再缩小一半 ) # 全连接层将卷积特征映射到10个分类结果 self.out nn.Linear(32 * 7 * 7, 10) # 前向传播定义数据流向 def forward(self, x): x self.conv1(x) # 输入经过第一个卷积模块 x self.conv2(x) # 经过第二个卷积模块 x x.view(x.size(0), -1) # 展平特征图适配全连接层 output self.out(x) # 全连接层输出分类结果 return output # 【初始化模型、优化器、损失函数】 model CNN() # 创建CNN模型实例 optimizer optim.Adam(model.parameters(), lr0.001) # Adam优化器 loss_func nn.CrossEntropyLoss() # 交叉熵损失函数用于分类任务 # 【开始训练模型】 print(开始训练...) train_loss_list [] # 保存每轮的平均损失用于绘图 # 循环训练指定轮数 for epoch in range(num_epochs): total_loss 0 # 累计当前轮的总损失 # 遍历训练集中的每一个批次 for i, (images, labels) in enumerate(train_loader): output model(images) # 前向传播计算模型输出 loss loss_func(output, labels) # 计算损失值 optimizer.zero_grad() # 清空上一步的梯度 loss.backward() # 反向传播计算梯度 optimizer.step() # 更新模型参数 total_loss loss.item() # 累加损失 avg_loss total_loss / len(train_loader) # 计算本轮平均损失 train_loss_list.append(avg_loss) # 保存损失 print(fEpoch [{epoch1}/{num_epochs}] 平均损失: {avg_loss:.4f}) # 【测试模型准确率】 print(\n开始测试...) correct 0 # 预测正确的样本数 total 0 # 总样本数 with torch.no_grad(): # 测试时不需要计算梯度节省资源 for images, labels in test_loader: outputs model(images) # 模型预测 _, predicted torch.max(outputs.data, 1) # 获取预测类别 total labels.size(0) # 累计总样本数 correct (predicted labels).sum().item() # 累计正确数 # 计算并打印准确率 print(f测试集准确率: {100 * correct / total:.2f}%) # 【绘制训练损失曲线】 plt.plot(train_loss_list, labelTraining Loss) plt.xlabel(Epoch) plt.ylabel(Loss) plt.title(训练损失变化) plt.legend() plt.show()超参数 人工手动设置的参数直接调用库内置 MNIST 数据集无需自己准备图片文件。# 导入PyTorch的核心库提供张量计算、自动求导等基础功能 import torch # 导入PyTorch的优化器模块用于更新神经网络的权重参数 import torch.optim as optim # 导入PyTorch的神经网络层模块包含卷积层、全连接层等网络组件 import torch.nn as nn # 导入PyTorch的函数式接口包含激活函数、损失函数等工具 import torch.nn.functional as F # 从torchvision库中导入数据集工具和数据预处理工具 from torchvision import datasets, transforms # 导入numpy数值计算库用于数组、矩阵相关计算 import numpy as np # 导入matplotlib的pyplot模块用于绘制图表可视化数据 import matplotlib.pyplot as plt # 定义输入图像的尺寸MNIST数据集的图片大小为28*28像素 input_size 28 # 定义分类的类别数量手写数字识别分为0-9共10个类别 num_classes 10 # 定义训练的总轮数代表将整个训练集完整训练10次 num_epochs 10 # 定义批次大小每次训练时输入模型的样本数量为10 batch_size 10 # 加载MNIST训练数据集 train_dataset datasets.MNIST( # 指定数据集的存储根目录为当前文件夹下的data文件夹 root./data, # 设置为True表示加载训练集数据 trainTrue, # 数据预处理将PIL图片格式转换为PyTorch专用的张量格式 transformtransforms.ToTensor(), # 设置为True如果本地没有数据集自动从官方服务器下载 downloadTrue ) # 加载MNIST测试数据集 test_dataset datasets.MNIST( # 测试集存储路径与训练集一致 root./data, # 设置为False表示加载测试集数据 trainFalse, # 测试集同样需要转换为张量格式 transformtransforms.ToTensor(), ) # 创建训练集的数据加载器用于批量读取数据 train_loader torch.utils.data.DataLoader( # 指定需要加载的训练数据集 datasettrain_dataset, # 设置每个批次包含的样本数使用上方定义的batch_size batch_sizebatch_size, # 设置为True训练时打乱数据顺序防止模型记忆数据顺序 shuffleTrue ) # 创建测试集的数据加载器 test_loader torch.utils.data.DataLoader( # 指定需要加载的测试数据集 datasettest_dataset, # 测试批次大小与训练保持一致 batch_sizebatch_size, # 测试集打乱顺序保证测试的随机性 shuffleTrue ) # 定义CNN神经网络类继承自nn.ModulePyTorch所有模型的基类 class CNN(nn.Module): # 类的初始化函数定义网络的层结构 def __init__(self): # 调用父类nn.Module的初始化方法固定语法 super(CNN, self).__init__() # 定义第一个卷积模块使用Sequential组合多层网络 self.conv1 nn.Sequential( # 二维卷积层用于提取图像特征 nn.Conv2d( # 输入通道数MNIST是灰度图通道数为1 in_channels1, # 输出通道数卷积后生成16张特征图 out_channels16, # 卷积核的尺寸为5x5 kernel_size5, # 卷积核移动的步长为1 stride1, # 图像边缘填充2圈0保证卷积后尺寸不变 padding2, ), # ReLU激活函数增加网络的非线性表达能力 nn.ReLU(), # 二维最大池化层池化核大小2x2将特征图尺寸缩小一半 nn.MaxPool2d(kernel_size2, ), ) # 定义第二个卷积模块 self.conv2 nn.Sequential( # 二维卷积层输入16通道输出32通道卷积核5x5 nn.Conv2d(16, 32, 5, 1, 2), # ReLU激活函数 nn.ReLU(), # 最大池化层尺寸再次缩小一半 nn.MaxPool2d(kernel_size2), ) # 定义全连接层将卷积特征展平后映射为10分类结果 self.out nn.Linear(32*7*7, 10) # 前向传播函数定义数据在网络中的流动路径 def forward(self,x): # 输入数据经过第一个卷积模块 x self.conv1(x) # 数据经过第二个卷积模块 x self.conv2(x) # 将特征图展平batch维度保留其余维度合并为一维 x x.view(x.size(0), -1) # 数据传入全连接层得到最终的分类输出 output self.out(x) # 返回模型的输出结果 return output # 实例化CNN模型创建一个可以训练的网络对象 model CNN() # 定义Adam优化器传入模型参数和学习率lr0.001 optimizer optim.Adam(model.parameters(), lr0.001) # 定义交叉熵损失函数适用于多分类任务 loss_func nn.CrossEntropyLoss() # 打印训练开始的提示信息 print(开始训练...) # 创建空列表用于存储每一轮训练的平均损失值 train_loss_list [] # 外层循环遍历每一个训练轮数 for epoch in range(num_epochs): # 初始化当前轮次的总损失为0 total_loss 0 # 内层循环遍历训练集中的每一个批次数据 for i, (images, labels) in enumerate(train_loader): # 前向传播将图片输入模型得到预测输出 output model(images) # 计算损失值对比预测输出和真实标签 loss loss_func(output, labels) # 清空上一步的梯度防止梯度累加 optimizer.zero_grad() # 反向传播计算损失对模型参数的梯度 loss.backward() # 优化器更新模型的权重参数 optimizer.step() # 将当前批次的损失值累加到总损失中 total_loss loss.item() # 计算当前轮次的平均损失总损失 / 批次数量 avg_loss total_loss / len(train_loader) # 将平均损失添加到列表中 train_loss_list.append(avg_loss) # 打印当前轮次的训练信息 print(fEpoch [{epoch1}/{num_epochs}] 平均损失: {avg_loss:.4f}) # 打印测试开始的提示信息 print(\n开始测试...) # 初始化预测正确的样本数量为0 correct 0 # 初始化测试集的总样本数量为0 total 0 # torch.no_grad()测试阶段关闭梯度计算节省内存和计算资源 with torch.no_grad(): # 遍历测试集中的每一个批次 for images, labels in test_loader: # 将测试图片输入模型得到输出 outputs model(images) # 获取预测结果取输出中概率最大的类别 _, predicted torch.max(outputs.data, 1) # 累加当前批次的样本总数 total labels.size(0) # 统计预测正确的样本数量并累加 correct (predicted labels).sum().item() # 计算并打印模型在测试集上的准确率 print(f测试集准确率: {100 * correct / total:.2f}%) # 绘制训练损失曲线x轴为轮数y轴为损失值 plt.plot(train_loss_list, labelTraining Loss) # 设置x轴标签 plt.xlabel(Epoch) # 设置y轴标签 plt.ylabel(Loss) # 设置图表标题 plt.title(训练损失变化) # 显示图例 plt.legend() # 展示绘制的图表 plt.show()