☰
PyTorch MobileNet微生物分类实战:从数据准备到PyQt界面部署
2026/10/5 3:36:48 网站建设 项目流程

简介:本资源面向深度学习入门者与图像分类实践者,提供一套基于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 python=3.8 -y conda activate microbe # 安装 pytorch 1.8.1(CPU 版示例,有显卡按官网命令换 cu 版本) pip install torch==1.8.1 torchvision==0.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 torch==1.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 脚本到底把什么写进了 txt

3.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', encoding='utf-8') as f: f.write('\n'.join(lines[:split])) with open(val_txt, 'w', encoding='utf-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(pretrained=True) # 替换分类头,输出类别数改成你的类别数 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)

逻辑说明:pretrained=True会下载 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 或 32,GPU 可以 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 可以和训练一致,shuffle=False,验证不需要打乱。如果验证集某类样本数为 0,max(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(f'epoch {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 PyQt5==5.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(pretrained=True) # 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 以下,这三步过了才敢让它跑通宵。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询