新闻详情

新闻详情

首页 / 资讯中心 / 详情

Python+TensorFlow 2.3花卉识别:迁移学习与MobileNetV2实战全解析

发布时间:2026/10/1 3:58:19来源:尧图网络
Python+TensorFlow 2.3花卉识别:迁移学习与MobileNetV2实战全解析
简介基于Python与TensorFlow 2.3实现的花卉识别系统是一款面向高校期末大作业、课程设计及毕业设计的完整项目适合具备一定深度学习和Python基础的开发者参考或直接使用。项目围绕数据划分、模型训练、数据读取、模型测试及可视化窗口等模块展开整体识别率约97%具备清晰的目录结构和完整可运行代码。资源共27个文件包含Python源码、H5模型权重、XML配置、PNG/JPG图片样本、文本说明及依赖清单等压缩包约239.31MB。已有251人学习下载可作为花卉分类任务从数据处理到模型部署的完整参考。除核心代码外还提供数据集说明、readme文档、训练与测试脚本及模型文件便于理解实现思路并快速复现实验。项目界面简洁、操作便捷能够识别多种花卉具有较好的实际应用与演示价值。1. 用 Python TensorFlow 2.3 做花卉识别期末大作业为什么这个组合最稳期末大作业选 Python TensorFlow 2.3 做花卉识别这个组合看起来普通实际是最稳的一条路不自己从头搭卷积网络用现成的 MobileNetV2 预训练模型做迁移学习把大部分时间花在数据整理和参数调整上而不是被梯度消失、过拟合这些理论坑拖住。这篇笔记按一套最省事、也经得起答辩追问的课设流程来写从环境部署、数据集下载、模型构建到最后的图形界面把每一步细节和踩坑标出来。适合刚入门 Python 想拿一个完整 CV 项目练手、或者正在准备期末大作业答辩的人。照着跑一遍就能拿到可演示、可解释、有曲线有结论的结果。2. 搭建开发环境Python 版本选型与 TensorFlow 2.3 的兼容边界2.1 从 Python 安装开始版本差一个小数点都不行TensorFlow 2.3 的坑不在代码在环境。它的官方轮子明确支持 Python 3.5 到 3.8我建议直接用 Python 3.7这是网上能找到的 python 安装教程里报错最少的一个版本。装 Python 不推荐直接去官网装完就用那样多个项目共用一套 site-packages装到后面全是版本冲突。我一般用 Miniconda 或 Anaconda 建独立环境文件夹就叫 flower以后重复实验直接删掉重来比手动卸包省心得多。conda create -n flower python3.7 -y conda activate flower pip install tensorflow2.3.0创建环境时把 python3.7 显式写在命令里能避免 conda 默认解析到最新 Python 导致后面装 TF 时提示找不到匹配版本。pip 安装如果网络慢可以在命令末尾追加-i https://pypi.tuna.tsinghua.edu.cn/simple用国内镜像源下载会快很多这也是目前最稳妥的 python 下载方式。装完以后打开 VSCode按 CtrlShiftP 调出命令面板选择 Python: Select Interpreter把解释器指到 flower 环境。这个步骤就是许多人常说的 vscode python 环境配置。配置错会出现一种很迷惑的现象在终端里import tensorflow能成功在 VSCode 里点运行却报 ModuleNotFoundError。本质是编辑器用的解释器跟终端不是同一个选对虚拟环境后这个问题就消失了。2.2 安装 TensorFlow 2.3CPU 版、GPU 版与 CUDA 匹配TensorFlow 2.3 的安装分 CPU 和 GPU 两条线。CPU 版是最省事的不管有没有独立显卡都能跑缺点是训练稍慢GPU 版在 Windows 上建议直接安装带 GPU 后缀的包并且要匹配 CUDA 10.1 和 cuDNN 7.6版本错一位就会在 import 阶段报缺少 DLL 的错误。import tensorflow as tf print(tf.__version__) # 期望输出 2.3.0 print(tf.test.is_gpu_available()) # CPU 环境输出 False 也正常这段验证代码要放在项目最前面因为期末大作业后面所有代码都依赖这一个 import 能通过。如果输出版本号不是 2.3.0说明你当前环境装的是别的版本后续某些 API 调用会有差异。is_gpu_available()输出 False 不代表环境坏了CPU 也可以完成整个训练流程只是慢一些。GPU 环境最容易翻车的点是显卡太新。比如 RTX 30 系显卡普遍需要 CUDA 11 以上而 TensorFlow 2.3 固定要求 CUDA 10.1两者在驱动层面不兼容。遇到这种情况我建议别花时间折腾降级驱动直接改用 CPU 版先把流程跑通答辩时老师关注的是识别效果和实验过程不会因为你用 CPU 训练就扣分。能调通 GPU 算加分项调不通也完全不影响交付。提示把 conda 环境和 pip 包严格锁定后整个大作业期间不要再轻易执行pip install --upgradeTensorFlow 2.3 的 API 跟 2.10 之后版本有明显差异升级容易把已经跑通的代码弄坏。3. 准备花卉数据集102 类牛津花卉的下载、划分与标签对账3.1 数据集选哪个Oxford 102 还是自己爬图花卉识别题目的公开数据集主要有两个流派一个是直接用 Oxford 102 Flowers包含 102 个类别、约 8189 张图片每类 40 到 258 张不等标注文件是官方提供的答辩时引用它最有说服力另一个是自己用爬虫收集十几类花优点是类别少、图好凑缺点是要自己清洗大量重复图和错误标签反而比调模型更费时间。对期末大作业来说我强烈建议直接用 Oxford 102。类别多会让模型看起来更有分量官方标注还能省掉一整套人工校对工作。如果你的题目只要求识别 10 类花也不用换数据集按下面的脚本对 Oxford 102 抽一个子集就行模型最后 Dense 层的 102 改成你的类别数即可。对比项Oxford 102 Flowers自爬图片类别数102 类固定自己定标注准确性官方人工标注需要自己洗数据版权风险学术使用无风险图片来源复杂答辩说服力强有标准 benchmark弱需解释数据来源3.2 下载与按类别分目录数据准备的 Python 脚本下载到的 Oxford 102 压缩包解压后是一个名为 102flowers 的文件夹里面图片的命名规则是image_00001.jpg到image_08189.jpg文件名本身不携带类别信息。类别标签存放在 102labels.mat 文件里是 MATLAB 的 mat 格式要用 scipy 读取。所以数据准备的第一步是解析标签把图片按类别放进独立文件夹。import os import shutil import numpy as np from scipy.io import loadmat data_root flower_data raw_imgs 102flowers mat_path 102labels.mat target os.path.join(data_root, by_label) labels loadmat(mat_path)[labels].flatten() os.makedirs(target, exist_okTrue) for img_id, label in enumerate(labels, 1): src os.path.join(raw_imgs, fimage_{img_id:05d}.jpg) dst_dir os.path.join(target, flabel_{int(label):02d}) os.makedirs(dst_dir, exist_okTrue) shutil.copy2(src, os.path.join(dst_dir, fimage_{img_id:05d}.jpg)) print(总类别数:, len(os.listdir(target)))这段代码的核心是loadmat(mat_path)[labels].flatten()。mat 文件读出来是二维数组.flatten()把它压成一维之后就能按图片序号索引。循环里img_id从 1 开始对应文件名image_00001.jpglabel是类别编号label_{int(label):02d}格式化成两位数文件夹名保证 class 排序稳定。最终输出 102 个文件夹如果输出数值不是 102优先检查 mat 文件路径是不是写对了。按类别分好目录后还要按训练集和验证集划分。我一般固定按每类图片数量的 15% 抽到 val 目录并且设置随机种子保证每次划分结果一致否则你训练到一半重新跑脚本验证集变了之前的训练曲线就失去对照意义。import random import os import shutil from glob import glob split_dir os.path.join(data_root, split) for mode in [train, val]: os.makedirs(os.path.join(split_dir, mode), exist_okTrue) for cls in os.listdir(target): cls_path os.path.join(target, cls) imgs glob(os.path.join(cls_path, *.jpg)) random.seed(42) random.shuffle(imgs) n_val max(3, int(len(imgs) * 0.15)) for i, img in enumerate(imgs): mode val if i n_val else train dst os.path.join(split_dir, mode, cls, os.path.basename(img)) os.makedirs(os.path.dirname(dst), exist_okTrue) shutil.copy2(img, dst) print(训练集图片数:, sum(len(f) for _, _, f in os.walk(os.path.join(split_dir, train))))这里有两个参数值得注意。n_val max(3, int(len(imgs) * 0.15))里的max(3, ...)保证每类至少进验证集 3 张图防止某些类别数量太少导致验证集为空random.seed(42)则是玄学但管用的东西答辩时老师要求你重跑一次实验有固定种子就能复现给老师看。最后一行用 os.walk 统计训练集总数正常情况下应该是 7000 张左右。3.3 标签与文件名对不上的排查数据准备最常见的异常是图片数量跟 labels 数组对不上。Oxford 102 官网的图片包和标签包是分开下载的有时网盘里下载的压缩包版本不一致labels 数组是 8189 个元素实际图片却只有 8180 张运行脚本时会在后半段报 FileNotFoundError。排查方法是数一遍解压目录里的文件数量然后在脚本里打印 labels.shape 和实际图片列表长度做对比。如果数量差得很小一般是压缩包传输出问题重新从课程资源站或同学处拷贝一份完整压缩包即可不用自己补造图片。如果数量差得离谱比如图片有 1 万张说明下载的是更高版本的花卉数据集那份数据集标签格式可能不一样需要重新下载匹配的 labels 文件。提示数据准备整个阶段不要用移动硬盘直接作为目标目录复制 8000 多张小图在 USB 上可能只要几分钟但后期训练要反复读取文件放到本地 SSD 上会让每个 epoch 快很多。4. 构建模型并训练迁移学习的选型与三个关键参数4.1 为什么用 MobileNetV2 而不是自己搭 CNN 或 VGG16很多同学拿到这个题目第一反应是自己搭一个 CNN几层 Conv2D、几层 MaxPooling、最后接 Flatten 和 Dense。这个思路本身没问题但对期末大作业来说性价比很低因为从零训练的模型在 8000 张图上很难收敛到 80% 以上准确率而迁移学习可以轻松做到。答辩老师一定会问「为什么不用经典网络」答案很简单VGG16 有 1.38 亿参数ResNet50 也有 2500 万而 MobileNetV2 只有约 350 万参数在 CPU 和低端显卡上都能快速训练同时精度表现又不差。模型参数量ImageNet 预训练训练速度期末作业适配度自搭 CNN几百万到上千万无快低收敛难VGG161.38 亿有慢中答辩可讲MobileNetV2约 350 万有快高首选选择迁移学习的另一个理由是逻辑清晰它在 ImageNet 上已经学会了通用特征提取花卉的边缘、花瓣纹理、颜色分布这些底层特征可以直接复用你要训练的部分只是最后的分类器。这个思路在答辩时一两句话就能讲明白比解释多层卷积的感受野好讲得多。4.2 搭建模型两段式结构的核心代码迁移学习模型的搭建分为两步先加载预训练骨干网络并冻结它再在顶部拼接自己的分类层。这能避免预训练权重在训练初期被随机初始化的分类层反向传播破坏掉。import tensorflow as tf from tensorflow.keras import layers, models base_model tf.keras.applications.MobileNetV2( include_topFalse, weightsimagenet, input_shape(224, 224, 3), ) base_model.trainable False # 冻结骨干网络 model models.Sequential([ base_model, layers.GlobalAveragePooling2D(), layers.Dropout(0.2), layers.Dense(102, activationsoftmax), ]) model.compile( optimizertf.keras.optimizers.Adam(1e-3), losscategorical_crossentropy, metrics[accuracy], ) print(model.summary())这段代码里include_topFalse去掉 MobileNetV2 原有的 ImageNet 分类头只保留卷积部分GlobalAveragePooling2D把输出的 7×7×1280 特征图压缩成 1280 维向量相比 Flatten 更省参数也更不容易过拟合Dropout(0.2)给分类层加一点随机失活最后Dense(102)输出 102 个类别的概率分布。base_model.trainable False是关键它让骨干网络的权重在 fit 过程中不被更新第一轮训练只学习新加的分类层参数。如果要展示自己有更多思考可以在骨干网络冻结训练一轮之后解冻后面一部分层做微调。常见做法是把base_model.layers[:100]保持冻结只让靠后的层参与训练学习率降到 1e-5。这一步在答辩时作为「如何进一步提升精度」的加分项很有用。4.3 数据增强与训练参数这些数字是我踩坑后定下来的数据只有 8189 张训练集约 7000 张对 102 类分类任务来说每类平均不到 70 张直接硬训练很容易过拟合。数据增强是解决这个问题的标准手段TensorFlow 2.3 里用 ImageDataGenerator 就能实现不需要额外安装包。from tensorflow.keras.preprocessing.image import ImageDataGenerator train_gen ImageDataGenerator( rescale1./255, rotation_range20, width_shift_range0.2, height_shift_range0.2, zoom_range0.2, horizontal_flipTrue, ) val_gen ImageDataGenerator(rescale1./255) train_ds train_gen.flow_from_directory( flower_data/split/train, target_size(224, 224), batch_size32, class_modecategorical, ) val_ds val_gen.flow_from_directory( flower_data/split/val, target_size(224, 224), batch_size32, class_modecategorical, )rescale1./255把所有像素值从 0 到 255 归一化到 0 到 1使用预训练模型时这一步是必须的因为 ImageNet 预训练权重就是在归一化后的输入上训练出来的。rotation_range20表示图片最多旋转 20 度width_shift_range和height_shift_range为 0.2 表示水平垂直各平移 20%zoom_range控制随机缩放。验证集不能用任何增强只用归一化这样才能真实反映模型在未见过的图片上的表现。训练阶段的回调配置也直接影响结果我通常同时启用三个回调callbacks [ tf.keras.callbacks.ModelCheckpoint( flower_model.h5, save_best_onlyTrue, monitorval_accuracy, ), tf.keras.callbacks.ReduceLROnPlateau( factor0.5, patience3, verbose1, ), tf.keras.callbacks.EarlyStopping( patience6, restore_best_weightsTrue, ), ] history model.fit( train_ds, validation_dataval_ds, epochs30, callbackscallbacks, )ModelCheckpoint 靠monitorval_accuracy把验证集表现最好的权重保存下来训练完直接用这个文件做推理ReduceLROnPlateau 在验证集连续 3 个 epoch 不提升时把学习率减半避免后期震荡EarlyStopping 在连续 6 个 epoch 无提升时提前停止防止浪费时间。batch_size 在 4G 显存下建议 32CPU 训练也设 32显存不足就降到 16不需要硬撑。5. 避坑指南期末大作业里最常见的 5 个翻车点5.1 环境与依赖的 2 个坑网上那些免费 python 源码大全里的花卉识别代码大多是 TensorFlow 1.x 的写法直接抄进 2.3 环境会报各种 AttributeError。如果你找参考代码先确认代码里有没有tf.keras或keras.layers字样出现tf.Session()、placeholder的十有八九是旧项目不要浪费时间。现象一Windows 下安装完 TensorFlow 2.3 后 import 报错提示 DLL load failed。原因Python 版本与 TF 轮子不匹配或者缺少 Microsoft Visual C Redistributable 运行库。TensorFlow 2.3 在 Windows 上的编译依赖特定 VC 运行库很多干净系统默认没装。解决先确认当前 Python 是 3.6 到 3.8然后安装最新的 VC_redist.x64.exe重启后重新 import。如果还不行卸掉 tensorflow 重新pip install tensorflow2.3.0这次注意看输出的文件名有没有 cp37 或者 cp38 标记。现象二GPU 环境已经装好tf.test.is_gpu_available()返回 False。原因CUDA 版本不是 10.1或者 cuDNN 版本不是 7.6。TensorFlow 2.3 对这两个版本卡得很死装成 CUDA 10.2 或者 cuDNN 8.x 都没用。解决直接放弃 GPU换pip install tensorflow2.3.0CPU 版。CPU 版训练 30 个 epoch 大约 20 到 30 分钟完全在可接受范围内期末大作业的演示视频也可以提前录好不耽误。5.2 数据与训练的 3 个坑现象三训练时准确率很高但用自己的测试图预测结果却一塌糊涂。原因有可能验证集和训练集没有正确分开图片在 copy 时混进了同一个目录也有可能预测时的预处理和训练时不一致比如用 OpenCV 读图得到 BGR 三通道训练却用的 RGB输入数据的颜色通道顺序反了。解决检查by_label和split两个目录是否完全独立写预测脚本时统一用tf.keras.preprocessing.image.load_img读图它默认输出 RGB。如果非要用 cv2.imread就手动做一次通道转换img img[:, :, ::-1]这类数组切片就是干这个的。现象四模型训练了 10 个 epoch准确率一直停在 1% 左右完全不收敛。原因最常见的是标签与输出层不匹配。flow_from_directory的class_modecategorical要求 Dense 层输出维度等于类别文件夹数量如果你的 by_label 目录里有 102 个 folderDense(102) 是对的但如果你选了 10 类花的子集Dense 还写 102就会梯度混乱。解决打印model.summary()最后一行检查 Dense 输出数再打印train_ds.class_indices确认文件夹顺序与类别对应。改完后如果还不收敛把 ImageDataGenerator 的加强参数全部关掉只留 rescale 试一版确认能跑通再逐步加增强。现象五matplotlib 画混淆矩阵时中文标题变成方块。原因matplotlib 默认字体不支持中文系统里也没有合适的字体映射。解决在画图代码最前面加两行配置plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False这是最简单且通用的做法Windows 自带 SimHei 字体设置后中文能正常显示。答辩报告里如果有训练曲线和混淆矩阵截图这一步一定要提前处理否则截图里全是方框观感很差。6. 从模型到作品包一个预测界面并导出 exe6.1 用 PySide2 写最小预测界面训练完成的 h5 文件只是模型期末大作业要交付的是一个能用的系统。用 PySide2 或 PyQt5 做一个单窗口界面包含一个「选择图片」按钮和一个「识别结果」标签代码量不大但演示效果好。预测部分的预处理必须跟训练完全一致这一步最容易把之前所有工作毁掉。import sys import numpy as np import tensorflow as tf from PySide2.QtWidgets import QApplication, QLabel, QPushButton, QVBoxLayout, QWidget, QFileDialog model tf.keras.models.load_model(flower_model.h5) def predict_image(path): img tf.keras.preprocessing.image.load_img(path, target_size(224, 224)) arr tf.keras.preprocessing.image.img_to_array(img) / 255.0 arr tf.expand_dims(arr, axis0) pred model.predict(arr)[0] return int(np.argmax(pred))这段代码里tf.expand_dims把单张图片从 (224, 224, 3) 扩成 (1, 224, 224, 3) 的批次格式是因为model.predict要求第一维是样本数即使只有一张也要补上这个维度。/ 255.0对应训练时的rescale如果省掉这一步预测准确率会明显下降。界面其他部分用 QVBoxLayout 组装两个控件就行核心逻辑就这五行的量。6.2 导出 exe 与写答辩报告的验收清单交付给老师时很多学校要求能独立运行的 exe。用 PyInstaller 打包 TensorFlow 程序体积会到 500MB 左右这是正常现象不用费劲精简。打包命令很简单pip install pyinstaller pyinstaller -F -w app.py-F表示打成单个 exe 文件-w表示不显示控制台窗口。打包完成后务必在另一台没有 Python 环境的机器上双击测试TensorFlow 的模型文件路径、图片路径这类相对路径问题要在打包前处理成os.path.abspath或嵌入资源文件。答辩报告里建议放三样东西训练过程的 accuracy 曲线证明模型收敛过程正常混淆矩阵展示哪些类容易混淆并给出你的分析至少一组参数对比比如「增强前 78% vs 增强后 86%」这比最终准确率数字本身更有说服力。我自己做这个题目时最深的教训是环境搭了两天模型训练只花了半小时。后来每次启动新项目都先检查 Python 版本和三方库版本再也不会在环境上反复横跳。这个坑你提前知道就能把时间花在真正加分的数据分析和调参上。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

FCPX插件红屏与感叹号:版本兼容性排查与修复指南 2026/10/1 5:58:09

FCPX插件红屏与感叹号:版本兼容性排查与修复指南

1. 红屏和感叹号到底在告诉你什么:现象分类与快速自检做FCPX这一行,最怕的其实不是插件功能不够强,而是插件装上去之后,时间线里赫然一片红底、一个黄色感叹号,预览窗口怎么刷都是雪花一样的红屏。这个画面几乎每个剪辑…

阅读更多 →
RTX 5060分子对接与虚拟筛选实战:性能边界、工具链选型与参数调优 2026/10/1 5:58:09

RTX 5060分子对接与虚拟筛选实战:性能边界、工具链选型与参数调优

1. 先搞清楚RTX 5060在分子对接里到底扮演什么角色很多人一上来就问“RTX 5060能不能跑分子对接”,这个问题本身问得不够精确。分子对接和虚拟筛选是两件不同量级的事,前者是单个或少量配体与受体的结合姿态搜索,后者是成千上万个化合物批量过…

阅读更多 →
QuickReporter实战:基于模板替换的Word批量生成方案全解析 2026/10/1 5:58:09

QuickReporter实战:基于模板替换的Word批量生成方案全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
iOS 上运行 Windows 程序:Wine + FEX-Emu + DXMT 兼容层实战 2026/10/1 5:58:09

iOS 上运行 Windows 程序:Wine + FEX-Emu + DXMT 兼容层实战

1. 项目缘起:为什么要在 iOS 上折腾 Wine 和 FEX-Emu“Madeira”这个项目名,乍一看像是个地名,但在我们这圈子里,它指的是一套在 iOS 设备上运行 Windows 应用程序的兼容层方案。核心思路是把Wine、FEX-Emu和DXMT这三样东西串起来…

阅读更多 →
从卡尔曼滤波到信息滤波:多传感器融合的状态估计新思路 2026/10/1 5:58:08

从卡尔曼滤波到信息滤波:多传感器融合的状态估计新思路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
微码本质与安全更新:CPU底层补丁技术解析 2026/10/1 5:58:02

微码本质与安全更新:CPU底层补丁技术解析

1. 微码不是“固件”,也不是“驱动”:先划清三道技术边界很多人第一次听到“微码”(microcode)这个词,下意识会把它和BIOS、UEFI固件、CPU驱动甚至主板厂商的管理工具混为一谈。我刚接触这个概念时也犯过同样的错——在…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉