ARTICLE DETAIL

资讯详情

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

基于深度学习的垃圾识别分类系统:从迁移学习到Web部署实战

基于深度学习的垃圾识别分类系统:从迁移学习到Web部署实战 简介这套Python垃圾识别分类系统源码主要面向需要完成环保类课程设计或入门深度学习图像识别的开发者与学生。压缩包共28个文件大小约1.79MB核心为12个Python脚本既包含基于CNN和MobileNet的训练代码也提供测试脚本、窗口推理程序与依赖清单其余配套文件涵盖xml配置、txt说明、docx设计与计划文档、pdf风险管理报告、md说明以及pptx项目计划。目前已有336人学习。通过学习源码读者可以理解垃圾分类数据集的预处理思路、模型训练与验证流程、推理部署方式以及项目风险管理等工程文档的写法源码中附带的详细设计文档、项目计划书、风险登记册和模型链接也为二次开发或论文撰写提供了可用素材适合循序渐进地对照调参、训练与评估。整体上这份资源为从零开始搭建图像识别项目提供了完整的参考路径。1. 打开这份垃圾识别系统源码之前先想清楚你要拿它做什么市面上的垃圾分类需求这几年一直没凉过但真正能跑到生产环境、或者能拿来交课程设计/毕业设计的完整代码其实并不多。这份「一个Python写的垃圾识别分类系统源码.zip」正是冲着这个缺口来的它用Python的深度学习图像分类流程把「识别一张照片里的垃圾是什么类别」这件事从数据集准备、模型训练到Web界面部署拧成了一条可以落地的链路。你拿到手的不该是一堆只能看的.py文件而是能跑通、能换数据、能调参的一整套骨架。这个系统对三类人最有价值第一类是正在做课程设计或毕业设计、需要「能演示能讲清楚原理」的学生第二类是被老板丢来调研垃圾分类可行性的工程师想快速评估准确率和部署成本第三类是刚学完Python基础、想看看一个完整项目长什么样子的自学者。系统核心其实不神秘就是一个图像分类模型常见做法是用ResNet或MobileNet这类预训练网络做迁移学习再封装一个上传图片看结果的界面。但我要先说句大实话源码能跑通不等于你的环境能跑通。这个标题里带着zip意味着整个项目从Python版本到pip依赖版本都被锁过一次你在自己的机器上复现时八成会把时间花在配环境而不是改代码上。所以这篇笔记里我会先把一个能用的实现方案完整拆开再把我踩过的坑——Python版本适配、模型文件缺失、中文路径乱码这类——一条条摆出来。毕竟我是拿这类项目摸爬滚打过来的有些坑不写出来你能折腾一晚上。这份笔记不仅是项目说明书更是帮你做技术选型和避坑的路径图。2. 识别系统背后的技术链路从图像到分类结果中间发生了什么2.1 图像分类为什么是垃圾识别的主力方案而不是目标检测很多刚接触这个题目的人会问垃圾识别不应该是把瓶子、袋子框出来吗为什么要用图像分类这是一个特别关键的选型问题。这套系统里最核心的深度学习任务是图像分类而不是目标检测或实例分割。区别在于分类回答的是「这张图里最主要的东西是什么」检测回答的是「图里有哪些东西、分别在什么位置」。对于一份课程设计或一个初版验证系统用图像分类是完全正确的选择。理由有三个第一分类模型简单数据标注成本极低只需要给图片打标签第二训练和推理速度快CPU也能勉强跑起来第三源码里一般配套的是现成的垃圾分类数据集比如按厨余、可回收、有害、其他四类划分或者更细的几十类划分分类任务足够支撑演示。等你把分类链路跑通再往检测方向扩展也有清晰的路径。我一般会劝第一次做这个项目的人不要一上来就上YOLO这类检测模型。虽然检测能「框出」垃圾位置看起来更炫但它要求的数据标注成本直接翻好几倍后台源码量也大得多。对于没接触过深度学习的人来说把分类系统跑通、指标讲明白、界面能交互已经是一个完整且有说服力的项目了。2.2 迁移学习为什么是唯一现实的选择从零训练的成本算给你看一部分源码里其实保留了从零训练模型的入口但现实情况是你自己几乎不可能从零训练出一个可用的图像分类模型。这里先算一笔账。一个像样的垃圾图像分类模型如果从零训练ResNet50在单张消费级显卡上跑完十几个epoch训练轮次动辄要十几个小时以上这还只是训练时长更核心的问题是数据量——你需要上万张每类的标注图片否则模型根本学不到泛化特征会严重过拟合。对于拿到一份zip源码、想快速看到效果的人来说这两个条件基本都不满足。所以这套系统的正常配方是迁移学习加载在ImageNet上预训练好的模型权重比如ResNet50、MobileNetV2把最后一层全连接层替换成你自己的分类器然后只对这个「头」做微调。这样做的好处是你只需要几百张到几千张垃圾图片训练时间压缩到几十分钟甚至几分钟效果却比从零训练好得多。下面是典型的迁移学习声明代码import torchvision.models as models import torch.nn as nn # 加载预训练权重保持特征提取层不变 model models.resnet50(pretrainedTrue) # 获取全连接层的输入维度 num_features model.fc.in_features # 替换最后一层垃圾类别数 num_classes 4 model.fc nn.Linear(num_features, num_classes) # 冻结除最后一层之外的所有参数加快训练 for param in model.parameters(): param.requires_grad False for param in model.fc.parameters(): param.requires_grad True这里第一个关键逻辑是pretrainedTrue它会自动下载在ImageNet上训好的权重这是效果下限的保障第二个逻辑是requires_grad False把前面那些层锁死只训练新的全连接层。有些人会问为什么不全模型微调省时间当然是一方面但更重要的是垃圾图片和ImageNet的自然图像在底层特征边缘、纹理、颜色上是通用的锁住特征提取器不容易在少量数据上跑飞。如果你用MobileNetV2这类轻量网络替代ResNet50训练时间更长或更短要斟酌轻量网络在CPU服务器上也能玩得动。源码里换模型也简单把上面代码里的torchvision.models.resnet50换成torchvision.models.mobilenet_v2即可代价是准确率略降换来部署体积和速度的优势。这是我在实际项目里常做的替换因为课程设计答辩现场不一定有GPU。2.3 数据处理链路目录命名、标签映射与验证集划分垃圾识别系统源码拿到手之后你首先打开的大概率不是一个模型文件而是数据集的目录结构。数据集的组织方式直接决定了DataLoader数据加载器好不好写。最常见的做法是ImageFolder风格根目录下每个子文件夹名对应一个类别文件夹里的图片全部属于该类。dataset/ ├── train/ │ ├── 厨余垃圾/ │ │ ├── 101.jpg │ │ ├── 102.jpg │ ├── 可回收垃圾/ │ ├── 有害垃圾/ │ └── 其他垃圾/ └── val/ ├── 厨余垃圾/ ├── 可回收垃圾/ ├── 有害垃圾/ └── 其他垃圾/这种结构下PyTorch的torchvision.datasets.ImageFolder可以直接把目录名转成数字标签省去手写标签映射表。对应的数据加载代码长这样from torchvision import datasets, transforms # 训练集数据增强提高泛化能力 train_transform transforms.Compose([ transforms.Resize((224, 224)), transforms.RandomHorizontalFlip(p0.5), transforms.ColorJitter(brightness0.2, contrast0.2), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) # 验证集不增强只缩放和归一化 val_transform transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) train_dataset datasets.ImageFolder(rootdataset/train, transformtrain_transform) val_dataset datasets.ImageFolder(rootdataset/val, transformval_transform) # 分批加载shuffle打乱训练顺序 train_loader DataLoader(train_dataset, batch_size32, shuffleTrue, num_workers4) val_loader DataLoader(val_dataset, batch_size32, shuffleFalse, num_workers4)这里的四个参数值得你多看一眼Resize((224, 224))是ResNet的标配输入尺寸如果你换了模型输入尺寸要跟着换Normalize的三组数值是ImageNet的均值和标准差迁移学习中别乱改batch_size32在8GB显存下比较稳显存不够就先降到16num_workers4在Windows下要小心多进程加载偶尔会报错真遇到就改成0用主进程加载慢一点但稳定。还有个很多新手会忽略的问题验证集和训练集不能有交集。源码里如果从数据集里随机抽样划分还好但如果你自己收集图片加到训练集里一定要确保同一张图不会同时出现在训练集和验证集里否则验证准确率是虚高的答辩时一问就露馅。2.4 训练循环里必须监控的指标loss下降之外还要看什么很多从零学深度学习的同学在训练时只盯着一个数字精确率Accuracy。这个习惯在垃圾分类场景下会带来误导。原因很简单垃圾分类数据集的类别往往不平衡——「其他垃圾」的图片数量可能是「有害垃圾」的好几倍。这时候模型只需要把所有图片都预测成「其他垃圾」准确率也能轻松刷到70%以上但这种模型没有任何实用价值。我在调这类模型时训练循环里至少同时记录三个指标每个epoch的平均损失值、验证集准确率、每个类别的召回率。损失值告诉你模型有没有在正常收敛准确率给你一个直观的整体水平分召类别回的召回率能暴露「某个类别根本没学会」的问题。下面这段代码展示的是最朴素的训练循环骨架所有源码项目基本都逃不出这个框架for epoch in range(epochs): model.train() running_loss 0.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() * inputs.size(0) epoch_loss running_loss / len(train_dataset) print(fEpoch {epoch1}/{epochs}, Loss: {epoch_loss:.4f}) # 每个epoch结束后跑一次验证 model.eval() correct 0 total 0 with torch.no_grad(): for inputs, labels in val_loader: outputs model(inputs) _, predicted torch.max(outputs, 1) total labels.size(0) correct (predicted labels).sum().item() val_acc 100 * correct / total print(fValidation Accuracy: {val_acc:.2f}%)有两个细节值得你特别留意。model.train()和model.eval()的切换不是走形式——它们控制着Dropout和BatchNorm层的行为漏掉model.eval()的话验证集的准确率会被严重低估。with torch.no_grad()也是必须的推理时不计算梯度内存占用直接降一个量级否则验证几轮就可能内存溢出。这两个坑是我见过的最常见的「翻车」点。2.5 推理与部署的两种形态一行命令的CLI和可视化界面模型训练好后落地方式通常有两种。第一种是最简单的命令行推理输入一张图片路径输出预测类别和置信度。第二种是Web界面上传图片浏览器里显示分类结果。源码里通常两种都有但Web界面往往是项目的门面演示效果好不好全靠它。命令行推理的核心代码非常短实际上就是把训练时的预处理流程再走一遍from PIL import Image import torch def predict(image_path, model, class_names, devicecpu): image Image.open(image_path).convert(RGB) transform transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) input_tensor transform(image).unsqueeze(0) # 加batch维度 with torch.no_grad(): outputs model(input_tensor.to(device)) probabilities torch.softmax(outputs, dim1) # 转概率 confidence, predicted torch.max(probabilities, 1) return class_names[predicted.item()], confidence.item() # 调用示例 class_names [厨余垃圾, 可回收垃圾, 有害垃圾, 其他垃圾] model load_your_trained_model() # 加载你训练好的权重 result, conf predict(test.jpg, model, class_names) print(f预测结果: {result}, 置信度: {conf:.2%})注意这里的model.load_state_dict(torch.load(model.pth))在加载权重时必须保证模型结构和你训练时完全一致包括类别数、骨干网络名称差一个字母都会报错。置信度输出最好保留在界面上因为后端模型可能不确定这时你需要把低置信度的结果打回给用户确认这个交互环节是这类系统是否实用的关键。3. 跑通这套代码的完整过程从环境搭起3.1 环境准备用conda隔离环境是最不容易翻车的姿势一份工程源码最怕的就是环境不干净。我吃过这个亏一开始图省事直接在全局Python环境里pip install结果某个依赖包升级后原本运行的代码开始疯狂报错。从那以后我养成了一个习惯——每个项目一套虚拟环境尤其是这种还涉及深度学习库的项目。conda天然适合做这件事因为Python深度学习库对底层库如CUDA的依赖比较敏感用conda装能省下编译的苦。针对垃圾识别系统为了网络下载稳定离线也能用你通常要装unzip解压工具、Python 3.8到3.10之间的版本、pip包管理工具以及PyTorch系列。一般源码里会附带一个requirements.txt文件格式是库名加版本号。有条件的话我建议你从镜像源安装PyTorch比从国外源拉要快非常多。# 创建并激活独立环境 conda create -n garbage_classifier python3.9 -y conda activate garbage_classifier # 安装核心依赖以CPU版本为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu pip install flask pillow numpy matplotlib # 安装源码里的其他依赖 pip install -r requirements.txt # 解压源码并确认目录结构 unzip garbage_classifier.zip -d garbage_project cd garbage_project ls -la这里我用的是Python 3.9而非最新的3.12原因是PyTorch对最新Python版本的支持往往滞后源码里用到的某些旧版库在新Python下可能直接编译失败。选一个「生态里验证过的版本」比选「最新的版本」更重要。安装完成后建议先跑一个python -c import torch; print(torch.__version__)验证安装这一步能提前暴露80%的环境问题。3.2 数据准备源码自带数据集怎么用如何替换成自己的数据解压源码后你大概率会看到两类东西一类是train/和val/目录里面直接装好了分类好的图片另一类是data/目录下的原始压缩包或CSV标注文件需要你自己划分数据集。前者开箱即用后者需要你写个简单的脚本去划分。如果你的数据集是CSV标注格式比如文件名和标签分开两列那就需要先写脚本生成ImageFolder需要的目录结构。这里给一个通用的转换脚本无论你从哪个网站下载的垃圾分类数据集基本都能用这把「万能钥匙」整理出来import csv import os import shutil from pathlib import Path def csv_to_imagefolder(csv_path, src_dir, dest_dir, train_ratio0.8): # 读取CSV假设格式: filename,label with open(csv_path, r, encodingutf-8) as f: reader csv.reader(f) next(reader) # 跳过表头 pairs [(row[0], row[1]) for row in reader] # 创建目录结构 for split in [train, val]: for _, label in set(pairs): (Path(dest_dir) / split / label).mkdir(parentsTrue, exist_okTrue) # 按比例划分 class_files {} for fname, label in pairs: class_files.setdefault(label, []).append(fname) for label, files in class_files.items(): split_idx int(len(files) * train_ratio) for i, fname in enumerate(files): src Path(src_dir) / fname split train if i split_idx else val dst Path(dest_dir) / split / label / fname shutil.copy(src, dst) print(数据集转换完成) csv_to_imagefolder(garbage.csv, images_raw, dataset)写这类整理脚本最容易出问题的就是中文编码CSV文件如果是Excel里直接导出的编码多半是GBK而非UTF-8读取时要把encodingutf-8换成encodinggbk否则读出来的标签全是乱码最后模型的类别名也是乱码。另外shutil.copy是在复制文件如果你的源数据集很大建议改成os.replace配合两次遍历来做移动能省一半磁盘空间。关于划分比例这里用的是8:2。训练集比例太低会欠拟合太高又让验证集缺乏代表性。如果你发现某个类别的图片特别少比如还不到50张建议手工把它多复制几份到训练集里做数据扩充让模型在训练时能把这个类别的样本看到足够多次。3.3 训练自己的分类模型epoch、学习率与设备选择环境搭好、数据理清之后终于可以开始训练了。为求稳妥建议先不改任何参数直接用源码里的默认配置跑一遍目的是验证整条链路是通的。默认配置下第一次训练往往只需要几分钟在GPU上也可能在CPU上跑一旦能跑通说明环境没问题然后再开始逐步调参。这里以一个常用的训练启动脚本为例大家看到这类train.py时应该要能读懂里面每个参数的含义和制约关系import torch import torch.optim as optim # 训练参数 epochs 30 # 训练轮次 batch_size 32 # 批次大小 learning_rate 0.001 # 学习率 device torch.device(cuda if torch.cuda.is_available() else cpu) print(fUsing device: {device}) model create_model(num_classes4) model.to(device) criterion nn.CrossEntropyLoss() optimizer optim.Adam(model.fc.parameters(), lrlearning_rate) scheduler optim.lr_scheduler.StepLR(optimizer, step_size10, gamma0.5) for epoch in range(epochs): # ... 训练循环代码 ... scheduler.step() # 每10个epoch把学习率减半关于参数这是最核心的调参经验learning_rate是0.001还是0.0001直接决定你模型能不能收敛。对Adam优化器来说0.001是常用起步值但如果你发现loss剧烈震荡降到0.0001就好很多step_size10, gamma0.5表示每10轮学习率减半这是一种简单的学习率衰减策略能让模型后期稳定收敛batch_size决定看到多少张图才更新一次权重显存不够就调小但别太小16以下的batch在BatchNorm层上容易不稳定。3.4 界面启动与本地演示Flask应用的最小运行路径系统里通常包含一个Web界面常见的是用Flask写的代码比直接用C写界面要简单得多。启动它通常只需要一行命令但关键在于模型路径和静态文件路径的配置。# 启动Web应用 python app.py # 终端会显示 Running on http://127.0.0.1:5000浏览器打开http://127.0.0.1:5000后正常的界面应该长这样顶部标题「垃圾识别分类系统」中间一个上传按钮选择图片后点击识别页面下方显示预测类别和置信度。如果打开后画面错乱或者图片传不上来第一反应应该去看终端里有没有报错堆栈90%的问题会直接写在报错信息里。app.py里有个核心变量需要你确认模型路径。有的源码默认加载model.pth但你的模型文件名可能叫best_model_acc91.pth之类。找到Flask里加载模型的那一行把路径改成你训练出的真实权重的路径。另外有些源码的app.py会把类别编号写死这里的类别编号要和你的训练文件夹里的文件名顺序完全一致比如把「可回收垃圾」的编号写成0结果模型把编号0当成「其他垃圾」那识别结果就会全员错位这种错误最难排查因为训练和推理都显示正常只是结果错得离谱。4. 初版系统为什么常常「识别翻车」置信度之外的真实边界4.1 识别错误的第一类坑拿到一个训练好的模型无论是自己训的还是源码自带的先在几类代表性图片上试跑一遍再谈效果。我见过很多同学把模型一跑换张没见过的图就开始怀疑人生其实模型的能力边界在训练集分布里就已经划定了。最容易出现的问题集中在三类图片上。第一类是「背景干扰过大的图」模型的主干网络是在ImageNet上预训练的它对自然图像的背景纹理是敏感的如果你的垃圾图片是带复杂背景拍的模型很容易被背景里的桌子、草地「带偏」第二类是「多物体混杂图」比如一张照片里同时有一个塑料瓶和一张废纸分类模型只能给出一个答案它不会告诉你瓶子和纸各占多少第三类是「光照异常图」通过转成HSV色域再归一化可以缓解一部分但根本解法是训练时多做颜色抖动增强。4.2 置信度不是真理低置信度输出怎么办做系统的人总希望模型能崇高置信度地给出正确分类但实际测试时你会经常看到这样的输出结果预测结果是「可回收垃圾」置信度55%倒数第二的类别是「其他垃圾」置信度44%。这时候如果系统直接把55%的结果当成最终答案用户大概率会觉得这系统很蠢。比较好的处理方式是在界面上设置置信度阈值。如果置信度大于80%直接输出结果如果低于80%但高于50%显示两个候选类别让用户选择如果低于50%直接提示「无法确认请换一张更清晰的照片」。在推理代码里加上这个判断并不复杂却能显著提升用户对系统的信任感。坦白讲垃圾识别这种细分类任务类别间外观高度重叠时比如被压扁的易拉罐和铝箔纸置信度经常就在及格线边缘徘徊这种设计是很有必要的。4.3 类别不平衡导致的偏科训练时的隐藏陷阱回到训练环节一类容易被忽视的问题就是类别不平衡。你的数据集中「有害垃圾」可能极少几百张而「其他垃圾」几千张训练出的模型就会倾向于把不确定的图片统统归到大类里。这不是代码bug而是损失函数的设计问题。常见解法有两种第一种在数据层面做重采样对样本少的类别多复制几份可以给相关类别的图片做更强的数据增强第二种在损失函数层面调整权重给样本少的类别设置更高的loss权重让模型更在意它。下面是PyTorch里的写法from sklearn.utils.class_weight import compute_class_weight import numpy as np # 统计每个类别的样本数量 labels train_dataset.targets class_weights compute_class_weight( class_weightbalanced, classesnp.unique(labels), ynp.array(labels) ) class_weights torch.tensor(class_weights, dtypetorch.float32).to(device) # 用加权损失函数替换普通的CrossEntropyLoss criterion nn.CrossEntropyLoss(weightclass_weights)这里compute_class_weight会自动计算权重样本越少的类别权重越高。用了这个加权损失后低频类别的召回率通常会有明显上涨这是处理真实垃圾数据时的必备手段。但也要注意权重拉得过满少数类别勉强能保住但这个类别的训练拟合难度会显著增加整体准确率小幅度下降是正常的这不是缺陷而是取舍。4.4 过拟合与欠拟合从训练曲线读出真实问题最后再讲一个老生常谈但极其重要的问题——过拟合。垃圾识别数据集的规模通常不大几百张到几千张在这种规模下训练一个模型过拟合几乎是必然趋势。具体表现是训练集准确率一路涨到99%验证集准确率只到85%以后就开始震荡或者下降。「翻车」的常见画面是你看着训练集loss降得挺漂亮感觉模型要成功了一测验证集准确率反而在掉。这时说明模型开始「背题」而不是在「学规律」了。对策是配套的数据增强加狠一点随机旋转、随机裁剪、MixUp都属于这一类、提前终止做一份「后悔药」或者加Dropout。换一批数据重新跑这件事也是项目里的常态。提前终止的实现比想象中简单就是记录每个epoch的验证集准确率只有当它超过历史最佳时才保存一次权重。带这个逻辑的代码通常是这样的best_acc 0.0 best_model_path best_model.pth for epoch in range(epochs): train_one_epoch() acc evaluate() if acc best_acc: best_acc acc torch.save(model.state_dict(), best_model_path) print(fEpoch {epoch1}: 保存更优模型准确率 {acc:.2f}%)这段代码是全项目中最值得保留的设计。训练完你永远会拿到「验证集上最好的那一份」而不是最后一个epoch可能已经过拟合的权重。我一直建议只要你打算认真调试这个模型这份保留最优权重的代码就要存在它在后续效果对比里就是你的后悔药。5. 从能跑到能用提升识别效果的三条进阶路线5.1 路线一用更轻或更强的骨干网络替换如果你对现有模型的准确率不满意第一反应不应该是堆数据而是换骨干网络。从ResNet50换成ResNet101准确率通常能小幅上涨但这意味着训练时间变长约一倍从ResNet50换成EfficientNet-B4通常能在同样量级下拿到更好的效果。不过要注意这套垃圾识别系统的预处理尺寸要和网络匹配EfficientNet需要根据输入图片尺寸相应调整。在换网络时源码里涉及的改动点通常有三个模型声明那一行、输入预处理尺寸、全连接层输出的类别数跟数据集对齐。这三个改动点只要有一个遗漏你就会撞上tensor维度不匹配的报错。第一次改动建议先备份原始代码「后悔有药」才能放心折腾。5.2 路线二集成学习带来的准确率稳定提升当单模型效果已达85%左右上不去的时候我通常会尝试做集成学习。技术上最省事的是「权重平均法」和「预测结果投票法」。投票法实操起来很直白训练两个或三个不同骨干的模型比如一个ResNet50、一个MobileNetV2推理时分别预测取相同结果或平均值作为最终答案。实验结论通常是三个模型投票的出结果比任何一个单模型都稳但推理耗时也相应增长如果你要考虑在嵌入式的设备上包应用成本要算进去。5.3 路线三把分类系统升级成检测系统的最小改动路径如果你的项目做完分类后还想要更完整的演示效果想指出「垃圾在图里的位置」最务实的升级路径是换用YOLO系列或Faster R-CNN把它接到你当前的推理接口上。我把这称为「最小改动路径」保住你已经写好的Web界面和数据管理代码只把模型推理接口替换掉。Flask里只需要改一行调用界面完全不用动。这显然是下一阶段的玩法但把升级路线想清楚你的项目从第一天起就有了想象空间。整个系统的调优其实是建立在多次训练和验证的循环上的。我习惯每换一个网络或调一组参数就把这轮的验证结果记下来包括数据增强、学习率、准确率、是否过拟合等。当你积累了四五条记录后自然会找到你手头数据下的最优配置。这个习惯在答辩或交付时也很有用——你可以拿出实验记录来说明「为什么选这个模型、做了哪些对比」比空口谈原理有说服力得多。希望这份梳理能帮你在垃圾识别分类这个方向少走点弯路。垃圾识别这个方向看似小众但在智慧城市、绿色回收这些应用里一直有用武之地我把自己从这套源码里学到的经验和踩过的坑写在这里也是希望帮到你稳稳跑通第一个版本。本文还有配套的精品资源点击获取
返回列表