尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
EfficientNet迁移学习实现104种花图像分类的完整方案
简介面向图像分类实战的EfficientNet轻量级迁移学习项目聚焦104种常见花卉图像识别任务。项目内置b0至b7共8种模型可通过参数选择是否加载官方预训练权重、是否冻结特征层仅训练分类层优化器提供Adam、SGD、AdamW三种损失函数使用多类别交叉熵并采用余弦退火调整学习率训练集精度约0.9。压缩包内共约2000个文件以1993张花卉jpg图像为主另含3个Python训练与评估脚本、2个JSON指标结果文件、1个TXT说明及1个readme文档总体积约514MB。除常规训练流程外项目会在训练集和验证集上输出loss与准确率曲线并绘制混淆矩阵、计算recall、precision、F1-score和特异度各类别详细指标可直接查看JSON文件若需更换数据集可参考readme中的说明调整配置。目前已有124人学习下载适合希望借助现成数据与代码快速上手EfficientNet迁移学习并深入理解分类评估指标的开发者和学生。1. 用 EfficientNet 迁移学习认 104 种花一个能直接跑通的图像分类项目手头有一套完整的 104 种花图像分类工程约 16k 张花类图片、标签文件、训练脚本和评估脚本都打包好了。网络结构用 EfficientNet 家族 b0-b7 共 8 种模型带 ImageNet 预训练权重开关带冻结训练开关优化器、多分类交叉熵损失、cos 余弦退火学习率都已经写在工程里。训练结束后自动在训练集和验证集上输出 loss、准确率、混淆矩阵、recall、precision、F1 和特异度。最省事的是下载后按 readme 跑一遍就能出结果训练集精度能到 0.9 上下。它适合刚接触迁移学习的入门者也适合做课程设计、毕业设计的在校生以及手里有自己的数据集、想快速搭一个分类基线的工程师。下面我按「选型 → 数据 → 训练 → 避坑 → 评估」的顺序把整个工程拆开讲。2. EfficientNet 选型与迁移学习两根控制杆b0 到 b7 差在哪pretrained 和 freeze_layers 怎么配合2.1 EfficientNet 的缩放逻辑和 b0-b7 的实际差距EfficientNet 的核心思路不是单独加深网络或加宽通道而是用一个系数同时缩放深度、宽度和输入分辨率这叫 compound scaling。b0 是基线模型b1 到 b7 逐步把这三个维度放大模型容量、FLOPs 和显存占用都随之上升。放到这个项目里切换模型只需要改一个名字。实际使用中差距最直观的体现是输入分辨率。b0 通常用 224b3 用到 300b5 以后普遍到 456 甚至 600。分辨率变大意味着图片细节更多但也意味着训练变慢、显存翻倍。下面是这个项目里 8 种模型的常规配置对照模型常见输入分辨率相对参数量适用场景efficientnet-b02241xCPU 或小显存快速验证流程efficientnet-b1240约 1.2x入门首选能跑动efficientnet-b2260约 1.4x4G 显存左右的机器efficientnet-b3300约 2x大多数场景的均衡点efficientnet-b4380约 3.5x追求精度且数据量够efficientnet-b5456约 5x大显存 几千张以上数据efficientnet-b6528约 7x显卡好才考虑efficientnet-b7600约 9x数据量很大才值得我的建议是第一次跑通先用 b0 或 b1确认整个数据加载、训练、评估链路没问题再换 b3 提精度。别一上来直接跑 b716k 张花的量级未必撑得起这么大的模型而且训练时间会让你怀疑人生。输入分辨率还要和预训练权重对齐这个后面避坑章会细说。2.2 pretrained 和 freeze_layers这两个开关决定训练方式pretrained 参数控制是否载入官方 ImageNet 权重。True 就是标准的直推式迁移学习让网络从已经能识别 1000 类通用物体的特征出发再学花的细粒度差异False 就是随机初始化从零开始训练。freeze_layers 参数控制可训练范围True 表示只训练最后一层分类头前面卷积层全部固定参数不更新False 表示全量微调所有层都参与反向传播。这两个开关组合出来四种情况效果差异非常大pretrainedTrue freeze_layersTrue只训分类层训练快、显存小、不容易过拟合数据量少时最稳。pretrainedTrue freeze_layersFalse全量微调效果上限最高几千张数据一般选这个。pretrainedFalse freeze_layersTrue基本没意义卷积层随机初始化还不训练特征就是一堆噪声准确率会很差。pretrainedFalse freeze_layersFalse彻底的从零训练需要的数据量往往在十万张级别104 种花的 16k 张不太够泛化容易翻车。所以这个项目里最常用的组合是 pretrainedTrue再根据数据量决定 freeze_layers 取 True 还是 False。先冻结跑一轮看数据能不能收敛再解冻全量微调这是我在实际项目里经常用的两个阶段训练方式。2.3 参数集中管理config 里改这三个值就够了这个工程把模型名、预训练开关、冻结开关都做成了参数换模型不用改训练代码。我一般建议所有可调项集中放在一个 config 文件里方便复现也方便排错# config.py cfg dict( model_nameefficientnet-b3, # b0 - b7 可选 num_classes104, # 花的类别数换数据集要改 pretrainedTrue, # True 载入 ImageNet 权重 freeze_layersTrue, # True 只训分类层False 全量微调 input_size300, # 和 b3 预训练分辨率对齐 batch_size32, epochs60, )model_name 决定加载哪套结构换成 efficientnet-b0 就是最小模型同时要把 input_size 改成 224。num_classes 是分类头的输出维度换成自己的数据集时直接改成类别数。pretrained 和 freeze_layers 上面解释过这里不再重复。把配置集中到一起跑崩了先看 config 再看 log比到处翻代码找参数快很多。3. 数据与标签104 类花的目录结构、标签映射和换数据集套路3.1 数据集是怎么组织的标签在哪约 16k 张图分布在 104 个类别里平均每类一百多张。常见组织方式是根目录下每个类别一个文件夹文件夹名就是类别名图片按编号命名比如 0008.jpg、0038.jpg 这种。训练时用文件夹名做标签或者用一个 json 文件做 id 到花名的映射。这个工程的标签文件放在数据集目录里训练脚本会自动读取不需要手动标。项目正文里那一串图片文件名0008.jpg、0038.jpg、15104.jpg 这种其实是数据集里实际存在的样本训练时会按文件名去对应目录里找图。你拿到压缩包解压后数据路径配好直接跑训练脚本就行它会自动扫目录、划分数据集、开始训练。不需要你自己去凑训练集和验证集。3.2 用数据探针脚本先确认数据完整性我拿到这类工程第一步不是直接训练而是跑一段数据探针确认图片数量、类别数和文件完整度。这个习惯能省掉很多后面排查的时间import os from collections import Counter root data/flowers # 换成你的数据集根目录 labels [] for cls_name in sorted(os.listdir(root)): cls_dir os.path.join(root, cls_name) if not os.path.isdir(cls_dir): continue files [f for f in os.listdir(cls_dir) if f.lower().endswith((.jpg, .png, .jpeg))] labels.extend([cls_name] * len(files)) print(f{cls_name}: {len(files)} 张) print(类别数:, len(set(labels))) print(总图片数:, len(labels)) print(样本数量分布 Top5:, Counter(labels).most_common(5))这段代码按文件夹名统计每个类别的图片数量。如果某个类只有个位数图片训练时这一类的梯度信号会被其他类淹没如果总数和简介里说的约 16k 差太多多半是数据集没解压完整先补数据再训练。最后数出来的类别数必须和 config 里的 num_classes 一致不一致分类头维度和标签会直接对不上训练时 loss 会除以错误的类别数。3.3 换自己的数据集只需要动两个地方readme 里写了换数据集的做法。沿用这个工程的目录约定根目录下每个类别一个文件夹把图片放进去文件夹名就是类别名。然后改两个地方config.py 里的 num_classes以及 input_size 让它和当前选择的 EfficientNet 预训练分辨率对齐。有一个长期容易被忽略的问题类别不平衡。花数据集每类一百多张算是比较均衡的但换到工业场景比如缺陷检测、织物分类长尾分布很常见。这时候先别急着训练用上面那段探针脚本跑一下分布。如果最少的类别只有个位数样本建议先做扩充或者给少样本类别提高损失权重否则验证集上的 F1 会非常难看。数据质量决定模型上限这一点在图像分类里永远是真理。4. 训练配置优化器、交叉熵损失与 cos 余弦退火的参数落法4.1 优化器三选一Adam、SGD、AdamW 怎么挑项目里提供了 Adam、SGD、AdamW 三种优化器通过 config 参数切换。三者的性格差别很大优化器特点实际选型逻辑Adam自适应学习率收敛快超参不敏感默认首选出基线最快AdamWAdam 的权重衰减修正版泛化更好预训练模型微调时常用SGD需要手动调 momentum 和 lr收敛慢数据多、训练轮数长时上限更高我的经验是第一次跑先用 Adam 或 AdamW快速确认模型能收敛、数据没毛病。之后想提效果再切 SGD配合 momentum 0.9 和足够的训练轮数。SGD 对学习率敏感初始学习率设太大容易发散设太小收敛极慢属于调参玄学不建议新手直接挑战。4.2 模型初始化、冻结与分类头覆盖加载 EfficientNet 预训练模型之后最关键的一步是替换最后一层分类头。因为 ImageNet 预训练模型最后输出 1000 类这里要改成 104。PyTorch 里常用 torchvision 或 timm 的实现以 torchvision 为例from torchvision.models import efficientnet_b0, efficientnet_b3 import torch.nn as nn def build_model(cfg): if cfg[model_name] efficientnet-b0: base efficientnet_b0(weightsIMAGENET1K_V1 if cfg[pretrained] else None) in_features base.classifier[1].in_features base.classifier[1] nn.Linear(in_features, cfg[num_classes]) elif cfg[model_name] efficientnet-b3: base efficientnet_b3(weightsIMAGENET1K_V1 if cfg[pretrained] else None) in_features base.classifier[1].in_features base.classifier[1] nn.Linear(in_features, cfg[num_classes]) # b1,b2,b4-b7 同理 if cfg[freeze_layers]: for name, param in base.named_parameters(): if classifier not in name: param.requires_grad False return baseweights 参数在较新版本 torchvision 里用 IMAGENET1K_V1旧一点的写法是 pretrainedTrue。classifier[1] 是 torchvision EfficientNet 最后一层 Linear 所在位置不同库实现不一样比如 timm 的分类头属性叫 classifier原版 efficientnet-pytorch 库叫 fc这也是换库之后最常见的翻车点。freeze_layersTrue 时遍历所有参数把分类层以外参数的 requires_grad 置为 False。这样反向传播时只更新分类头显存占用小训练速度快。解冻时把 requires_grad 全部恢复 True 即可。4.3 损失函数与 cos 余弦退火两个关键参数 T_max 和 eta_min损失函数采用多类别交叉熵直接用 PyTorch 的 CrossEntropyLoss它内部把 LogSoftmax 和 NLLLoss 合在一起输入网络原始 logits 和整数标签即可不需要手动接 Softmax。对 104 类分类来说这是标准做法不用自己实现。学习率策略用 cos 余弦退火对应 CosineAnnealingLR。核心代码from torch import nn, optim from torch.optim.lr_scheduler import CosineAnnealingLR criterion nn.CrossEntropyLoss() if cfg[optimizer] adam: optimizer optim.Adam(model.parameters(), lr1e-3) elif cfg[optimizer] adamw: optimizer optim.AdamW(model.parameters(), lr1e-3, weight_decay0.01) elif cfg[optimizer] sgd: optimizer optim.SGD(model.parameters(), lr1e-2, momentum0.9, weight_decay1e-4) scheduler CosineAnnealingLR(optimizer, T_maxcfg[epochs], eta_min1e-5)T_max 表示余弦退火的半周期一般直接设成总训练轮数学习率会从初始值平滑下降到 eta_min。eta_min 是最小学习率设太小会导致后期几乎不更新设太大退火效果不明显1e-5 到 1e-6 是比较稳的范围。注意每个 epoch 结束调用一次 scheduler.step()如果每个 step 都调用T_max 就要按总 step 数来算两个都试过之后你会发现按 epoch 设更符合直觉。5. 常见问题与避坑从图片路径到指标全零的五条实记5.1 训练集精度很高但验证集指标几乎为零现象训练时 loss 下降正常训练集准确率能到 0.9但验证集上准确率极低recall 和 precision 大量为 0。原因最常见的是标签映射没有对齐。训练集和验证集用了不同的类别 id或者验证集读取时按文件名排序导致和标签错位。其次是数据划分泄漏验证集图片混进了训练集模型背了答案泛化自然崩。解决先输出几个样本的预测标签和真实标签人工核对确认 id 映射一致。然后检查数据划分逻辑按 StratifiedShuffleSplit 按类别比例抽样确保验证集类别分布和训练集类似。5.2 换了 EfficientNet 大模型之后显存直接爆掉现象b0 能跑换成 b3 之后 OOM或者 b5 连加载权重都在 16G 显存上溢出。原因分辨率从 224 涨到 456特征图尺寸平方级增长显存占用不是线性翻倍而是翻几倍。batch_size 还是原来那个 32必然爆显存。解决换大模型时同步把 batch_size 调小比如 b3 用 16b5 用 8。还不行就降低输入分辨率别为了凑 b5 硬开 456降到 380 配合预训练权重通常影响不大。显存真不够就用梯度累积累积 4 个 batch 再更新一次效果等价于大 batch。5.3 冻结层忘改训练半天 loss 不降现象pretrainedTrue 也开了num_classes 也改了训练了 20 个 epoch loss 几乎不动预测结果全是同一个类别。原因freeze_layers 本身就是 True卷积层全被冻结只剩下随机初始化的分类头在学。分类头从随机权重出发单靠它一个层很难拟合几十个类别loss 卡住不奇怪。解决这种情况先确认输出里是否打印了可训练参数数量看看除 classifier 以外有没有可训练层。想要全量微调就把 freeze_layers 设成 False想两阶段训练就先冻结跑几十轮再把 requires_grad 恢复降低学习率继续训练注意解冻后学习率要调小一两个数量级。5.4 验证集和训练集曲线差距越来越大现象训练集准确率往上走验证集准确率程先升后降典型过拟合。原因数据增强太弱、模型容量过大、数据集太小三者的综合结果。花数据集虽然是 16k 张但对 b3 以上模型仍不算充足。解决第一优先开数据增强随机裁剪、水平翻转、色彩抖动。增强过强也会导致验证集掉点需要平衡。其次是加 weight_decay 正则AdamW 自带解耦权重衰减取 0.01 起步。如果还是过拟合就换小模型 b1降低容量比强行正则更有效。5.5 余弦退火周期设置错误后期 loss 突然反弹现象训练前 2/3 段 loss 平顺下降后 1/3 段 loss 突然反弹验证集指标跟着抖动。原因scheduler.step() 调用次数和 T_max 不匹配。常见误用是每个 step 调一次 step()但 T_max 仍按 epoch 数设置余弦曲线一个 epoch 内就被强推到底之后进入平台期甚至学习率归零后反弹。解决统一按 epoch 调度在每个 epoch 结束后调用 scheduler.step()T_max 等于总 epoch 数。如果一定要按 step 调度T_max 要改写成总 step 数eta_min 不要设成 0留 1e-6 左右给后期微调空间曲线就平顺了。6. 评估闭环与结果验证从曲线、混淆矩阵到 json 指标定位短板类目6.1 曲线和四指标一起看别只看准确率训练结束后工程会在训练集和验证集上分别评估 loss 和准确率并绘制曲线同时输出混淆矩阵、recall、precision、F1 score、特异度等指标。对于 104 类分类准确率只能反映整体水平真正判断模型短板要看每个类别的 recall 和 precision。recall 低说明这个类的图经常被漏判precision 低说明其他类总是被误判进来两者都低说明这个类本身特征太弱或者样本太少。6.2 用 json 文件定位最差类别工程会把各类别指标写到 json 文件里一份 json 就是一张体检报告。我拿到 json 后会这样读import json with open(eval_metrics.json, r, encodingutf-8) as f: metrics json.load(f) # 实际字段名以输出的 json 为准常见是 per_class 或 class_metrics per_class metrics.get(per_class) or metrics.get(class_metrics) worst sorted(per_class.items(), keylambda kv: kv[1][recall])[:5] for cls, m in worst: print(cls, recall:, round(m[recall], 3), precision:, round(m[precision], 3), f1:, round(m[f1], 3))这段代码按 recall 排序找出最差的 5 个类别。这些类别往往是样本数少、形态相近或者拍摄角度差异大的花。定位到具体类别后再回看对应图片如果发现是标注噪声清洗数据后重训如果样本太少就针对这些类补充数据或做类别加权。混淆矩阵里对角线周围的高亮区域对应的就是容易混淆的花类组合这类问题靠换更大模型不一定有用先看数据本身是不是有偏。从那以后我每次跑分类实验都会强制走一遍完整流程数据探针确认完整性、打印模型确认分类头覆盖、小数据集跑几轮验证链路、训练完先看 json 里最差类别再决定要不要重训。走完这一遍才敢把结果拿出去。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

跨平台 Agent 技能管理中枢:一次编写,54+ AI 编程工具通用

跨平台 Agent 技能管理中枢:一次编写,54+ AI 编程工具通用

1. 为什么需要一个统一的 Agent 技能管理中枢 过去一年我陆续在五六个 AI 编程工具之间来回切换,从最早的单一补全插件,到后来支持 Agent 模式的各类 IDE、命令行工具、桌面客户端,越用越发现一个很尴尬的问题: 每个工具都有自己…

📅 2026/10/5 12:34:06
YOLO白萝卜检测数据集实战:1000张带标签图像从训练到避坑

YOLO白萝卜检测数据集实战:1000张带标签图像从训练到避坑

简介:本资源为面向YOLO系列算法目标检测任务的萝卜检测数据集,适合从事农业视觉识别、目标检测模型训练与验证的开发者及学生使用。数据集已按训练与验证需求划分完毕,并附带data.yaml配置文件,可直接适配yolov5、yolov8、yolov9、…

📅 2026/10/5 12:34:06
统一管理54种AI编程工具Agent技能:Skills Manager架构设计与实操

统一管理54种AI编程工具Agent技能:Skills Manager架构设计与实操

1. 为什么需要统一管理AI编程工具的Agent技能 1.1 从“工具爆炸”到“技能碎片化”的真实困境 过去两年,AI编程工具的数量增长非常快。我自己的开发机上,常用的就有Trae、Cursor、Windsurf、Cline、Roo Code、Continue、Aider、OpenHands、Goose、Kilo …

📅 2026/10/5 12:34:06
MORE NEWS

更多资讯

📰

轻型AI中台落地实践:消除重复录入与财务对账难题

前阵子帮一家成长型公司落地了一套“轻型AI中台”,目标是解决两个让他们头疼很久的问题:业务数据重复录入、财务月度对账困难。项目周期不到两个月,用的全是开源和轻量工具,没有搞那种大而全的企业级中台。这篇文章就把整个项目的…

📰

WorkBuddy接入Ollama本地模型:从无输出到70 tok/s的调优实战

大概半年前,我决定把 WorkBuddy 从云端 API 迁到本地大模型上。原因很简单:不想每写一段代码都提心吊胆盯着额度,也想试试完全离线跑 AI 编程助手是什么体验。结果第一天差点把我劝退——模型明明加载成功了,WorkBuddy 聊天窗口转…

📰

ChatGLM LoRA微调实战:从环境搭建到避坑验证

简介:本资源是一套面向AI工程师与NLP方向学习者的ChatGLM大模型微调实战工程包,聚焦LoRA、PEFT、量化训练等主流轻量微调技术在文本生成、语音识别、图像分类等多任务场景的落地实践。压缩包共148个文件,涵盖58个Python训练/推理脚本、36个Ju…

📰

AI辅助论文写作全流程实战:从需求说明书到初稿打磨

用AI辅助写论文这件事,我算是个老用户了——各大模型刚面向公众那阵,我就开始把它塞进自己改论文的工作流里。半年多下来,我前前后后帮人改了二十来篇稿子,硕士毕业论文、期刊投稿、本科课程论文都碰过,于是踩出了一些…

📰

生产级AI Agent工程化:七要素与七个决策点

AI Agent这词在技术圈火了大半年,真正上手做过生产级 Agent 的人其实没有想象中那么多。我接触过不少团队、也评测过不少开源项目,大家的状态基本一样:demo 跑得飞快,一聊到工程实现就开始卡壳。所谓工程实现,不是把 L…

📰

SAP委外采购订单创建:BAPI_PO_CREATE1核心参数与组件传参实战

做SAP集成的年头久了,你会发现一个规律:MM模块里但凡要用接口创建业务单据,采购订单永远排得到前三名,而采购订单里最容易被问到的场景就是委外加工。前阵子正好帮一个项目把“手工录入委外PO”改成“系统间接口自动创建”&#x…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬