
简介本资源面向深度学习入门者与图像分类实践者提供一套基于PyTorch的MobileNet微生物分类识别方案可用于病毒、真菌、藻类、细菌等类别的图像识别实验。代码共3个Python脚本分别负责生成数据索引、CNN模型训练以及PyQt可视化界面每一行均配有中文注释便于零基础读者理解网络结构与训练流程。压缩包共9个文件包含py脚本、jpg提示图、txt环境依赖说明与docx说明文档整体约228KB体积轻便。需注意资源不含数据集图片需自行按类别建文件夹并放入对应图片每个文件夹内附有提示图指引存放位置。环境方面提供requirement.txt推荐使用Anaconda搭配Python3.7或3.8及PyTorch1.7.1或1.8.1。目前已有151人学习适合希望快速跑通MobileNet分类流程、掌握数据组织与训练排错思路的读者参考。1. 拆开这个微生物分类包三个 py 文件怎么把 MobileNet 跑成能用的分类器微生物图像分类这件事真正卡住人的往往不是模型结构而是数据怎么摆、标签怎么生成、训练完怎么验证。这个资源包给的是一个基于 PyTorch 的 MobileNet 图像分类工程专门做微生物识别覆盖病毒、真菌、藻类、细菌这几类。它不含数据集图片但把训练链路完整搭好了01生成txt.py负责把文件夹结构转成标签文件02CNN训练数据集.py负责训练03pyqt界面.py提供一个可视化推理入口外加一份逐行中文注释的说明文档和requirement.txt。适合两类人一类是想拿现成模板快速跑通微生物分类的新手另一类是想找一个干净 MobileNet 微调骨架、自己换数据换类别的从业者。下面按「资源是什么 → 怎么用 → 坑在哪」的顺序拆。2. 环境与目录结构先让三个 py 文件找得到自己的数据2.1 为什么推荐 Anaconda Python 3.7/3.8 PyTorch 1.7.1/1.8.1这个组合不是随便写的。MobileNet 在 PyTorch 里的预训练权重加载、torchvision.transforms的接口在 1.7 到 1.8 这两个版本上最稳再往上一些 API 有变动往下 1.6 之前部分算子兼容性差。Python 3.7/3.8 是这两个 PyTorch 版本官方轮子覆盖最全的区间3.9 之后有些依赖包编译会翻车。用 Anaconda 的好处是能把环境隔离出来避免和你机器上已有的 torch 版本打架。先建环境命令如下# 创建独立环境指定 python 3.8 conda create -n microbe python3.8 -y conda activate microbe # 安装 pytorch 1.8.1CPU 版示例有显卡按官网命令换 cu 版本 pip install torch1.8.1 torchvision0.9.1 # 安装其余依赖 pip install -r requirement.txt逻辑说明conda create把环境隔开后面所有操作都在microbe里做。torch和torchvision版本要配对1.8.1 对应 torchvision 0.9.1装错版本会在导入时直接报undefined symbol。requirement.txt里通常是 numpy、Pillow、matplotlib、PyQt5 这类先装 torch 再装它避免 pip 把 torch 当依赖重装一遍。参数说明如果你有 NVIDIA 显卡去 PyTorch 官网查对应 CUDA 版本的安装命令把pip install torch1.8.1换成带cu111之类的写法。没有显卡就用 CPU 版训练慢但能跑通微生物数据集一般几千张图CPU 也能忍。2.2 目录结构决定 01 脚本能不能正确生成标签下载解压后根目录大致是这样项目根目录/ ├── 数据集/ │ ├── 病毒/ │ │ └── 提示图.jpg │ ├── 真菌/ │ │ └── 提示图.jpg │ ├── 藻类/ │ │ └── 提示图.jpg │ └── 细菌/ │ └── 提示图.jpg ├── 01生成txt.py ├── 02CNN训练数据集.py ├── 03pyqt界面.py ├── 说明文档.docx └── requirement.txt每个类别文件夹里那张提示图是告诉你「图片放这里」不是训练数据正式训练前要把它删掉或者替换成真实图片。类别文件夹名就是类别标签01生成txt.py读的是文件夹名不是文件名。所以你想加类别直接新建文件夹比如放线菌/往里丢图就行不用改代码里的类别列表——前提是脚本用的是os.listdir遍历目录这也是这类模板的常见写法。提示文件夹名不要用中文空格或特殊符号虽然 Python 3 能处理中文路径但 PyTorch 的DataLoader在某些系统上读中文路径会出编码问题稳妥起见用英文或拼音。3. 数据准备与标签生成01 脚本到底把什么写进了 txt3.1 图片收集的硬性要求和常见数量级这个包不含图片你得自己搜集。微生物图像来源一般是显微镜拍摄图、公开数据集截图、论文配图。每个类别建议至少 200 张低于这个数 MobileNet 的预训练权重微调会严重过拟合。四类各 200 张就是 800 张按 8:2 划分训练验证训练集 640 张这个量级在 CPU 上跑 20 个 epoch 大概几十分钟到一两小时看图片分辨率。图片格式统一成 jpg 或 png尺寸不用提前裁剪训练脚本里的transforms会做 resize。但要注意如果原始图片长宽比差异极大比如有的 2000x200有的 200x2000直接 resize 到 224x224 会把微生物拉变形影响分类。常见做法是先做中心裁剪再 resize或者保持比例 padding。这个包的训练脚本用的是标准Resize((224,224))所以你自己收图时尽量选长宽比接近的。3.2 01生成txt.py 的逻辑与输出格式这个脚本的核心任务是把「文件夹名 → 类别索引」和「图片路径 → 标签」写成 txt。典型实现如下逐行注释版import os # 数据集根目录按实际路径改 data_root ./数据集 # 输出标签文件路径 train_txt ./train.txt val_txt ./val.txt classes sorted(os.listdir(data_root)) # 类别按字母序排保证索引稳定 class_to_idx {cls: i for i, cls in enumerate(classes)} print(类别映射:, class_to_idx) lines [] for cls in classes: cls_dir os.path.join(data_root, cls) if not os.path.isdir(cls_dir): continue for img_name in os.listdir(cls_dir): # 跳过提示图和非图片文件 if not img_name.lower().endswith((.jpg, .png, .jpeg)): continue if 提示 in img_name: continue img_path os.path.join(cls_dir, img_name) lines.append(f{img_path} {class_to_idx[cls]}) # 按 8:2 划分训练验证 split int(len(lines) * 0.8) with open(train_txt, w, encodingutf-8) as f: f.write(\n.join(lines[:split])) with open(val_txt, w, encodingutf-8) as f: f.write(\n.join(lines[split:])) print(f总样本 {len(lines)}训练 {split}验证 {len(lines)-split})逻辑说明sorted(os.listdir())保证每次运行类别顺序一致否则这次「病毒0」下次可能「病毒2」训练出来的模型标签就乱了。跳过提示图那一步很关键提示图本身不是微生物图混进去会污染标签。输出格式是「图片路径 空格 类别索引」这是 PyTorch 自定义 Dataset 最常见的读法。参数说明data_root改成你实际的文件夹路径。split比例 0.8 是经验值数据少于 500 张时可以调到 0.7给验证集多留点。如果你想让每个类别内部均匀划分而不是全局按顺序切需要先按类别分组再各自切分否则可能出现验证集里某一类特别少的情况——这是这个简单实现的一个边界。注意运行完 01 脚本后打开train.txt看一眼确认路径分隔符和你系统一致Windows 是反斜杠Linux 是斜杠路径不对训练时会报FileNotFoundError。4. 训练脚本怎么改MobileNet 微调的关键参数与断点4.1 02CNN训练数据集.py 的结构拆解训练脚本一般分四块数据集类定义、模型加载、训练循环、验证与保存。MobileNet 在 torchvision 里有两个常用版本mobilenet_v2和mobilenet_v3。这个包标题写的是 mobilenet具体版本看代码里的 import。以mobilenet_v2为例加载预训练权重的写法import torch import torch.nn as nn from torchvision import models # 加载预训练 mobilenet_v2 model models.mobilenet_v2(pretrainedTrue) # 替换分类头输出类别数改成你的类别数 num_classes 4 # 病毒/真菌/藻类/细菌 model.classifier[1] nn.Linear(model.last_channel, num_classes) # 有 GPU 就用 GPU device torch.device(cuda if torch.cuda.is_available() else cpu) model model.to(device)逻辑说明pretrainedTrue会下载 ImageNet 预训练权重第一次运行需要联网。model.classifier[1]是 MobileNetV2 的最后一层全连接原来输出 1000 类改成你的类别数。last_channel是 1280不用硬编码。改完分类头前面的卷积层默认还是冻结的如果你想微调全部层需要把requires_grad打开但小数据集建议只训分类头避免过拟合。参数说明num_classes必须和 01 脚本生成的类别数一致不一致会在算 loss 时维度报错。学习率一般设 1e-3 到 1e-4只训分类头可以用 1e-3全量微调用 1e-4。batch size 看显存CPU 训练设 16 或 32GPU 可以 64。4.2 训练循环里必须盯的三个量训练循环里 loss 和 accuracy 是基本盘但微生物分类还要盯混淆矩阵。因为藻类和真菌在低倍镜下形态可能接近模型容易把这两类搞混。常见做法是每个 epoch 结束后在验证集上跑一遍打印每类的 precision 和 recall。如果某一类 recall 特别低说明这类样本太少或者和另一类太像需要补数据。# 验证阶段统计每类正确数 correct_per_class [0] * num_classes total_per_class [0] * num_classes model.eval() with torch.no_grad(): for imgs, labels in val_loader: imgs, labels imgs.to(device), labels.to(device) outputs model(imgs) _, preds torch.max(outputs, 1) for label, pred in zip(labels, preds): total_per_class[label] 1 if label pred: correct_per_class[label] 1 for i in range(num_classes): acc correct_per_class[i] / max(total_per_class[i], 1) print(f类别 {i} 验证准确率: {acc:.4f})逻辑说明model.eval()关掉 dropout 和 batchnorm 的训练模式验证必须加。torch.no_grad()省显存。按类别统计能暴露全局 accuracy 掩盖的问题——比如全局 85%但藻类只有 50%那这个模型实际不可用。参数说明val_loader的 batch size 可以和训练一致shuffleFalse验证不需要打乱。如果验证集某类样本数为 0max(total,1)防止除零。4.3 模型保存与断点续训训练脚本一般会在每个 epoch 后保存best.pth或last.pth。建议保存两个一个是最佳验证准确率的一个是最后一个 epoch 的。微生物数据少训练可能在第 10 个 epoch 就开始过拟合最佳模型往往不是最后一个。best_acc 0.0 for epoch in range(epochs): # ... 训练代码 ... val_acc evaluate(model, val_loader) if val_acc best_acc: best_acc val_acc torch.save(model.state_dict(), best.pth) print(fepoch {epoch} 保存最佳模型acc{val_acc:.4f}) torch.save(model.state_dict(), last.pth)逻辑说明state_dict()只存权重不存模型结构加载时需要先实例化同样的模型再load_state_dict。这样文件小也灵活。best_acc初始为 0第一个 epoch 只要验证准确率大于 0 就会保存。参数说明如果你中途中断想续训需要额外保存 optimizer 的 state_dict 和当前 epoch这个简单模板通常没做续训要从头开始。想续训的话自己加torch.save({epoch: epoch, model: model.state_dict(), optimizer: optimizer.state_dict()}, checkpoint.pth)。5. 避坑与排查微生物分类跑不通时先看这五条5.1 现象训练 loss 不下降一直卡在 1.6 左右原因最常见的是标签没对上。01 脚本生成的 txt 里类别索引和训练脚本里的num_classes不一致或者图片路径错了导致读进来的是空白图。另一种可能是学习率太大loss 震荡不下降。解决先打印一个 batch 的图片和标签确认图片能正常显示、标签在 0 到 num_classes-1 之间。然后把学习率降到 1e-4 试。如果 loss 还是不动检查model.classifier[1]是否真的被替换了打印model看最后一层输出维度。5.2 现象验证准确率远高于训练准确率原因验证集太小或者验证集和训练集有重叠图片。微生物数据收集时容易把同一张图的不同裁剪版本分别放进训练和验证导致数据泄漏。解决检查 01 脚本的划分逻辑确保是按图片划分而不是按类别划分。如果同一张原图有多个变体要按原图分组划分同一原图的所有变体只能出现在训练集或验证集之一。验证集至少占总样本 15%。5.3 现象PyQt 界面启动报No module named PyQt5原因requirement.txt里可能没写 PyQt5或者装了但版本和 Python 不匹配。解决pip install PyQt5。如果还报错试pip install PyQt55.15.4这个版本在 Python 3.8 上最稳。界面脚本里加载模型的部分要确认模型路径和类别数一致否则界面能启动但推理会崩。5.4 现象GPU 显存不足报CUDA out of memory原因batch size 太大或者图片分辨率没降下来。MobileNet 本身不大但 224x224 的 batch 64 在 4G 显存上会爆。解决把 batch size 降到 16 或 8或者在训练脚本里加torch.cuda.empty_cache()。如果还不行检查是不是在训练循环里累积了计算图比如没有用optimizer.zero_grad()。5.5 现象推理时所有图片都预测成同一类原因模型没训练好或者推理时的预处理和训练时不一致。训练用了Normalize推理时忘了加输入分布对不上模型输出就退化成常数。解决把训练脚本里的transforms复制到推理脚本确保Resize、ToTensor、Normalize三步完全一致。Normalize 的 mean 和 std 用 ImageNet 的[0.485, 0.456, 0.406]和[0.229, 0.224, 0.225]因为预训练权重是在 ImageNet 上统计的。6. 进阶把 MobileNet 换成 v3 并做类别增量的小技巧这个包默认的 MobileNet 版本可能是 v2但如果你想试更新的结构换成mobilenet_v3_small或mobilenet_v3_large只需要改两行。v3 在同等精度下参数更少适合部署到边缘设备做微生物实时识别。换的时候注意分类头位置不同v2 是model.classifier[1]v3 是model.classifier[3]改错了会报维度不匹配。from torchvision import models import torch.nn as nn # 换成 mobilenet_v3_small model models.mobilenet_v3_small(pretrainedTrue) # v3 的分类头是 classifier 里的第 3 个 Linear model.classifier[3] nn.Linear(model.classifier[3].in_features, num_classes)逻辑说明model.classifier[3].in_features自动读取原层输入维度不用硬编码。v3 的 classifier 是一个 Sequential包含 Linear、Hardswish、Dropout、Linear所以索引是 3。参数说明v3_small 的输入尺寸也是 224不用改 transforms。学习率可以比 v2 稍低因为 v3 的 Hardswish 激活对学习率更敏感建议 5e-4 起步。另一个实用技巧是类别增量。你第一次用四类训好了模型后来想加「放线菌」这一类不用从头训。冻结前面的卷积层只把分类头换成五类用新数据微调分类头几个 epoch 就行。但要注意旧类别的数据也要混进去一起训否则模型会灾难性遗忘把旧类别全忘光。常见做法是旧数据和新数据按 1:1 混合学习率降到 1e-4训 5 到 10 个 epoch。验证方法上除了看准确率建议拿几张没参与训练的图片手动跑一遍03pyqt界面.py看预测结果是否符合肉眼判断。微生物分类有个玄学模型在验证集上 90%但实际用的时候把藻类判成真菌往往是因为验证集和实际场景的成像条件不同。所以最终验收一定要用你真实场景拍的图而不是网上下的图。从那以后我每次拿到这类分类模板都强制先跑一遍 01 脚本、打开生成的 txt 数一遍每类样本数、再启动训练看第一个 epoch 的 loss 有没有降到 2 以下这三步过了才敢让它跑通宵。希望帮到你。本文还有配套的精品资源点击获取