ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

【深度学习项目实战·13】服装图像分类:在相同条件下比较MLP与CNN

【深度学习项目实战·13】服装图像分类:在相同条件下比较MLP与CNN

文章目录

    • 01 本篇要解决什么问题
    • 02 背景:同样是28×28,分类难点已经改变
    • 03 实操:设计一个有边界的比较实验
      • (1)先下载,沿用固定划分
      • (2)MLP先把图像展平成向量
      • (3)CNN保留二维邻域信息
      • (4)控制能控制的条件
      • (5)比较指标,同时查看错误样本
      • (6)从小规模检查过渡到完整比较
    • 04 一个具体例子:一条命令训练两个模型
    • 05 常见问题与自测
    • 06 本篇回顾与下一步

01 本篇要解决什么问题

跑通MNIST以后,很容易想试试更大的模型。但一个模型的准确率比另一个高,究竟是结构带来的,还是训练轮数、样本划分或数据增强不同?

本篇使用Fashion-MNIST,让一个MLP和一个小CNN完成同一任务。除了训练,还要把“怎样比较”这件事做清楚。

  • 本篇关键词:Fashion-MNIST、MLP、CNN、公平比较、错分分析。
  • 完成标志:用同一份划分训练两个模型,分别保存权重和结果,形成可复查的比较。
  • 运行约定:保留完整examples目录,命令从练习根目录执行;依赖沿用第12篇。

02 背景:同样是28×28,分类难点已经改变

Fashion-MNIST包含60000张训练图和10000张测试图,每张为28×28灰度图,共10类服装。发布方提供文件、校验和及类别说明,见Fashion-MNIST作者仓库。

类别包括T恤、裤子、套头衫、连衣裙、外套、凉鞋、衬衫、运动鞋、包和短靴。低分辨率下,某些服装轮廓接近,单靠“整体像一个形状”可能不够。

这里可以沿用数字识别的数据流程,但不能沿用数字类别的解释。项目必须把真实的类别映射随权重一起保存。

03 实操:设计一个有边界的比较实验

(1)先下载,沿用固定划分

python examples/download_data.py--dataset fashion--datadata

代码使用发布方GitHub数据文件作为优先镜像,并保留作者原始下载站作为备用,仍检查原始文件校验和。

官方训练部分按类别划为约54000训练、6000验证,官方10000测试保留。两个模型共用同一份索引;如果缩小数据规模,也共用同一份子集。

(2)MLP先把图像展平成向量

下面的模型把784个像素当作输入特征,经过一个128维隐藏层,再输出10个类别分数。

fromtorchimportnnclassFashionMLP(nn.Module):def__init__(self):super().__init__()self.layers=nn.Sequential(nn.Flatten(),nn.Linear(28*28,128),nn.ReLU(),nn.Linear(128,10))defforward(self,x):returnself.layers(x)

它有101770个参数,计算直接,适合作为起点。但展平之后,网络没有显式采用卷积中的局部连接与权重共享机制。

(3)CNN保留二维邻域信息

CNN使用第12篇的GrayCNN(classes=10):两次卷积与池化后接分类头。它在不同位置重复使用卷积核,有机会利用局部边缘和纹理。

本版CNN有114314个参数,与MLP处于相近量级,但并不完全相同。因此这个实验是两个具体配置的比较,不能解释成“只改变一种因素、其余完全相等”的严格结构消融。

卷积带来的先验也不代表任何设置下都必然更好。训练是否充分、优化器是否合适、样本规模多大,都可能改变结论。

(4)控制能控制的条件

条件本篇约定
数据划分、使用数量两个模型完全相同
预处理灰度浮点、统一缩放与标准化
随机增强两个模型均不使用
优化器Adam,相同初始学习率
batch size与轮数使用同一组参数
批次顺序每个模型重新设置同一数据加载随机种子
最优权重各自按验证损失最小选择

模型初始化使用相同种子,方便重复实验,但不同结构不会因此得到一一对应的相同初始权重。这里先做一次可复查的比较;如果要形成更可靠结论,还应在多个种子下报告均值与波动。

(5)比较指标,同时查看错误样本

总体准确率适合快速观察,但建议同时看macro-F1和逐类召回率。某个类别预测困难时,混淆矩阵能帮助定位它通常被分成哪一类。

不要预先认定某几类一定混淆。先从本次的predictions.csv和错分图中找到证据,再回看这些类别的轮廓、局部纹理和遮挡情况。

不同模型的计算成本也值得记录。本篇输出参数量与本次总耗时;总耗时包含评价和文件输出,不能直接当作纯推理延迟。需要比较部署速度时,应另做同设备、同批次和统一预热的测量。

(6)从小规模检查过渡到完整比较

python examples/compare_fashion.py--epochs 1--limit-train1024--limit-val256--limit-test256

正式使用完整划分时:

python examples/compare_fashion.py--epochs 5--output artifacts/13_fashion_full

一轮小样本结果主要确认两个流程都正常,不能据此给出结构优劣的普遍结论。即使固定轮数相同,两个模型也未必都已充分收敛,应结合训练与验证曲线解释。

图:本篇原创比较设计图,列出两个模型共享与不同的部分。

04 一个具体例子:一条命令训练两个模型

主入口是examples/compare_fashion.py。数据只加载和划分一次,再分别创建模型、重置训练随机状态并保存到独立子目录。

"""Chapter 13: compare two models using identical splits and training budgets."""importcopyfromproject_commonimportparser_for,validate_args,seed_everything,run_experiment,write_jsonfromproject_dataimportload_data,preprocessingfromproject_modelsimportbuild_modeldefmain():parser=parser_for(__doc__,"artifacts/13_fashion",epochs=5,batch_size=128)args=parser.parse_args()validate_args(parser,args)data,classes,manifest=load_data("fashion",args)results={}forname,specin[("mlp",{"kind":"fashion_mlp"}),("cnn",{"kind":"gray_cnn","classes":10})]:seed_everything(args.seed,args.threads)current=copy.copy(args)current.output=args.output/name result=run_experiment(build_model(spec),spec,data,classes,manifest,preprocessing("fashion"),current)results[name]={"parameters":result["parameters"],"best_epoch":result["best_epoch"],"test_accuracy":result["test"]["accuracy"],"test_macro_f1":result["test"]["macro_f1"]}write_json(args.output/"comparison.json",results)print(results)if__name__=="__main__":main()

输出目录中的mlp与cnn分别保存最优权重、训练历史、混淆矩阵数据和预测图。顶层comparison.json汇总两者参数量、最优轮次、测试准确率与macro-F1。

python examples/visualize_run.py--run artifacts/13_fashion/mlp python examples/visualize_run.py--run artifacts/13_fashion/cnn python examples/predict_image.py--checkpoint artifacts/13_fashion/cnn/best.pt--imagedata/my_clothing.png

单图输入也应尽量接近数据集的灰度、背景和主体占比。真实商品照片涉及更复杂背景,后面第15篇会用真实彩色图与迁移学习继续处理这种差异。

公共函数和模型完整代码见配套工程及公共代码附录。本篇不填写预设的“CNN比MLP高几个百分点”,比较结果以实际输出为准。

05 常见问题与自测

问题1:给两个模型设同一个seed,实验就完全公平了吗?

还要控制划分、样本数、预处理、训练预算和选择规则。不同结构的初始化也不会因同一个seed变成相同参数。

问题2:为什么这次不先给CNN加很多数据增强?

先让两个起点共享输入条件。后续要研究增强作用,可以固定模型再单独比较有无增强。

问题3:参数量接近,就代表计算量和显存相同吗?

不代表。中间特征、运算方式和输入尺寸也会影响成本,不能只凭参数量判断运行速度。

问题4:能不能只把测试结果更好的模型叫“最佳模型”?

本篇报告两个已确定配置的测试结果。若还要据此不断修改和选择方案,就需要保留新的独立最终评价数据。

问题5:测试macro-F1和Accuracy为什么不同?

它们统计的角度不同。macro-F1逐类计算再等权平均,更容易反映具体类别的短板。

06 本篇回顾与下一步

这次项目增加的能力,是把模型比较组织成一个可解释的实验。结果文件负责记录数值,数据划分和训练约定负责让这些数值有可比较的含义。

中文常见英文或写法
多层感知机MLP
归纳偏置Inductive Bias
宏平均F1Macro-F1
对照实验Controlled Comparison

下一篇进入32×32彩色自然图像,用适配小图的ResNet学习更复杂的特征。

参考与延伸阅读

  • Torchvision FashionMNIST接口
  • PyTorch可复现性说明
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进