尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
PyTorch与VGG16实现鲜花分类的迁移学习实践
1. 项目概述用VGG16实现鲜花分类的快速入门方案这个项目展示了如何利用PyTorch框架和经典的VGG16模型快速搭建一个能够识别不同种类鲜花的图像分类器。对于刚接触深度学习视觉任务的新手来说鲜花分类是个理想的起点——数据集容易获取、类别区分度明显、模型效果直观可见。我选择VGG16作为基础模型不仅因为它的结构清晰适合教学更因为其预训练权重能帮助我们在小数据集上获得不错的效果。整个项目从环境配置到模型训练只需不到一小时但涵盖了PyTorch工作流的完整环节数据加载、预处理、模型定义、训练循环和性能评估。特别值得一提的是我会分享如何调整VGG16的全连接层来适配我们的分类任务这个技巧在迁移学习中非常实用。下面让我们从最基本的开发环境准备开始。2. 环境配置与工具准备2.1 PyTorch环境搭建推荐使用Anaconda创建独立的Python环境避免包冲突。对于大多数初学者CPU版本就足够运行这个项目conda create -n flower_cls python3.8 conda activate flower_cls pip install torch torchvision torchaudio如果你的设备配有NVIDIA显卡可以安装CUDA版本的PyTorch以获得更快的训练速度。在安装前先用nvidia-smi查看CUDA版本然后到PyTorch官网选择对应的安装命令。例如对于CUDA 11.3pip install torch1.12.1cu113 torchvision0.13.1cu113 torchaudio0.12.1 --extra-index-url https://download.pytorch.org/whl/cu113注意Windows系统下如果遇到DLL加载错误通常是CUDA环境变量问题。可以尝试在Anaconda环境中执行conda install cudatoolkit来补充运行时库。2.2 辅助工具安装除了PyTorch核心库我们还需要一些数据处理和可视化的工具包pip install matplotlib opencv-python pillow pandas tqdm建议使用Jupyter Notebook进行开发调试它能分段执行代码并即时显示图像结果pip install notebook jupyter notebook3. 数据集准备与预处理3.1 获取鲜花数据集本项目使用的是公开的Oxford 102 Flowers数据集包含102类常见鲜花约8,000张图像。通过torchvision可以自动下载from torchvision import datasets, transforms train_data datasets.Flowers102( rootdata, splittrain, downloadTrue, transformtransforms.ToTensor() )如果下载速度慢也可以手动从官网下载压缩包解压到项目目录下的data/flowers102文件夹中。数据集目录结构应该是data/ flowers102/ jpg/ image_00001.jpg image_00002.jpg ... labels.txt3.2 数据增强与标准化为了提高模型泛化能力我们需要对训练图像做随机增强处理。同时由于VGG16是在ImageNet上预训练的输入需要做相同的标准化from torchvision import transforms train_transform transforms.Compose([ transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.RandomRotation(15), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) val_transform transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ])实操技巧在资源有限的情况下可以减小RandomResizedCrop的尺寸到192甚至160虽然会略微降低精度但能显著减少显存占用。3.3 创建数据加载器使用PyTorch的DataLoader来批量加载数据设置合适的batch_size根据GPU显存调整from torch.utils.data import DataLoader batch_size 32 train_loader DataLoader( train_data, batch_sizebatch_size, shuffleTrue, num_workers4 ) val_data datasets.Flowers102( rootdata, splitval, downloadTrue, transformval_transform ) val_loader DataLoader( val_data, batch_sizebatch_size, shuffleFalse, num_workers4 )4. 模型构建与迁移学习4.1 加载预训练VGG16PyTorch的torchvision.models提供了预训练好的VGG16模型import torchvision.models as models model models.vgg16(pretrainedTrue)查看模型结构会发现原始的VGG16最后是一个1000类的分类器对应ImageNet类别数我们需要替换它import torch.nn as nn # 冻结所有卷积层的参数 for param in model.features.parameters(): param.requires_grad False # 替换最后的分类器 num_features model.classifier[6].in_features model.classifier[6] nn.Linear(num_features, 102) # 102个鲜花类别4.2 自定义分类头设计原始VGG16的分类器由三个全连接层组成。对于我们的任务可以保留这个结构但调整输出维度from collections import OrderedDict classifier nn.Sequential(OrderedDict([ (fc1, nn.Linear(25088, 4096)), (relu1, nn.ReLU(inplaceTrue)), (dropout1, nn.Dropout(p0.5)), (fc2, nn.Linear(4096, 4096)), (relu2, nn.ReLU(inplaceTrue)), (dropout2, nn.Dropout(p0.5)), (fc3, nn.Linear(4096, 102)), ])) model.classifier classifier经验分享全连接层的中间维度如这里的4096可以根据任务复杂度调整。对于较小的数据集可以减小到1024甚至512以减少过拟合风险。5. 模型训练与验证5.1 训练配置设置损失函数和优化器。由于我们冻结了卷积层只需要对分类器参数进行优化import torch.optim as optim criterion nn.CrossEntropyLoss() optimizer optim.Adam(model.classifier.parameters(), lr0.001) # 学习率调度器 scheduler optim.lr_scheduler.StepLR(optimizer, step_size5, gamma0.1)5.2 训练循环实现下面是完整的训练过程包含验证环节def train_model(model, criterion, optimizer, scheduler, num_epochs10): for epoch in range(num_epochs): model.train() running_loss 0.0 correct 0 total 0 for inputs, labels in train_loader: optimizer.zero_grad() outputs model(inputs) loss criterion(outputs, labels) loss.backward() optimizer.step() running_loss loss.item() _, predicted torch.max(outputs.data, 1) total labels.size(0) correct (predicted labels).sum().item() train_loss running_loss / len(train_loader) train_acc 100 * correct / total # 验证阶段 model.eval() val_loss 0.0 val_correct 0 val_total 0 with torch.no_grad(): for inputs, labels in val_loader: outputs model(inputs) loss criterion(outputs, labels) val_loss loss.item() _, predicted torch.max(outputs.data, 1) val_total labels.size(0) val_correct (predicted labels).sum().item() val_loss / len(val_loader) val_acc 100 * val_correct / val_total print(fEpoch {epoch1}/{num_epochs}) print(fTrain Loss: {train_loss:.4f} Acc: {train_acc:.2f}%) print(fVal Loss: {val_loss:.4f} Acc: {val_acc:.2f}%) print(- * 20) scheduler.step() return model model train_model(model, criterion, optimizer, scheduler, num_epochs10)5.3 训练过程可视化使用Matplotlib绘制损失和准确率曲线import matplotlib.pyplot as plt def plot_training(history): plt.figure(figsize(12, 4)) plt.subplot(1, 2, 1) plt.plot(history[train_loss], labelTrain Loss) plt.plot(history[val_loss], labelVal Loss) plt.title(Loss Curve) plt.legend() plt.subplot(1, 2, 2) plt.plot(history[train_acc], labelTrain Acc) plt.plot(history[val_acc], labelVal Acc) plt.title(Accuracy Curve) plt.legend() plt.show()6. 模型评估与优化6.1 测试集性能评估在完整训练后我们需要在测试集上评估最终性能test_data datasets.Flowers102( rootdata, splittest, downloadTrue, transformval_transform ) test_loader DataLoader( test_data, batch_sizebatch_size, shuffleFalse, num_workers4 ) def evaluate(model, loader): model.eval() correct 0 total 0 class_correct [0] * 102 class_total [0] * 102 with torch.no_grad(): for inputs, labels in loader: outputs model(inputs) _, predicted torch.max(outputs.data, 1) total labels.size(0) correct (predicted labels).sum().item() for i in range(labels.size(0)): label labels[i] class_correct[label] (predicted[i] label).item() class_total[label] 1 print(fOverall Accuracy: {100 * correct / total:.2f}%) # 打印每个类别的准确率 for i in range(102): if class_total[i] 0: print(fClass {i}: {100 * class_correct[i] / class_total[i]:.2f}%) evaluate(model, test_loader)6.2 常见问题与调优策略在实际训练中可能会遇到以下典型问题过拟合训练准确率高但验证准确率低解决方案增加数据增强如颜色抖动、随机擦除、加大Dropout比率、添加L2正则化、减少全连接层维度欠拟合训练和验证准确率都低解决方案解冻部分卷积层进行微调、增大模型容量、延长训练轮次类别不平衡某些类别的准确率显著低于其他解决方案使用加权交叉熵损失、对少数类过采样或多数类欠采样这里给出一个解冻部分卷积层进行微调的示例# 解冻最后两个卷积块 for param in model.features[24:].parameters(): param.requires_grad True # 使用更小的学习率微调卷积层 optimizer optim.Adam([ {params: model.features[24:].parameters(), lr: 1e-5}, {params: model.classifier.parameters(), lr: 1e-4} ]) # 重新训练 model train_model(model, criterion, optimizer, scheduler, num_epochs5)7. 模型部署与应用7.1 保存与加载模型训练完成后保存模型权重供后续使用torch.save(model.state_dict(), flower_vgg16.pth)加载时先重建模型结构再加载权重model models.vgg16(pretrainedFalse) num_features model.classifier[6].in_features model.classifier[6] nn.Linear(num_features, 102) model.load_state_dict(torch.load(flower_vgg16.pth)) model.eval()7.2 单张图像预测实现一个预测函数输入图像路径返回预测结果from PIL import Image def predict(image_path, model, class_names): image Image.open(image_path).convert(RGB) image val_transform(image).unsqueeze(0) with torch.no_grad(): output model(image) _, predicted torch.max(output, 1) return class_names[predicted.item()] # 加载类别名称 with open(data/flowers102/labels.txt, r) as f: class_names [line.strip() for line in f.readlines()] # 测试预测 result predict(test_rose.jpg, model, class_names) print(fPredicted: {result})7.3 性能优化技巧在实际部署时可以考虑以下优化模型量化减小模型大小提高推理速度quantized_model torch.quantization.quantize_dynamic( model, {nn.Linear}, dtypetorch.qint8 )ONNX导出跨平台部署dummy_input torch.randn(1, 3, 224, 224) torch.onnx.export(model, dummy_input, flower_vgg16.onnx)TorchScript序列化脱离Python环境运行scripted_model torch.jit.script(model) scripted_model.save(flower_vgg16.pt)8. 项目扩展方向这个基础项目可以进一步扩展多模型对比尝试ResNet、EfficientNet等其他架构比较它们在鲜花数据集上的表现细粒度分类在同一个花种内区分不同变种如不同颜色的玫瑰Web应用开发使用Flask或FastAPI构建在线识别服务移动端部署将模型转换为Core ML或TFLite格式开发手机应用主动学习让模型主动选择最有价值的样本进行标注减少标注成本一个简单的Flask Web应用示例from flask import Flask, request, jsonify from PIL import Image import io app Flask(__name__) app.route(/predict, methods[POST]) def predict(): if file not in request.files: return jsonify({error: No file uploaded}) file request.files[file] image Image.open(io.BytesIO(file.read())).convert(RGB) image val_transform(image).unsqueeze(0) with torch.no_grad(): output model(image) _, predicted torch.max(output, 1) return jsonify({class: class_names[predicted.item()]}) if __name__ __main__: app.run(host0.0.0.0, port5000)这个项目虽然从技术角度看不算复杂但它完整展示了深度学习图像分类任务的标准流程。在实际操作中我发现合理调整数据增强策略和学习率调度往往比更换更复杂的模型更能提升最终效果。另外对于这类细粒度分类任务在最后全连接层前添加一个注意力模块通常会有意想不到的效果提升。
RELATED

相关推荐

北大青鸟11SF系统调试硬约束与U盘升级避坑指南

北大青鸟11SF系统调试硬约束与U盘升级避坑指南

简介:本资源是北大青鸟JBF-11SF火灾报警控制器的官方级调试操作指南,面向消防工程调试人员、维保技术人员及系统集成工程师,解决现场设备配置、模式切换、权限管理与固件升级等核心实操难题。文档覆盖调试前软硬件准备(含串口线选…

📅 2026/10/28 14:18:16
基于YOLOv6的无人机高速抛洒物智能检测系统实践

基于YOLOv6的无人机高速抛洒物智能检测系统实践

1. 项目背景与核心价值高速公路货物抛洒是威胁行车安全的重大隐患。传统人工巡检方式存在效率低、覆盖范围有限、危险系数高等问题。我们团队基于无人机航拍和YOLOv6算法构建的这套智慧高速抛洒巡检系统,实现了对公路货物抛洒物的实时自动识别。实测表明&#xff0c…

📅 2026/10/28 14:18:16
Agent-Reach:LLM Agent运行时可达性能力地图

Agent-Reach:LLM Agent运行时可达性能力地图

1. “Agent-Reach”不是工具名,而是能力边界的具象化表达你第一次在GitHub上看到Agent-Reach这个词,大概率是在某个CLI工具的README里,或者某段Python调用日志的报错信息中——它不像requests或click那样是标准库或广为人知的包名&#xff0c…

📅 2026/10/28 14:18:16
MORE NEWS

更多资讯

📰

AI写代码实战复盘:提示词工程、代码审查与pytest全记录

上周末我干了一件一直想干的事:系统性用AI写代码,把一个小工具从零到一完整实现出来。不是拿AI补个函数、修个报错那种零敲碎打,而是把一个真实需求丢给大模型,让它当主要生产力,我只做需求定义、代码审查和测试验证。…

📰

工业软件AI落地实战:从知识工程到多Agent协作的出图助手

1. 工业软件AI落地的整体思路拆解1.1 为什么工业软件必须往“会思考”的方向走干了十多年工业软件这行,我亲眼看着CAD从二维绘图板变成三维参数化建模,又看着CAE从专家级分析工具变成实时仿真平台。但说实话,直到大模型出现之前,工…

📰

智能体运行时框架Flowing:用状态机与事件总线管理复杂交互

干智能体开发的同行应该都有过这种体验:功能demo跑得很顺,一上复杂交互就失控。多轮对话里上下文悄悄变脏,工具调用结果和决策逻辑纠缠在一起,一个分支状态漏处理,整个会话就像脱缰的野马。去年我做一个客服场景的智能…

📰

LSTM与Adaboost结合ABKDE优化时间序列预测

1. 项目概述:当LSTM遇上Adaboost与ABKDE在时间序列预测领域,传统LSTM神经网络虽然表现出色,但在处理复杂非线性关系和多变量耦合问题时仍存在预测区间不够精准的痛点。这个项目创造性地将三种技术融合:用LSTM捕捉时序特征&#xf…

📰

RT-DETR:实时目标检测的Transformer架构突破与应用

1. RT-DETR模型的技术演进与核心突破RT-DETR(Real-Time Detection Transformer)作为目标检测领域的新锐模型,其技术价值主要体现在三个维度:实时性突破、精度提升和架构创新。与传统CNN-based检测器相比,RT-DETR首次在…

📰

JSP招生管理系统开发实战与架构解析

1. 项目概述与核心价值JSP招生宣传管理系统7003b是一套基于Java Server Pages技术的教育行业信息化解决方案,专为各类教育机构设计开发。这个系统最吸引我的地方在于它提供了从程序源码到部署指南的完整技术栈支持,真正实现了"开箱即用"的开发…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

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

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

📞 💬