ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python蘑菇识别系统实战:图像分类与迁移学习全流程解析

Python蘑菇识别系统实战:图像分类与迁移学习全流程解析 简介Python蘑菇识别系统源码是一套面向图像分类场景的工程化项目核心功能是利用图片输入通过训练好的模型自动区分蘑菇种类可用于食品安全科普、户外菌类辨别辅助及 Python 视觉开发练习。压缩包共54个文件其中9个py源文件可直接阅读与修改20个pyc为编译缓存23张png图片覆盖界面素材和测试用蘑菇图像另有1份md项目说明和1个txt文本整体大小30.98MB。目前已有382人学习下载。项目主程序为 mogu.pymodels 目录存放识别模型gui_util 与 utils 提供界面和通用工具支撑代码覆盖图像预处理、模型加载预测和图形界面交互流程README 也给出了运行思路。对希望快速了解图像识别项目实际结构、学习 GUI 集成与二次修改的开发者具有较强的参考价值整体结构清晰适合入门到中级学习者拆解。1. Python蘑菇识别系统源码.zip先搞清楚这 3 个问题再动手解压蘑菇摆在案板上人眼都要犹豫半天的辨认题换给神经网络做的时候翻车往往不是因为认错而是“明明没见过却非常肯定地给你一个答案”。Python蘑菇识别系统源码.zip这个压缩包通常在图像分类的交流群里被当成入门工程分享下载解压后能看到模型定义、训练脚本、推理脚本、依赖清单和少量样例图片解决的是“给定一张蘑菇照片输出种类与可食用性判断”这一具体任务。适合已经会写 Python 基础语法、想用深度学习做课程设计、毕设或者独立小项目的开发者。拿到压缩包我建议先别急着解压跑代码先把选型、环境、边界问题这三件事捋清楚否则大概率会浪费一个下午在跟 import 报错和显存报错搏斗。本文就按这个顺序展开。2. 蘑菇识别的技术选型与模型原理图像分类是一条更稳的路蘑菇识别系统放在哪里用、拍什么照片直接决定技术选型。很多人一想着“识别蘑菇”就直奔目标检测觉得检测比分类高级但实际上绝大多数蘑菇识别需求用图像分类就能解决而且效果更稳、训练成本更低。我见过不少从检测入门最后又退回分类的案例原因基本都是数据量撑不住检测模型的训练。2.1 图像分类还是目标检测先想清楚你拍的是什么两类的核心差别在输出上。图像分类对整张图输出一个类别标签适合“画面里有一个明确的拍摄主体”目标检测输出若干个边界框和对应类别适合“一张照片里有多朵蘑菇不仅要识别还要数清楚”。蘑菇标本照片、手机随手拍的近景、甚至是显微镜下的孢子照片主体基本居中直接用分类网络即可。任务类型输入输出标注成本典型模型图像分类一张图一个类别标签每张图打一个标签ResNet、EfficientNet、MobileNet目标检测一张图多个边界框和类别每个目标画框并标注YOLOv8、Faster R-CNN、SSD实例分割一张图像素级掩码逐像素标注Mask R-CNN这个对比放到蘑菇场景里差距是数量级的。假设整理 1 万张蘑菇照片分类任务只需要按文件夹摆放、确认每张图的名称检测任务则要手动标出图像中每朵蘑菇的边界还要处理被遮挡、出土一半、距离过远的小目标。没有专门标注团队的话检测方案很难落地。所以标题里的源码如果主体代码是train.py、infer.py加models/目录那基本可以判断是分类路线如果出现了yolo.yaml、annotations/这类文件才需要考虑检测路线。2.2 卷积神经网络在蘑菇图像上学习的特征CNN 的结构可以理解成“逐层抽象”第一层卷积核关注边缘、颜色梯度、菌盖上的斑纹边界中间层把这些低级信息组合成圆形轮廓、鳞片纹理、菌褶走向靠近分类头的深层则更接近类别语义比如“这朵蘑菇的菌盖是黏滑型还是干燥型”“菌柄上有没有菌环”。这也是为什么蘑菇识别不能像普通猫狗分类那样只靠整体轮廓它属于细粒度识别需要网络捕捉更细微的特征。一个从零开始写的微型 CNN 通常长这样import torch.nn as nn class SimpleMushroomNet(nn.Module): def __init__(self, num_classes5): super().__init__() self.features nn.Sequential( nn.Conv2d(3, 16, kernel_size3, padding1), nn.ReLU(inplaceTrue), nn.MaxPool2d(2), # 224x224 - 112x112 nn.Conv2d(16, 32, kernel_size3, padding1), nn.ReLU(inplaceTrue), nn.MaxPool2d(2), # 112x112 - 56x56 nn.Conv2d(32, 64, kernel_size3, padding1), nn.ReLU(inplaceTrue), nn.AdaptiveAvgPool2d(1) # 全局池化变成 [batch, 64, 1, 1] ) self.classifier nn.Linear(64, num_classes) def forward(self, x): x self.features(x) x x.view(x.size(0), -1) return self.classifier(x)第一个卷积层用了 16 个卷积核padding1 是为了让特征图尺寸在卷积前后不缩水MaxPool2d 取 2x2 区域的最大值把分辨率减半同时保留最显著的纹理响应。这段代码只是为了演示卷积层堆叠的逻辑真正做蘑菇识别时没人会从这种小网络开始因为数据量撑不起充足的训练。实际项目里更常用的做法是站在预训练模型肩上做迁移学习。2.3 迁移学习为什么复用 ImageNet 预训练模型是主流做法蘑菇数据集的规模通常不大常见的公开蘑菇图像集也就每类几百到几千张从零训练一个深层 CNN 很难收敛而且很容易过拟合。ImageNet 预训练模型已经见过了大量自然图像它的底层卷积核学到的边缘、纹理、颜色分布是通用的我们只需要替换最后的全连接层让模型学会“用这些通用特征区分蘑菇种类”。在有限数据下这种迁移学习方式的准确率明显高于从零训练。import torch.nn as nn import torchvision.models as models def build_transfer_model(num_classes, backbonemobilenet_v3_large, pretrainedTrue): if backbone mobilenet_v3_large: weights models.MobileNet_V3_Large_Weights.IMAGENET1K_V1 if pretrained else None model models.mobilenet_v3_large(weightsweights) in_features model.classifier[-1].in_features model.classifier[-1] nn.Linear(in_features, num_classes) elif backbone resnet50: weights models.ResNet50_Weights.IMAGENET1K_V2 if pretrained else None model models.resnet50(weightsweights) model.fc nn.Linear(model.fc.in_features, num_classes) return model这里用weights...而不是旧版常见的pretrainedTrue因为新版 torchvision 对pretrained参数已经开始告警语义上weights也更明确。主干选择上CPU 环境或低功耗设备优先 MobileNetV3它在保证精度的同时推理更快有独立显卡、对精度要求高的场景选 ResNet50。还有一个关键点是微调策略第一次跑通时先把主干参数冻结、只训练新换上的分类头确认整个链路没问题后再解冻部分主干层做全面微调这样能避免一开始就踩到训练不稳定的坑。3. 从 zip 到跑通推理环境配置、目录梳理与最小运行步骤拿到压缩包后最要紧的是把环境搭起来让推理脚本能跑通。很多人习惯先看代码再跑环境我恰恰反着来先建独立 Python 环境再装依赖最后跑一张测试图整个过程控制在十分钟内。如果先读代码、试图理解每个函数很容易陷入细节里出不来。3.1 解压与目录梳理每个文件夹在做什么解压这一步看起来很基础但编码问题容易在 Windows 上翻车。源码包文件名有中文解压后目录里如果出现乱码先检查压缩软件用的是不是 UTF-8 编码。Linux 或 macOS 下直接用 unzip 就好unzip Python蘑菇识别系统源码.zip -d mushroom_project cd mushroom_project ls -la解压后先看整体结构常见的工程布局大致如下具体以你实际拿到的包为准目录或文件典型作用data/数据集通常分 train / val / test 三个子目录models/网络结构定义比如 resnet_mushroom.pyscripts/训练、推理、评估的入口脚本checkpoints/训练权重存放位置.pth / .pt 文件requirements.txt依赖库清单README.md项目说明和启动命令把README.md和requirements.txt打开扫一眼再做下一步。README 里如果明确写了环境版本、训练命令优先按它的来如果写得含糊再参考下面的通用方式。3.2 搭建 Python 环境用 conda 隔离依赖Python 安装教程里最常见的问题不是装不上 Python而是全局环境被各种项目依赖搞乱。蘑菇识别系统涉及 PyTorch、torchvision、OpenCV 等一堆包版本稍微错一个就能让训练脚本报出莫名其妙的错误。所以我会用 conda 单独建一个虚拟环境跟系统 Python 隔离开conda create -n mushroom python3.9 conda activate mushroomPython 3.8 到 3.11 都可以但建议先确认 requirements.txt 里有没有写版本上限。创建完环境后安装依赖pip install -r requirements.txt安装完成后立刻验证 PyTorch 是否可用这一步能提前暴露版本不匹配的问题python -c import torch; print(torch.__version__) python -c import torch; print(torch.cuda.is_available())没有 NVIDIA GPU 的机器会看到cuda.is_available()返回 False这没关系推理和训练在 CPU 上也能跑只是慢一些。若机器有 GPU 但返回 False多半是装了 CPU 版 PyTorch或者是 CUDA 驱动与 PyTorch 版本不匹配这部分属于环境问题可以在后面避坑章里单独排查。3.3 跑通推理脚本用一张蘑菇照片验证模型依赖装好后第一步不是重新训练而是用源码包里自带的权重文件跑一次推理。常见命令是python scripts/infer.py \ --image data/test/red_cap_001.jpg \ --checkpoint checkpoints/best_model.pth \ --class_names data/class_names.txt如果 README 里没有写明参数名直接打开infer.py看一眼 argparse 定义。大多数推理脚本的逻辑类似# scripts/infer.py import argparse import torch from PIL import Image from torchvision import transforms def get_test_transform(): return transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), ]) def main(): parser argparse.ArgumentParser() parser.add_argument(--image, requiredTrue, help待识别图像路径) parser.add_argument(--checkpoint, requiredTrue, help模型权重路径) parser.add_argument(--class_names, defaultdata/class_names.txt) args parser.parse_args() transform get_test_transform() image Image.open(args.image).convert(RGB) tensor transform(image).unsqueeze(0) # 变成 [1, 3, 224, 224] model torch.load(args.checkpoint, map_locationcpu) model.eval() with torch.no_grad(): logits model(tensor) prob torch.softmax(logits, dim1) top1_idx logits.argmax(dim1).item() with open(args.class_names, r, encodingutf-8) as f: names [line.strip() for line in f] print(f预测类别: {names[top1_idx]}) print(f置信度: {prob[0][top1_idx].item():.4f}) if __name__ __main__: main()两个参数值得注意map_locationcpu让模型在无 GPU 机器上也能加载如果权重文件是用 GPU 保存的不加这个参数会直接报错topk改成dim1是按每个样本独立取最大值。类别文件class_names.txt的顺序必须和训练时的类别索引一致否则会出现“模型预测的是第 3 类但名字文件里第 3 行写的是另一种蘑菇”的错位问题这一点在训练章节还会展开。4. 训练你自己的蘑菇识别模型数据划分、调参与效果评估推理跑通只是起点真正要让系统适配你自己的数据得重新训练模型。这个阶段最值得花时间的是数据准备模型结构反而是其次。我见过很多人一上来就调网络层数结果数据划分本身就有问题再好的模型也白搭。4.1 数据准备与划分避免同源图片造成的数据泄漏蘑菇识别数据一般按类别建文件夹整理成下面的形式data/ train/ 牛肝菌/ 鸡油菌/ 毒蝇伞/ val/ 牛肝菌/ test/ 牛肝菌/如果原始图片散落在一个目录里需要写脚本按比例拆分。要注意的是拆分之前先按“拍摄批次”分组而不是把每张图当作完全独立的样本。同一批蘑菇在同一光照、同一背景下连续拍的几十张照片如果同时进训练集和测试集会让测试成绩虚高这叫数据泄漏。下面这个脚本用random.seed(42)控制拆分结果可复现import os import random import shutil random.seed(42) data_root data/raw # 原始图片按类别文件夹存放 out_root data/split for class_name in os.listdir(data_root): class_dir os.path.join(data_root, class_name) if not os.path.isdir(class_dir): continue images [f for f in os.listdir(class_dir) if f.lower().endswith((.jpg, .jpeg, .png))] random.shuffle(images) n_total len(images) train_end int(n_total * 0.7) val_end int(n_total * 0.85) for idx, img in enumerate(images): if idx train_end: split train elif idx val_end: split val else: split test src os.path.join(class_dir, img) dst os.path.join(out_root, split, class_name, img) os.makedirs(os.path.dirname(dst), exist_okTrue) shutil.copyfile(src, dst)70% 训练、15% 验证、15% 测试是分类任务的常见起点。如果总体样本特别少比如每类只有两三百张可以适当调整为 80% 训练、10% 验证、10% 测试。数据准备好后用torchvision.datasets.ImageFolder直接读取目录结构它会自动按文件夹名生成类别索引代码很简洁from torchvision import datasets, transforms data_transform { train: transforms.Compose([ transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(p0.5), transforms.RandomRotation(15), transforms.ColorJitter(brightness0.2, contrast0.2), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), ]), val: transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), ]), } train_ds datasets.ImageFolder(data/split/train, data_transform[train]) val_ds datasets.ImageFolder(data/split/val, data_transform[val]) # 把类别名和索引的映射保存下来训练完推理时要用 import json with open(checkpoints/class_to_idx.json, w, encodingutf-8) as f: json.dump(train_ds.class_to_idx, f, ensure_asciiFalse, indent2)训练集增强用RandomResizedCrop模拟不同距离的拍摄RandomRotation(15)模拟手持拍摄的角度偏移ColorJitter模拟不同天气下的色差。验证集不做随机增强只用缩放和中心裁剪保证评估结果稳定。4.2 训练超参数batch size、学习率与 epoch 的配合方式微调预训练模型时新手最常犯的错是把学习率设成从头训练时常用的 1e-2 或 1e-3。预训练模型已经有一个较好的特征空间学习率太大一步就能把原有参数冲坏。我的习惯是 Adam 优化器配 1e-4 起步观察 loss 曲线后再决定要不要调高或调低。import torch import torch.nn as nn import torch.optim as optim model build_transfer_model(num_classes5, backboneresnet50) criterion nn.CrossEntropyLoss() optimizer optim.Adam(model.parameters(), lr1e-4, weight_decay1e-4) scheduler optim.lr_scheduler.ReduceLROnPlateau( optimizer, modemax, factor0.3, patience3, verboseTrue )关键超参数按下面这个表去理解比死记数值更重要参数常见起始值作用与注意点batch sizeGPU 32 / CPU 16太小会导致梯度抖动大太大容易显存溢出learning rate1e-4 ~ 3e-4微调阶段最敏感别直接用 1e-2weight decay1e-4 ~ 5e-4L2 正则化对防止过拟合有实际帮助epochs20~50 配合早停不要盲目训练到 100 轮验证集不涨就该停训练循环里除了计算 loss 和精度还要把每一轮的最佳验证精度模型保存下来。固定训练 50 轮、每轮结束比较验证集精度、只保留最好的一次权重这是最省心的做法best_val_acc 0.0 for epoch in range(50): model.train() running_loss, correct, total 0.0, 0, 0 for images, labels in train_loader: optimizer.zero_grad() outputs model(images) loss criterion(outputs, labels) loss.backward() optimizer.step() running_loss loss.item() * images.size(0) correct (outputs.argmax(1) labels).sum().item() total labels.size(0) train_acc correct / total val_acc evaluate(model, val_loader, criterion) # 自定义函数返回验证集准确率 if val_acc best_val_acc: best_val_acc val_acc torch.save(model.state_dict(), checkpoints/best_model.pth) scheduler.step(val_acc) print(fepoch{epoch1} train_acc{train_acc:.4f} val_acc{val_acc:.4f})注意这里保存的是state_dict而不是整个模型。state_dict只存参数配合build_transfer_model里的模型定义使用切换主干网络或者迁移到另一台机器时更灵活。加载时先构建相同结构的模型再load_state_dict。4.3 评估指标准确率不能只看“毒性”要看混淆矩阵准确率是最直观的指标但不能只看它。蘑菇识别场景里“有毒蘑菇被判断成无毒”和“无毒蘑菇被判断成有毒”是完全不同代价的两类错误。前者可能造成食物中毒后者顶多让用户不吃损失的是便利。所以我会每次都打印混淆矩阵和分类报告import torch from sklearn.metrics import confusion_matrix, classification_report all_preds, all_labels [], [] model.eval() with torch.no_grad(): for images, labels in val_loader: outputs model(images) preds outputs.argmax(dim1).cpu().numpy() all_preds.extend(preds) all_labels.extend(labels.numpy()) print(classification_report(all_labels, all_preds, target_namesval_ds.classes, digits4))classification_report会输出每个类别的精确率、召回率、F1 值。我要重点看的是毒菌类别如果召回率低于其他类别说明有相当比例的毒菌被分到了其他类这时候不能急着加数据先弄清是哪些种类之间互相混淆。比如毒蝇伞和可食用的橙盖鹅膏在视觉上很接近模型容易混淆那就需要单独补充这两个类别的样本或者在预处理里强化颜色归一化。单纯盯着总准确率这些问题都会被淹没。5. 蘑菇识别系统避坑指南我踩过的 5 个坑与修复方案这一章把我在类似图像分类项目里实际遇到过的坑挑五个最常见的写出来每条按“现象、原因、解决”的顺序讲。这些坑跟模型本身关系不大几乎都是数据、环境、预处理层面的事但任何一个都能让整个项目原地转圈。5.1 报错 ValueError: Expected more than 1 value per row when running现象训练循环走到最后一个 batch 时突然抛错停止训练。原因样本总数不能被 batch size 整除最后一个 batch 只剩一张图。BatchNorm 层在单样本上无法稳定地计算批内均值于是报错。解决在 DataLoader 里设置drop_lastTrue把最后不完整的一批数据丢弃或者调整 batch size让批数能整除样本数。更通用的是两者配合from torch.utils.data import DataLoader train_loader DataLoader(train_ds, batch_size32, shuffleTrue, drop_lastTrue, num_workers2)shuffleTrue是为了每个 epoch 打乱数据顺序避免模型学到样本排列的规律drop_lastTrue丢掉的样本量很小对精度几乎没有影响。如果用 Windows 系统num_workers2有时会报多进程相关的错误可以先改成num_workers0排查。5.2 训练集准确率 99%验证集只有 63%现象训练 loss 一路下降训练集准确率接近满分但验证集准确率停留在 60% 上下甚至逐轮下降。原因过拟合。模型把训练图里的背景、光照、甚至拍摄设备的水印都记住了没有真正学习蘑菇本身的特征。蘑菇图像集如果来源单一比如全部从图库下载背景高度相似这个问题更严重。解决第一步加强数据增强把RandomRotation、ColorJitter、RandomAffine加进训练预处理第二步在分类头加 Dropout并增大weight_decay第三步观察增强后的 loss 曲线验证集准确率一般会回升。注意不要为了提升验证集成绩去反复调整随机种子那是自欺欺人。我习惯把增强后的样本图单独保存几张出来看一眼确认增强没有把蘑菇的形态破坏到人眼都认不出的程度。5.3 训练效果不错单张推理结果却全错现象验证集上模型表现正常但拿一张网图或手机照片跑infer.py预测结果离谱且置信度往往很高。原因推理脚本的预处理和训练不一致。最常见的是三处图片没做Resize((224, 224))图片用 OpenCV 读入但通道顺序是 BGR归一化参数和训练时不一致。这三处任意一处出错输入数据的数值分布就偏离训练时的分布模型相当于在看一种“被调过色的图像”。解决把推理预处理写成和训练完全相同的函数不要用复制粘贴。最稳妥的做法是从训练脚本里 import 同一个transform对象。另外OpenCV 读图后要显式转换import cv2 img_bgr cv2.imread(test.jpg) img_rgb cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) # OpenCV 默认 BGRPyTorch 需要 RGB还有一种不太容易发现的情况训练时用了灰度图推理时却直接读彩色图导致模型首层卷积核看到的通道数不匹配。保证训练和推理用同一套读取方式别在步数上偷懒。5.4 有毒和无毒的判断整体颠倒现象模型输出的类别和图片实际内容对不上比如把无毒蘑菇的照片识别成有毒而且所有类别都错位看起来像“每张图都预测成了固定某个类”。原因99% 的可能是类别索引和名字列表没对应上。训练时ImageFolder按文件夹名的字母序生成索引比如“红菇”排在“鸡油菌”前面推理时如果class_names.txt里写的顺序跟这个索引不一致自然会把第 0 类当成第 0 行名字。解决训练结束时把class_to_idx保存成 JSON推理时加载它做反查import json import torch with open(checkpoints/class_to_idx.json, r, encodingutf-8) as f: class_to_idx json.load(f) idx_to_class {v: k for k, v in class_to_idx.items()} logits model(tensor) pred_idx logits.argmax(dim1).item() print(预测类别:, idx_to_class[pred_idx])这个坑的隐蔽之处在于如果只有部分类别顺序错位模型看起来像是“识别能力不行”实际是映射问题。以后无论谁跑这套代码都要求必须带class_to_idx.json别再用手打的class_names.txt。5.5 遇到没见过的蘑菇模型硬给一个答案现象把一种训练集里根本不存在的蘑菇照片放进推理脚本模型仍然以一个很高的置信度把它归到某个已知类别里。原因Softmax 的输出总和永远为 1它只能在已知类别里做选择。模型没有“拒识”能力面对未知类别时被迫选一个最接近的。这在蘑菇场景下很危险因为野外可能遇到大量未收录品种。解决给推理加一个置信度阈值。最大概率低于阈值时输出“不确定”而不是强行给结果prob, idx torch.topk(torch.softmax(logits, dim1), 1) confidence prob.item() if confidence 0.6: print(不确定建议不要食用) else: print(f预测类别: {idx_to_class[idx.item()]}置信度: {confidence:.2f})阈值怎么定在验证集上统计所有正确预测的置信度分布把阈值设在能让“有毒误判为安全”数量降到最低的位置。通常 0.5 到 0.7 之间比较常用但具体取决于你的数据。这个“不确定”的出口在很多安全相关场景里比提高一个百分点的准确率更有价值。6. 把识别能力收成一个可直接用的服务Flask 接口与接口验证训练好模型之后下一步往往是想让身边的人也能用。把推理脚本暴露成一个 Flask 接口是最直接的落地方式手机、小程序、Web 前端都能通过 HTTP 调用。下面是一个最小的服务端实现from flask import Flask, request, jsonify from PIL import Image import torch import io from torchvision import transforms app Flask(__name__) model torch.load(checkpoints/best_model.pth, map_locationcpu) model.eval() idx_to_class {0: 牛肝菌, 1: 鸡油菌, 2: 毒蝇伞} # 实际从 JSON 读取 transform transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), ]) app.route(/predict, methods[POST]) def predict(): file request.files[image] img_bytes file.read() img Image.open(io.BytesIO(img_bytes)).convert(RGB) tensor transform(img).unsqueeze(0) with torch.no_grad(): logits model(tensor) probs torch.softmax(logits, dim1)[0] conf, idx probs.topk(1) cls idx_to_class[idx.item()] return jsonify({ class_name: cls, confidence: round(conf.item(), 4) }) if __name__ __main__: app.run(host0.0.0.0, port5000)服务启动后用curl做一次接口验证curl -X POST -F imagedata/test/牛肝菌_001.jpg http://127.0.0.1:5000/predict返回结果类似{class_name:牛肝菌,confidence:0.9821}。验证接口时别只看成功返回还要测两种失败场景传一个空文件、传一个非图片文件确认服务端不会崩溃而是返回提示信息。这里有一个我养成的习惯每次训练完把best_model.pth、class_to_idx.json、推理命令、验证集结果四样东西放进同一个带日期和类目数的目录里比如models/mushroom_v3_5cls_20240115/。虽然多花一分钟但一个月后回来看你能直接说清这个模型是用什么数据、什么主干网络、达到什么指标训练出来的而不需要再翻当时的聊天记录。这套流程对蘑菇识别系统同样适用甚至在“安全判定”这类场景里这种记录习惯本身就是最后的后悔药。希望帮到你。本文还有配套的精品资源点击获取
返回列表