ARTICLE DETAIL

资讯详情

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

垃圾分类图像分类数据集实战:从选型清洗到模型训练避坑指南

垃圾分类图像分类数据集实战:从选型清洗到模型训练避坑指南 简介这份深度学习数据集面向图像分类入门与实战练习者聚焦垃圾分类场景中的瓶子识别任务可用于训练卷积神经网络完成塑料瓶、玻璃瓶、金属瓶等类别的自动判别适合课程设计、模型对比实验或迁移学习练手。资源包共约2000个文件以1998张jpg图像为主体另附1个py脚本与1个json类别文件压缩包大小39.65MB图像按类别目录存放同类样本归入同一文件夹便于直接接入ImageFolder等标准加载方式。数据已预先划分为训练集约2200张、验证集约200张、测试集约100张比例合理可支撑模型训练、调参与最终评估的完整流程。目前已有269人学习下载。借助清晰的目录结构与类别标注读者可快速搭建数据管道、复现分类基线并在此基础上尝试数据增强、类别不均衡处理与模型微调省去自行采集与清洗图像的繁琐环节。1. 垃圾分类图像分类数据集从「能跑通」到「能落地」差在哪垃圾分类的图像分类数据集核心就一件事把一张垃圾照片映射到「可回收物 / 厨余垃圾 / 有害垃圾 / 其他垃圾」这类标签上。听起来像入门练手项目但真正做过的人都知道公开数据集和真实场景之间隔着一道鸿沟——背景杂乱、光照突变、类别极度不均衡模型在验证集上 95% 的准确率换一批实拍图可能直接掉到 60%。这个方向适合两类人一是想找一个完整闭环练手图像分类算法的新手二是要做智能垃圾桶、分拣线视觉模块的工程师。下面我按「数据集怎么选 → 怎么清洗 → 怎么训练 → 怎么避坑」的顺序把这条链路讲透参数和命令都能直接抄。2. 垃圾分类数据集怎么选三类来源与选型对比2.1 公开数据集、自采数据、合成数据的取舍做垃圾分类图像分类数据来源无非三种选错了后面全是返工。公开数据集是最省事的起点。常见的做法是找 TrashNet 这类经典集合它把垃圾分成玻璃、纸、纸板、塑料、金属、其他六类图片数量在几千张量级背景大多是白纸或纯色桌面。优点是干净、标注质量高、拿来就能跑通 baseline缺点是太「实验室」模型学到的是「白背景 单个物体」一到真实场景就翻车。另一个常见来源是各类垃圾分类挑战赛放出的数据类别更贴近国内四分类但往往需要自己申请或从比赛页面获取格式不统一。自采数据是落地的必经之路。用手机或工业相机在目标场景拍比如小区垃圾桶投放点、分拣线传送带。自采的关键不是拍多少而是拍得「杂」不同时段的光照、不同角度、物体堆叠、部分遮挡、背景里有人有车。我一般建议每个类别先拍 300500 张四分类就是 12002000 张起步后续再按混淆矩阵补拍。合成数据适合补长尾类别。比如有害垃圾里的灯管、电池实拍样本少可以用抠图 背景融合的方式生成。但合成数据只能当补充不能当主力否则模型会学到合成痕迹而不是物体本身特征。数据来源典型规模优点主要风险公开数据集数千张开箱即用、标注干净场景单一迁移差自采数据每类 300贴合真实场景标注成本高、易漏标合成数据按需生成补长尾、可控域差异大需混训2.2 类别体系怎么定四分类还是细分类类别体系直接决定标注成本和模型上限。国内主流是「可回收物、厨余垃圾、有害垃圾、其他垃圾」四分类但实际落地时经常要再拆。比如可回收物里塑料瓶和纸箱的回收价值、处理工艺完全不同如果下游分拣线要分开那模型就得分。我的经验是先按下游动作定类别而不是按概念定类别。如果分拣线只需要「能回收 / 不能回收」两个动作就别做四分类二分类的准确率和鲁棒性会高一大截。反过来如果要做精细分拣那类别可能到 10 类以上这时候数据量必须跟上每类至少 500 张否则长尾类别必然拖后腿。还有一个容易被忽略的点「其他垃圾」是个筐。很多人把不好归类的全丢进去导致这个类内部差异极大模型学不动。正确做法是把「其他」再拆成几个视觉上一致的子类或者干脆在训练时给它更高的损失权重。2.3 数据格式与目录结构让训练脚本直接能读不管数据从哪来最后都要整理成训练框架能直接读的结构。图像分类最通用的是按类别分文件夹dataset/ ├── train/ │ ├── recyclable/ │ ├── kitchen/ │ ├── hazardous/ │ └── other/ ├── val/ │ ├── recyclable/ │ ├── kitchen/ │ ├── hazardous/ │ └── other/ └── test/ └── ...这种结构 PyTorch 的ImageFolder、TensorFlow 的image_dataset_from_directory都能直接读不用写自定义 Dataset。划分比例我一般用 7:1.5:1.5验证集和测试集都要保证每个类别都有样本不能出现某个类在验证集里一张都没有的情况。提示划分前先做一次全量去重。用感知哈希pHash或简单的文件 MD5把重复图片删掉。重复图会导致验证集泄漏准确率虚高这是最常见的翻车点之一。3. 数据清洗与增强把「脏数据」挡在训练之前3.1 用脚本做去重、坏图检测和尺寸统计拿到数据第一件事不是训练是体检。下面这段脚本做三件事检测损坏图片、按感知哈希去重、统计尺寸分布。import os from PIL import Image import imagehash from collections import Counter def audit_dataset(root): bad_files, hashes, sizes [], {}, [] for cls in os.listdir(root): cls_dir os.path.join(root, cls) if not os.path.isdir(cls_dir): continue for fname in os.listdir(cls_dir): fpath os.path.join(cls_dir, fname) try: img Image.open(fpath).convert(RGB) except Exception as e: bad_files.append((fpath, str(e))) continue # 感知哈希容忍轻微压缩差异 h str(imagehash.phash(img)) if h in hashes: print(f重复: {fpath} - {hashes[h]}) else: hashes[h] fpath sizes.append(img.size) print(损坏文件:, bad_files) print(尺寸分布 top5:, Counter(sizes).most_common(5)) audit_dataset(dataset/train)逻辑说明Image.open加convert(RGB)能同时暴露截断文件和四通道 PNGphash对缩放、轻微压缩不敏感适合找「同一张图存了多次」的情况。参数上如果发现大量图片尺寸差异极大比如有的 200×200有的 4000×3000不要急着统一缩放先看是不是混入了不同来源的数据必要时按来源分批处理。3.2 增强策略别把瓶子「增强」成别的类别图像分类的增强里翻转、裁剪、颜色抖动是标配但垃圾分类有几个特殊坑。水平翻转要慎用。瓶子、纸箱翻转后还是瓶子纸箱没问题但有些类别翻转后语义会变比如带文字的包装。如果类别里有依赖文字或方向的样本翻转前要确认。颜色抖动幅度别太大。垃圾分类里颜色是重要线索——厨余垃圾偏暗黄绿可回收塑料瓶颜色鲜艳。如果ColorJitter的hue给到 0.5模型可能把绿色瓶子认成厨余。我一般把brightness0.2, contrast0.2, saturation0.2, hue0.05作为起点。RandomResizedCrop 的 scale 下限别太低。如果scale(0.08, 1.0)一张瓶子图可能被裁得只剩瓶盖模型学到的就是局部纹理。垃圾分类建议scale(0.5, 1.0)保证主体基本完整。from torchvision import transforms train_tf transforms.Compose([ transforms.RandomResizedCrop(224, scale(0.5, 1.0)), transforms.RandomHorizontalFlip(p0.5), transforms.ColorJitter(brightness0.2, contrast0.2, saturation0.2, hue0.05), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), ])Normalize用的是 ImageNet 统计量如果你从零训练可以用自己数据算的均值方差但用预训练权重时保持一致更稳。3.3 类别不均衡加权采样还是损失加权垃圾分类数据几乎必然不均衡——其他垃圾一大堆有害垃圾没几张。两种处理方式加权采样WeightedRandomSampler让每个 batch 里各类别比例接近适合类别差距在 10 倍以内的场景。损失加权CrossEntropyLoss(weight...)给少数类更高惩罚适合差距极大的场景。我一般先用加权采样如果少数类召回还是上不去再叠加损失加权。import numpy as np from torch.utils.data import WeightedRandomSampler # labels 是训练集每个样本的类别索引 class_counts np.bincount(labels) class_weights 1.0 / class_counts sample_weights class_weights[labels] sampler WeightedRandomSampler( weightssample_weights, num_sampleslen(sample_weights), replacementTrue )replacementTrue表示有放回采样少数类会被反复抽到。注意num_samples设成训练集大小这样每个 epoch 的步数和普通训练一致方便对比。4. 训练垃圾分类模型从 baseline 到调参的完整命令4.1 选 backboneResNet 还是更新的图像分类模型2024 年之后做图像分类backbone 选择比几年前多得多。但垃圾分类这个任务数据量通常不大几千到几万张别一上来就上 ViT 大模型。我的建议数据 5000 张ResNet-18 / EfficientNet-B0用 ImageNet 预训练冻结前几层微调。数据 500050000 张ResNet-50 / ConvNeXt-Tiny / EfficientNet-B2。数据 50000 张且有 GPU 预算可以试 Swin-T 或 ViT-B/16但要注意小数据集上 ViT 容易过拟合。最新的图像分类模型不一定适合你的数据规模。我见过有人拿 ViT-H 在 3000 张垃圾图上训结果验证集准确率还不如 ResNet-18原因就是参数量和数据量不匹配。4.2 一个能直接跑的训练脚本下面用 PyTorch 写一个最小可跑的训练循环包含加权采样、余弦退火和验证。import torch import torch.nn as nn from torch.utils.data import DataLoader from torchvision import datasets, models, transforms device torch.device(cuda if torch.cuda.is_available() else cpu) train_ds datasets.ImageFolder(dataset/train, transformtrain_tf) val_ds datasets.ImageFolder(dataset/val, transformval_tf) # 加权采样 labels [s[1] for s in train_ds.samples] class_counts np.bincount(labels) sample_weights (1.0 / class_counts)[labels] sampler WeightedRandomSampler(sample_weights, len(sample_weights), True) train_loader DataLoader(train_ds, batch_size32, samplersampler, num_workers4) val_loader DataLoader(val_ds, batch_size32, shuffleFalse, num_workers4) model models.resnet18(weightsmodels.ResNet18_Weights.IMAGENET1K_V1) model.fc nn.Linear(model.fc.in_features, len(train_ds.classes)) model model.to(device) criterion nn.CrossEntropyLoss() optimizer torch.optim.AdamW(model.parameters(), lr3e-4, weight_decay1e-4) scheduler torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max30) for epoch in range(30): model.train() for x, y in train_loader: x, y x.to(device), y.to(device) optimizer.zero_grad() loss criterion(model(x), y) loss.backward() optimizer.step() scheduler.step() model.eval() correct total 0 with torch.no_grad(): for x, y in val_loader: x, y x.to(device), y.to(device) pred model(x).argmax(1) correct (pred y).sum().item() total y.size(0) print(fepoch {epoch}, val_acc {correct/total:.4f})关键参数说明lr3e-4是微调预训练模型的常用起点如果 loss 震荡就降到 1e-4weight_decay1e-4抑制过拟合T_max30和总 epoch 一致让学习率在一个训练周期内从峰值降到接近 0。batch_size32在 8GB 显存上跑 ResNet-18 的 224 输入基本够用显存不够就降到 16 并同步调小学习率。4.3 训练过程中该盯哪些指标别只看准确率。垃圾分类必须看混淆矩阵和每类召回。常见情况是整体准确率 90%但有害垃圾召回只有 40%——因为样本太少模型干脆全预测成其他类。from sklearn.metrics import confusion_matrix, classification_report all_preds, all_labels [], [] model.eval() with torch.no_grad(): for x, y in val_loader: x x.to(device) all_preds.extend(model(x).argmax(1).cpu().numpy()) all_labels.extend(y.numpy()) print(classification_report(all_labels, all_preds, target_namestrain_ds.classes)) print(confusion_matrix(all_labels, all_preds))如果发现某两类互相混淆严重比如塑料瓶和玻璃瓶说明特征区分度不够要么补这两类的难例要么在增强里加入更强的形变让模型关注材质纹理而不是颜色。5. 垃圾分类图像分类的避坑与排查清单5.1 验证集准确率很高实拍图一塌糊涂现象验证集 95%拿手机在垃圾桶前拍几张模型乱猜。原因训练数据和真实场景存在域差异。公开数据集多是白背景、单物体、正面拍摄实拍图背景杂乱、有遮挡、角度随意。解决在训练集里混入实拍图哪怕每类只有几十张也能显著拉近域距离。另一个办法是在增强里加入随机背景替换或 RandAugment让模型不过度依赖背景。5.2 某个类别召回率始终上不去现象有害垃圾召回 30%其他类都 90%。原因样本太少加权采样后每个 batch 里该类样本仍然有限模型没学够。解决先确认该类标注没有错标漏标然后叠加损失加权把该类权重设为其他类的 35 倍如果还不够用合成数据或从公开数据集里找同类样本补充。注意补数据后要重新划分验证集别把补充数据混进验证集。5.3 训练 loss 不降或震荡现象loss 在前几个 epoch 上下跳准确率不涨。原因学习率太大、batch size 太小导致梯度噪声大或者数据标注有大量错误。解决先把学习率降到 1e-4 试如果还震荡检查标注——随机抽 50 张看标签对不对。垃圾分类标注最容易错的是「其他垃圾」和「可回收物」的边界比如沾了油的纸盒到底算哪类标注前要统一规则。5.4 模型把「背景」当特征现象把垃圾桶放在桌上拍能识别放在地上就认不出。原因训练图里某个类别总是出现在特定背景比如厨余垃圾都在厨房拍模型学到了背景而不是物体。解决做背景多样性增强或者用 Grad-CAM 可视化模型关注区域确认它看的是物体还是背景。如果确实在看背景就要补拍不同背景下的同类样本。5.5 推理速度不达标现象模型准确率够但部署到边缘设备上帧率只有个位数。原因backbone 太大或者输入分辨率太高。解决先降输入分辨率224 降到 160 通常准确率掉 12 个点但速度翻倍再考虑换轻量 backboneMobileNetV3、EfficientNet-Lite最后才是量化。量化对垃圾分类这种颜色敏感任务要小心INT8 量化后颜色特征可能损失建议量化后在验证集上重新评估。6. 进阶技巧用混淆矩阵驱动数据迭代训练完一轮不是结束而是下一轮数据采集的开始。我习惯把混淆矩阵当成「数据采集指南」矩阵里非对角线的值就是模型分不清的类别对针对这些类别去补难例比盲目加数据有效得多。具体做法先跑一遍验证集得到混淆矩阵找出 top3 混淆对比如「塑料瓶 vs 玻璃瓶」「纸盒 vs 其他垃圾」。然后针对每一对去真实场景里专门拍这两类容易混的样本——比如透明塑料瓶和透明玻璃瓶放在一起拍沾油纸盒和干净纸盒对比拍。每类补 50100 张重新训练看混淆矩阵对应位置是否下降。import seaborn as sns import matplotlib.pyplot as plt cm confusion_matrix(all_labels, all_preds) sns.heatmap(cm, annotTrue, fmtd, xticklabelstrain_ds.classes, yticklabelstrain_ds.classes) plt.xlabel(pred) plt.ylabel(true) plt.savefig(confusion.png, dpi150)这个循环我一般跑 3 轮。第一轮用公开数据 少量实拍第二轮按混淆矩阵补难例第三轮做类别平衡和增强微调。三轮下来实拍场景的准确率通常能从 60% 提到 85% 以上。还有一个验证技巧留出一个「野生测试集」。从真实场景随机拍 100 张不参与任何训练和调参只在最后评估。这个集合的准确率才是你能对外说的数字。我吃过亏——早期只看验证集上线后被现实打脸后来养成习惯任何模型上线前必须过野生测试集这一关。最后说个习惯每次实验都记录数据版本、增强参数、学习率和混淆矩阵截图。垃圾分类这个任务数据改动对结果的影响远大于调参没有记录的话两周后你根本想不起来哪版数据对应哪个准确率。希望帮到你。本文还有配套的精品资源点击获取
返回列表