Fashion-MNIST 图像分类实战:TensorFlow 五模型对比与 Flask 可视化

Fashion-MNIST 图像分类实战:TensorFlow 五模型对比与 Flask 可视化

**本文源码+数据集:**通过网盘分享的文件:服装图像分类模型对比与可视化系统研究-相关资料.zip

链接: https://pan.baidu.com/s/1r_xZ41SJf2DYwOucrgnvpw 提取码: cp52

**本文实验结果:**在相同的 10 000 张 Fashion-MNIST 测试图像上,CNN+BN+Dropout 获得 90.60% 准确率和 0.9065 宏平均 F1;基础 CNN 以 41 866 个参数达到 90.48%。当前数据增强模型训练 60 轮后准确率为 86.70%,没有超过未增强模型。本文给出数据划分、模型结构、运行步骤与错误分析,说明这些数字如何得到,以及哪些结论仍需重复实验验证。

实验结果核对日期:2026 年 10 月 20 日。本文面向已掌握 Python 基础、希望完成图像分类课程设计或毕业设计的读者。

本次结果更新补齐了数据增强 CNN 的详细评估,并重新生成全部五模型评估与 17 张静态图表。数据来源为项目保存的模型、训练历史和评估 JSON,属于本项目单次训练记录,不是公开排行榜成绩。

1. Fashion-MNIST 五种模型的实际效果如何?

本项目中,CNN+BN+Dropout 的测试准确率最高,但基础 CNN 的参数规模更小。两者准确率仅相差 0.12 个百分点,相当于 10 000 张测试图像中正确样本数相差 12。没有多随机种子重复实验时,这个差值不足以证明前者具有稳定优势。

模型 测试准确率 测试损失 宏平均 F1 错误数 参数量 累计训练时间
MLP 基线 88.37% 0.4639 0.8829 1 163 235 146 122.2 秒
基础 CNN 90.48% 0.4192 0.9043 952 41 866 251.8 秒
三层 CNN 90.23% 0.3976 0.9010 977 26 826 202.5 秒
CNN+BN+Dropout 90.60% 0.2746 0.9065 940 98 474 606.2 秒
CNN+数据增强 86.70% 0.3881 0.8665 1 330 98 474 2 075.6 秒

前四个模型训练 20 轮,增强模型训练 60 轮。训练时间取每轮训练与验证过程的累计耗时,不包含完整进程初始化、数据下载和图表生成。由于没有记录完整 CPU 型号、线程设置与后台负载,表中耗时只描述本次运行条件。

如果希望先建立可运行、开销较低的卷积基线,基础 CNN 值得优先复现;如果重点分析正则化配置的分类表现,可以进一步研究 CNN+BN+Dropout。部署选型还需要另外测试推理延迟和内存占用,训练耗时不能代替推理速度。

2. Fashion-MNIST 数据集怎么划分,如何避免测试集泄漏?

Fashion-MNIST 包含 70 000 张 28×28 灰度图像,分为 10 个服装类别,官方训练集和测试集分别为 60 000 张与 10 000 张。数据集定义见 Fashion-MNIST 原始论文。

本项目保留官方测试集,从原训练集末尾取 6 000 张作为验证集,其余 54 000 张参与梯度更新。验证集采用固定末尾划分,没有额外做类别分层抽样。

数据部分 图像数量 用途
训练集 54 000 更新模型参数
验证集 6 000 观察验证曲线与停止条件
测试集 10 000 评估已保存模型

数据预处理包括转为 float32、像素除以 255、增加单通道维度和标签独热编码。下面是与项目处理方式一致的核心代码,可独立检查输入形状:

python 复制代码
import numpy as np
import tensorflow as tf

(x_train, y_train), (x_test, y_test) = (
    tf.keras.datasets.fashion_mnist.load_data()
)
x_train = np.expand_dims(x_train.astype("float32") / 255.0, -1)
x_test = np.expand_dims(x_test.astype("float32") / 255.0, -1)

x_val, y_val = x_train[-6000:], y_train[-6000:]
x_train, y_train = x_train[:-6000], y_train[:-6000]
y_train_1h = tf.keras.utils.to_categorical(y_train, 10)
y_val_1h = tf.keras.utils.to_categorical(y_val, 10)
y_test_1h = tf.keras.utils.to_categorical(y_test, 10)

print(x_train.shape)  # (54000, 28, 28, 1)
print(x_val.shape)    # (6000, 28, 28, 1)
print(x_test.shape)   # (10000, 28, 28, 1)

测试图像不参与模型训练。继续调参时,应依据验证集选择配置;如果反复根据测试结果修改模型,测试集就逐渐承担了模型选择的角色,最终分数可能出现选择偏差。

3. 五种神经网络分别采用什么结构?

五模型比较覆盖全连接基线、卷积深度变化、正则化配置与几何增强。模型名称中的"三层"指卷积层数量;原代码将该模型命名为 improved_cnn,名称不意味着结果必然更优。

模型标识 主体结构 分类头
mlp Flatten → Dense 256 → Dense 128 Dense 10,Softmax
basic_cnn Conv 32 → Pool → Conv 64 → Pool Flatten → Dense 10
improved_cnn Conv 32 → Pool → Conv 32 → Pool → Conv 32 Flatten → Dense 10
cnn_bn_dropout 三个 Conv+BN+ReLU+Pool 块,通道 32/64/128 Flatten → Dropout 0.5 → Dense 10
cnn_augment 输入增强 → 相同的 32/64/128 卷积主体 Flatten → Dropout 0.5 → Dense 10

3.1 基础 CNN 的 TensorFlow 实现

基础 CNN 先保留 28×28 空间尺寸,再通过池化降为 14×14。第二层使用 valid 卷积得到 12×12,再池化为 6×6。分类头接收 2 304 维特征,模型总参数量为 41 866。

python 复制代码
from tensorflow.keras import layers, models

def build_basic_cnn():
    return models.Sequential([
        layers.Input(shape=(28, 28, 1)),
        layers.Conv2D(32, (3, 3), padding="same"),
        layers.ReLU(),
        layers.MaxPooling2D((2, 2)),
        layers.Conv2D(64, (3, 3), padding="valid"),
        layers.ReLU(),
        layers.MaxPooling2D((2, 2)),
        layers.Flatten(),
        layers.Dense(10, activation="softmax"),
    ], name="basic_cnn")

model = build_basic_cnn()
model.compile(
    optimizer="adam",
    loss="categorical_crossentropy",
    metrics=["accuracy"],
)
print(model.count_params())  # 41866

本文基础 CNN 的准确率比 MLP 高 2.11 个百分点,参数量则更少。这个结果支持当前卷积配置的有效性,但不能代表所有卷积模型都优于所有全连接模型。

3.2 Batch Normalization 与 Dropout 怎么组合?

CNN+BN+Dropout 使用三个无偏置卷积块,每个块依次执行卷积、批归一化、ReLU 和最大池化,末端使用 0.5 Dropout。

Batch Normalization 与 Dropout 的方法来源分别见 BN 原始论文和 Dropout 原始论文。本文采用这两种方法构建组合模型,不预设组合后必然提高分数。

python 复制代码
from tensorflow.keras import layers, models

def build_cnn_bn_dropout():
    net = models.Sequential([layers.Input(shape=(28, 28, 1))])
    for filters, padding in [(32, "same"), (64, "same"), (128, "valid")]:
        net.add(layers.Conv2D(filters, 3, padding=padding, use_bias=False))
        net.add(layers.BatchNormalization())
        net.add(layers.ReLU())
        net.add(layers.MaxPooling2D(2))
    net.add(layers.Flatten())
    net.add(layers.Dropout(0.5))
    net.add(layers.Dense(10, activation="softmax"))
    return net

CNN+BN+Dropout 的 count_params() 为 98 474,包含批归一化的可训练参数与非训练状态参数。与基础 CNN 比较时,通道宽度、网络结构及正则化同时变化,因此 90.60% 的结果不能全部归因于 BN 或 Dropout 中的某一个模块。

4. 如何运行训练、评估和可视化流程?

项目将训练、评估、绘图和 Web 展示分成独立入口。重新生成实验报告时,只需运行评估和绘图,不需要重复训练已有模型。

text 复制代码
Fashion-MNIST/
├── src/
│   ├── common.py
│   ├── models_def.py
│   ├── train.py
│   ├── evaluate.py
│   └── visualize.py
├── models/
├── outputs/
│   ├── results/
│   └── figures/
└── web/
    ├── app.py
    ├── templates/
    └── static/

当前项目记录的环境为 Python 3.10.18、TensorFlow 2.21.0,使用 CPU 训练。核心依赖包括 NumPy、Matplotlib、Flask 和 TensorFlow。下面的命令面向已有项目源码的 Windows PowerShell 环境,依赖安装列表是运行示例,并非完整锁定环境:

powershell 复制代码
python -m venv .venv
& .venv/Scripts/python.exe -m pip install tensorflow==2.21.0 numpy matplotlib pandas flask

# 训练五种模型
& .venv/Scripts/python.exe src/train.py

# 根据已保存模型生成详细评估
& .venv/Scripts/python.exe src/evaluate.py

# 根据评估结果和训练历史重新生成图表
& .venv/Scripts/python.exe src/visualize.py

# 启动本地仪表盘
& .venv/Scripts/python.exe web/app.py

浏览器打开 http://127.0.0.1:5006。独立复现本文分数还需要相同代码与依赖、数据划分和随机性设置;仅安装相同 TensorFlow 版本不能保证得到完全相同的数值。

4.1 训练结果会保存到哪里?

工件 文件位置 主要内容
模型 models/<key>.h5 已训练网络
训练历史 outputs/results/history_<key>.json 每轮准确率、损失、耗时
详细评估 outputs/results/eval_<key>.json 混淆矩阵、分类指标、错误样本
汇总 outputs/results/summary.json 五模型总体指标
图表 outputs/figures/ 17 张 PNG

训练入口发现同一模型的模型文件与历史文件均存在时,会跳过该模型。这属于"复用已有训练结果",不是自动恢复最近 epoch 的断点续训。

4.2 95% 是训练结果还是停止目标?

95% 是项目设置的验证准确率停止目标,本次五种模型均未达到。程序要求训练至少完成 5 轮,且验证准确率达到 95% 后才提前停止;实际运行中前四个模型完成 20 轮,增强模型完成 60 轮。

项目保存最终轮模型,不会自动恢复验证集最优轮的权重。CNN+BN+Dropout 最佳验证准确率为 92.18%,出现在第17轮;最终测试准确率 90.60% 来自训练结束保存的模型。两者来自不同数据集,也不应被写成同一轮模型的一组验证与测试结果。

5. 为什么 CNN 加数据增强后准确率反而下降?

本项目的数据增强 CNN 最终准确率为 86.70%,比未增强的相同卷积主体低 3.90 个百分点。这个结果只说明当前增强组合在本次设置下没有改善最终测试表现,不能证明数据增强对 Fashion-MNIST 普遍无效。

增强配置如下:

python 复制代码
augmentation = models.Sequential([
    layers.RandomFlip("horizontal"),
    layers.RandomRotation(0.08),
    layers.RandomZoom(0.10),
    layers.RandomTranslation(0.10, 0.10),
])

上述代码展示增强配置;实际项目将相同的增强层放在卷积主体之前。增强层在训练时执行随机变换,预测和评估时按默认推理行为关闭随机增强。

RandomRotation(0.08) 的 factor 按整周比例定义,对应最大约 ±28.8°,不是 ±0.08°。参数含义见 Keras RandomRotation 官方文档。在只有 28×28 像素的输入上,旋转插值、缩放和位移可能改变衣领、边缘等细节。

当前结果可提出三个待验证的解释:几何变换组合可能过强;增强与 0.5 Dropout 共同增加训练难度;末端 2×2 空间表示可能限制细节保留。项目尚未进行单项增强和 Dropout 消融,因此不能确认主要原因。

验证这些解释时,先固定网络与训练预算,再分别测试仅翻转、仅弱旋转、仅缩放、仅平移;之后逐步组合,并用验证集选择强度。增强模型与未增强模型当前训练轮数不同,也应另做等轮数或等耗时对照。

6. 模型主要把哪些服装类别识别错了?

CNN+BN+Dropout 的主要错误集中在T恤、套头衫、外套和衬衫之间。裤子、凉鞋、运动鞋、包和短靴的召回率均不低于 97.00%,而套头衫与衬衫的召回率分别为 72.50% 和 78.90%。

真实类别 预测类别 错误数量
T恤 衬衫 145
套头衫 外套 139
套头衫 衬衫 112
衬衫 外套 86
衬衫 T恤 81

前两个误判方向合计 284 个,占该模型全部 940 个错误的约 30.21%。因此,下一轮优化可以优先检查上装细粒度区分,而不是只盯着总体准确率。

混淆矩阵按"行是真实类别,列是预测类别"读取。外套召回率为 92.10%,精确率为 77.53%,说明真实外套较容易被找出,但部分其他上装也被错分为外套。精确率和召回率一起看,才能区分漏识与误报。

项目保存按测试索引顺序出现的前 50 个错误样本,图中显示前 16 个。这些图像用于具体诊断,没有经过随机抽样,不能代表全部错误的比例分布。

7. 为什么准确率之外还要看 F1 和置信度?

Fashion-MNIST 总体准确率反映全部测试样本中预测正确的比例;宏平均 F1 则让每个类别的精确率与召回率共同参与评价。CNN+BN+Dropout 的准确率为 90.60%,宏平均 F1 为 0.9065,但衬衫 F1 只有 0.7408,总分会掩盖具体类别的困难。

python 复制代码
import numpy as np

def confusion_matrix_10(y_true, y_pred):
    cm = np.zeros((10, 10), dtype=int)
    for true, pred in zip(y_true, y_pred):
        cm[int(true), int(pred)] += 1
    return cm

def precision_recall_f1(cm, class_id):
    tp = cm[class_id, class_id]
    fp = cm[:, class_id].sum() - tp
    fn = cm[class_id, :].sum() - tp
    precision = tp / (tp + fp) if tp + fp else 0.0
    recall = tp / (tp + fn) if tp + fn else 0.0
    f1 = 2 * precision * recall / (precision + recall) if precision + recall else 0.0
    return precision, recall, f1

CNN+BN+Dropout 对正确样本的平均最大预测概率为 0.9537,对错误样本为 0.7265。错误样本也可能得到较高评分,最大 Softmax 概率不能直接当作客观正确概率。

当前项目的置信度直方图只统计 0.5,1.0,更低置信度的样本不显示在柱状图中;平均置信度则对全部相应样本计算。若需要概率校准,应补充完整区间的可靠性曲线与校准误差,本文没有报告这些尚未执行的实验。

8. Flask 与 ECharts 仪表盘如何读取实验结果?

Flask 仪表盘读取评估程序写出的 JSON,通过接口向 ECharts 提供数据。训练与展示分离后,更新模型评估不需要修改前端中的实验数值。

接口 用途
/api/meta 类别名称、模型信息与样本索引
/api/summary 五模型总体指标
/api/history/<key> 单模型训练曲线数据
/api/eval/<key> 分类报告与混淆矩阵
/api/image/<index> 测试图像 PNG

以下代码是后端读取汇总文件的最小示例,不是完整仪表盘实现:

python 复制代码
import json
from pathlib import Path
from flask import Flask, jsonify

app = Flask(__name__)
# 将本示例保存为 web/app_minimal.py 后,在项目根目录执行
RESULTS = Path(__file__).resolve().parents[1] / "outputs" / "results"

@app.get("/api/summary")
def summary():
    with (RESULTS / "summary.json").open(encoding="utf-8") as file:
        return jsonify(json.load(file))

if __name__ == "__main__":
    app.run(host="127.0.0.1", port=5006, debug=False)

当前系统支持浏览已有测试样本,不包含用户上传图片的在线预测接口。本地绑定 127.0.0.1 适合实验展示;公网部署还需要独立考虑输入校验、访问控制与生产服务配置。

9. 常见问题

Fashion-MNIST 本项目达到 95% 准确率了吗?

没有。本项目最高测试准确率为 90.60%,最高记录的验证准确率为 92.18%。95% 是验证集提前停止目标,不是已经实现的结果。

三层 CNN 一定比两层 CNN 好吗?

不一定。本项目三层 CNN 为 90.23%,基础两层 CNN 为 90.48%。两个配置的通道数和分类头维度也不同,现有实验不能将差异全部归因于卷积层数。

重新生成图表会重新训练吗?

不会。src/visualize.py 读取现有历史、评估和汇总文件,生成静态图表。模型发生变化后,应先执行 src/evaluate.py,再执行 src/visualize.py。

训练脚本打印完成就代表五个模型都成功了吗?

不一定。当前入口会捕获单模型异常,因此还应检查各模型文件和评估工件。本文更新时核验了五个混淆矩阵的样本总数均为 10 000,错误数与汇总一致,17 张 PNG 均可解码。

可以直接复制本文代码得到同样结果吗?

本文给出了数据处理、代表性模型与接口的核心片段,完整五模型实验还依赖项目的其余模块。随机种子、依赖版本及硬件执行差异也会影响结果。本文没有提供尚不存在的公开源码仓库链接。

10. 后续怎样改进这组实验?

下一步先完善实验协议,再比较新结构。为每个配置运行多个随机种子,记录均值和标准差;保存最佳验证检查点;统一增强对照的训练预算;补充推理耗时与完整环境记录。对上装类别分别统计混淆方向,能进一步判断总体分数变化是否来自真正困难类别的改善。

现有证据支持的结论是:本次运行中 CNN+BN+Dropout 的最终测试准确率最高,基础 CNN 具有较低参数与训练开销,当前增强组合未带来提升。模型稳定排名、增强退化的具体原因以及真实商品图像上的表现,都需要新的实验支持。

参考资料与实验数据说明

相关推荐
编码者卢布7 小时前
【Azure Storage Account】Azure Queue指标中的Transactions 高,真实业务处理的消息就多吗?
microsoft·flask·azure
DeeGLMath2 天前
optimtool最新版加速训练分类任务
人工智能·分类·数据挖掘
tomwang03222 天前
路径优化建模、优化算法分类及工程化小结
算法·数学建模·分类
dear_bi_MyOnly3 天前
栈和队列:从原理到应用全解析
c语言·开发语言·c++·学习·分类
winfredzhang3 天前
从零实现“照片按地理位置显示在矢量地图上”:Flask + SQLite + Leaflet 全栈实战
python·sqlite·flask
撸串-研究生3 天前
基于Spring Boot的智慧社区垃圾分类与回收系统的设计与实现【附源码】
spring boot·后端·分类·垃圾分类·社区管理
智码看视界4 天前
深度学习:环境搭建PyTorch vs TensorFlow 选型
pytorch·深度学习·tensorflow·gpu·环境搭建·cuda·框架选型
龙腾AI白云5 天前
数字孪生、具身智能、世界模型三者交叉
数据库·人工智能·机器学习·flask·pygame
GPU实战笔记5 天前
TensorBoard 空面板排查:日志写入、--logdir 与访问入口分层
深度学习·tensorflow·模型训练·tensorboard