PyTorch实战:从零构建卷积神经网络(CNN)精准分类Fashion-MNIST时尚单品

发布时间:2026/7/5 11:12:42

PyTorch实战:从零构建卷积神经网络(CNN)精准分类Fashion-MNIST时尚单品 1. 认识Fashion-MNIST数据集与CNN的优势Fashion-MNIST数据集是图像分类领域的经典基准数据集由德国时尚科技公司Zalando Research发布。它包含60,000张训练图像和10,000张测试图像每张都是28×28像素的灰度图涵盖T恤、裤子、外套等10类时尚单品。这个数据集常被用来测试机器学习算法的性能相当于时尚界的Hello World。与全连接神经网络相比卷积神经网络CNN在处理图像数据时具有三大先天优势局部感知机制CNN通过卷积核只关注图像的局部区域这模仿了人类视觉系统的感受野特性。比如识别T恤领口时不需要分析整张图片。权重共享同一个卷积核会扫描整张图片大幅减少参数量。一个5×5的卷积核在全图滑动时参数量只有25个而全连接层对应位置的参数量可能是784个28×28。平移不变性无论图案出现在图像哪个位置CNN都能识别。就像无论logo印在T恤胸口还是下摆我们都能认出品牌。实测表明在Fashion-MNIST上简单CNN模型的准确率能达到92%以上而全连接网络通常在89%左右徘徊。这种差距在处理更复杂的图像时会更加明显。2. 环境准备与数据加载推荐使用Python 3.8和PyTorch 1.12环境。如果使用GPU加速需要安装CUDA 11.6以上版本。以下是关键依赖import torch import torchvision from torch import nn from torch.utils.data import DataLoader import matplotlib.pyplot as plt数据加载时需要注意几个关键点# 数据预处理管道 transform transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,)) # 单通道归一化 ]) # 下载数据集 train_set torchvision.datasets.FashionMNIST( root./data, trainTrue, downloadTrue, transformtransform ) test_set torchvision.datasets.FashionMNIST( root./data, trainFalse, downloadTrue, transformtransform ) # 创建数据加载器 train_loader DataLoader(train_set, batch_size64, shuffleTrue) test_loader DataLoader(test_set, batch_size64, shuffleFalse)这里特别说明下Normalize的参数(0.5,)表示单通道均值0.5标准差0.5。计算过程是将原始0-1之间的像素值x做变换(x-0.5)/0.5最终数值范围变为[-1,1]。这种归一化能加速模型收敛。可视化一张训练样本的代码classes [T恤, 裤子, 套衫, 裙子, 外套, 凉鞋, 衬衫, 运动鞋, 包, 靴子] image, label next(iter(train_loader)) plt.imshow(image[0].squeeze(), cmapgray) plt.title(classes[label[0]]) plt.show()3. 构建CNN网络结构我们设计一个包含两个卷积层的CNN结构如下表所示层级类型参数配置输出尺寸作用说明卷积层ReLUin1, out16, kernel5(16,24,24)提取底层特征如边缘最大池化kernel2, stride2(16,12,12)降维增强平移不变性卷积层ReLUin16, out32, kernel5(32,8,8)提取高级特征如纹理最大池化kernel2, stride2(32,4,4)进一步降维全连接层in512, out128(128,)非线性组合特征输出层in128, out10(10,)输出分类概率对应的PyTorch实现class FashionCNN(nn.Module): def __init__(self): super().__init__() self.conv1 nn.Sequential( nn.Conv2d(1, 16, 5), nn.ReLU(), nn.MaxPool2d(2) ) self.conv2 nn.Sequential( nn.Conv2d(16, 32, 5), nn.ReLU(), nn.MaxPool2d(2) ) self.fc nn.Sequential( nn.Linear(32*4*4, 128), nn.ReLU(), nn.Linear(128, 10) ) def forward(self, x): x self.conv1(x) x self.conv2(x) x x.view(x.size(0), -1) # 展平 return self.fc(x)这里有几个设计细节值得注意卷积后立即接ReLU激活函数增加非线性最大池化用2×2窗口每次尺寸减半第一个全连接层后也加入ReLU最终输出层不需要softmax因为后续会使用CrossEntropyLoss4. 模型训练与调优技巧初始化模型和优化器model FashionCNN() criterion nn.CrossEntropyLoss() optimizer torch.optim.Adam(model.parameters(), lr0.001)训练循环中加入以下关键技巧学习率预热前5个epoch使用线性增长的学习率warmup_epochs 5 for epoch in range(epochs): if epoch warmup_epochs: lr 0.001 * (epoch 1) / warmup_epochs for param_group in optimizer.param_groups: param_group[lr] lr梯度裁剪防止梯度爆炸torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm1.0)模型验证每个epoch后在测试集评估model.eval() with torch.no_grad(): correct 0 total 0 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}%)早停机制当验证损失连续3个epoch不下降时停止训练实际训练时可能会出现的问题如果训练准确率远高于测试准确率可能是过拟合可以增加Dropout层如果损失值震荡严重可以调小学习率或增大batch size如果显存不足可以减小batch size或使用梯度累积5. 模型评估与结果分析训练完成后我们可以在测试集上评估模型性能confusion_matrix torch.zeros(10, 10) with torch.no_grad(): for images, labels in test_loader: outputs model(images) _, preds torch.max(outputs, 1) for t, p in zip(labels.view(-1), preds.view(-1)): confusion_matrix[t.long(), p.long()] 1绘制混淆矩阵可以帮助我们发现模型的薄弱环节。例如衬衫和T恤、外套和套衫之间容易混淆因为这些类别本身就有相似特征。为了提高模型性能可以尝试以下改进增加数据增强随机旋转、平移等使用更深的网络结构如ResNet加入注意力机制使用标签平滑等正则化技术最终一个精心调参的CNN模型在Fashion-MNIST上可以达到93-95%的准确率。相比全连接网络CNN不仅准确率更高而且参数量更少训练速度更快。

相关新闻