尧图精选

十类动物图片数据集:清洗、划分与YOLOv8分类训练实战

🕒 发布时间:2026/10/2 8:53:42 📁 来源:尧图网络
简介这份动物图像数据集包含约两万八千张图片覆盖狗、猫、马、蜘蛛、蝴蝶、鸡、羊、牛、松鼠、大象十个类别每类数量从两千到五千不等为图像分类与迁移学习提供现成训练语料适合深度学习初学者和生物图像识别研究者快速搭建实验。所有图片收集自公开网络并经人工检查部分样本刻意模拟手机拍摄等真实场景这批图像曾被用来评估从自制卷积神经网络到GoogLeNet等不同模型能够反映算法在实际图像中的泛化能力。数据包压缩后约五百七十MB内含两千个文件主体为一千四百余张JPEG图片与五百余张JPG图片另有少量PNG图像及一个Python预处理脚本便于划分数据集或格式转换。目前已有142人学习或下载适合需要快速验证网络结构或构建小型智能图像应用的人群。1. 10类动物JPG数据集先搞清楚它能训什么再碰代码第一次拿到“10个不同类别动物图片数据集28000张图像JPG”这种压缩包多数人的流程是解压、打开文件夹、瞪一眼缩略图然后开始写训练脚本。但真正决定这个数据集值不值得投入时间的不是28000这个总数而是10个类别各自的样本量、JPG的实际分辨率和压缩质量、以及标签到底有没有对齐。没有标注框和分割掩码的纯图像数据集第一定位永远是图像分类和预训练底座而不是检测或分割任务。这篇文章就按我实际处理这类数据集的顺序来写先扫描摸底再划分数据然后训练分类模型最后把用不上的图像资产转化成检索底库或检测预训练权重。2. 解剖28000张JPG类别分布、分辨率与坏图的检查脚本2.1 这个数据集的第一定位为什么是图像分类标题只承诺了“10个类别、28000张、JPG”没有提bounding box也没提json/xml/txt形式的标注文件。所以这组数据天然适合的任务是图像分类或者当作下游任务的预训练集。10类平均每类约2800张这个量级比CUB-200-2011鸟类数据集200类部分类只有几十张充裕得多足够把一个ResNet18或YOLOv8-nano分类模型从零开始训到可用的水平。但如果你想做的是动物检测或实例分割就得先确认压缩包里是否带了labels目录如果没带28000张图全部要人工标注按每张图框一个目标、每框耗时30秒算是200个小时以上的体力活。因此我拿到数据集后的第一反应不是写模型而是先确认边界条件图里只有单只动物还是多只背景是否干净类别名是否与文件名一一对应。这些直接决定后面训练策略。2.2 用PIL把整个数据集扫一遍类别、数量、尺寸和损坏文件网络上下载的动物图片数据集最常见的隐藏问题不是类别错误而是文件损坏、尺寸异常、透明通道残留。我会用一个脚本把全量JPG扫一遍输出每个类别的图片数、尺寸分布区间和打不开的文件列表。脚本逻辑很简单但能在训练前省掉大量排错时间。from pathlib import Path from PIL import Image, UnidentifiedImageError root Path(animals10) # 数据集根目录下辖10个类别子目录 for cls_dir in sorted(root.iterdir()): if not cls_dir.is_dir(): continue count 0 broken [] sizes [] for img_path in cls_dir.glob(*.jpg): count 1 try: with Image.open(img_path) as im: im.verify() # 只校验文件头与完整性不加载像素 sizes.append((im.width, im.height)) if im.mode ! RGB: broken.append(f{img_path.name}: mode{im.mode}) except UnidentifiedImageError: broken.append(f{img_path.name}: invalid jpg) if count: widths sorted(set(w for w, h in sizes)) heights sorted(set(h for w, h in sizes)) print( f{cls_dir.name:12s} images{count:5d} , fw(min/max){widths[0]}/{widths[-1]} , fh(min/max){heights[0]}/{heights[-1]} , fbroken{len(broken)} ) for item in broken[:10]: print( , item)脚本里用的Image.verify()只做完整性校验速度快适合扫28000张图但它不会真正解码像素内容所以校验通过不代表图能正常加载。想完全确认得在后续划分时再做一次im.load()试读。另外mode ! RGB这一行特别值得注意不少爬虫图是“JPG后缀的PNG”或者带alpha通道的RGBA图训练框架读取时会出现通道数不一致报错。上面脚本跑出来的成果物是一张表每个类的实际张数、最小/最大宽高、损坏文件数。拿到这张表才能判断要不要做类别均衡以及统一resize的短边定多少。2.3 JPG格式的三个隐性坑EXIF旋转、ICC色彩、重复压缩JPG不是一种行为一致的格式。第一坑是EXIF orientation手机拍摄的照片会在JPEG头里写一个旋转标记而PIL默认不会自动转正导致训练时同一张猫图在数据里可能是横的、也可能是竖的模型被迫学习方向特征。第二坑是ICC profile部分图像带非sRGB色彩配置OpenCV的cv2.imread会忽略它而PIL默认保留同一个数据集在不同框架下读出来的颜色都不一样。第三坑是反复压缩28000张图如果来源是社交媒体或爬虫很多已经经历过多次重编码高光区域会出现明显block artifact这对高精度分类模型是实打实的干扰。前两个坑可以在数据划分阶段一次性修掉做法是统一转存为RGB模式并写入标准orientation。转存要考虑任务预算如果原始尺寸是4000×3000这种级别转存时顺手缩到短边不超过1024能显著降低后续训练IO压力。from PIL import Image, ImageOps, ImageCms from pathlib import Path def normalize_jpg(src: Path, dst: Path, max_side: int 1024): with Image.open(src) as im: im ImageOps.exif_transpose(im) # 按EXIF旋转标记转正 im im.convert(RGB) # 丢掉alpha和灰度模式 im.thumbnail((max_side, max_side)) # 长边缩放到max_side以内 if icc_profile in im.info: try: im ImageCms.profileToProfile( im, im.info[icc_profile], sRGB, outputModeRGB ) except ImageCms.Error: pass im.save(dst, JPEG, quality90, subsampling1)这里的exif_transpose解决了方向问题convert(RGB)解决RGBA和灰度thumbnail按比例缩小而不变形ICC转换失败时直接忽略让PIL按内置sRGB处理。参数上max_side1024是分类任务的折中信息损失小显存占用可控quality90、subsampling1保留中高频纹理对鸟类、猫狗这类细粒度分类更友好。这一步跑完数据集的格式问题基本清零后面进训练框架就不会再翻车。3. 把10类JPG整理成可训练结构划分目录与标签准备3.1 先划分train/valid/test再动手训练很多初学者拿到数据集直接全量开训这是最容易出问题的做法。28000张图里如果混入重复图、相似图不做划分会导致验证集虚高。我一般按类别独立划分每个类别内部随机抽取保证10个类的train/valid/test比例一致避免某个类在验证集中缺席。划分完成后目录结构要符合常见训练框架的约定也就是train/狗、train/猫、valid/狗、valid/猫这样的组织方式。#!/bin/bash srcanimals10 # 原始数据集根目录 dstanimals_cls # 训练用根目录 mkdir -p $dst/train $dst/valid $dst/test for cls in $src/*/; do name$(basename $cls) mkdir -p $dst/train/$name $dst/valid/$name $dst/test/$name all_files($cls*.jpg) total${#all_files[]} n_train$((total * 80 / 100)) n_valid$((total * 10 / 100)) # 打乱顺序后按比例复制cp保证训练框架能稳定读取软链不确定 mapfile -t shuffled (printf %s\n ${all_files[]} | shuf) for f in ${shuffled[]:0:$n_train}; do cp $f $dst/train/$name/ done for f in ${shuffled[]:$n_train:$n_valid}; do cp $f $dst/valid/$name/ done for f in ${shuffled[]:$((n_train n_valid))}; do cp $f $dst/test/$name/ done echo $name: train$n_train valid$n_valid test$((total - n_train - n_valid)) done脚本里把all_files构造成数组再shuf是为了保证每个类内部随机且不重复取样shuf命令的随机种子可以另外指定方便复现实验。用cp而不是ln -s是因为部分Dataloader会把软链解析成绝对路径导致移动数据集后路径失效直接复制更保险代价是磁盘占用翻倍。28000张JPG如果统一缩过边总大小通常不超过3GB复制成本可以接受。这个脚本跑完animals_cls目录就是训练框架可以直接吃进的标准分类结构。3.2 用脚本抽样一个小数据集做快速验证全量28000张直接开训如果脚本有bug等发现时几小时已经浪费了。我的习惯是先抽一个小样本集把整个管道跑通——每个类别抽20张训练、10张验证总共300张先验证数据读取、模型前向、loss回传、保存权重这一串流程没问题再决定是否上全量。#!/bin/bash srcanimals_cls dstanimals_small for split in train valid test; do for cls in $src/$split/*/; do name$(basename $cls) mkdir -p $dst/$split/$name find $cls -name *.jpg | shuf -n ${1:-20} | while read -r f; do cp $f $dst/$split/$name/ done done done这个脚本可以反复执行shuf -n 20每次都取不同的20张等于天然做了多次抽样验证。小数据集跑一个epoch只需要几十秒能快速暴露两类问题一是某个类目录为空或文件名不规范导致Dataloader报错二是图像解码速度异常比如某张超大尺寸原图没被预处理脚本缩放过导致单张加载耗时数秒。按经验小样本验证通过之后再上全量训练中断的概率会大幅下降。3.3 如果将来要转检测标签文件的组织方式与工作量标题没有明确说带标注但很多做检测的人会想硬转。这里说清楚YOLO检测格式要求每张图像旁边放一个同名txt每个目标一行内容依次是类别id、归一化后的中心x、中心y、宽、高分辨率不同但归一化坐标与图像尺寸无关。一个标准的标签文件长这样。# cat_001.jpg 对应 cat_001.txt # 一行代表一个目标第二列以后是归一化坐标 0 0.5321 0.4412 0.3421 0.5214 0 0.7812 0.5933 0.2041 0.2917如果你确认数据集没有自带labels那转检测的唯一路径就是人工标注或自动标注加人工复核。自动标注可以用现成检测模型生成伪标签但10类28000张图里单目标图像约占多少、多目标占多少得先抽样判断。我的建议是如果最终目标是分类就不要被检测的扩展性绑架直接用前面划分好的训练结构推进如果确实要做检测优先抽2000张图做第一批人工标注验证类别边界清晰、目标尺度统一后再讨论全量标注。另外还要核对类别名和标注类别索引的对应关系这一步经常因为原始类别排序和训练yaml不一致而错位属于最常见但最难排查的玄学问题。4. 用YOLOv8在本地把这个数据集训成分类模型4.1 最小命令一条yolo classify train跑通全流程这里的“分类模型”没有必要写独立的PyTorch训练脚本。YOLOv8的classify子命令可以直接吃前面生成的animals_cls目录自动识别train/valid子目录无需额外写yaml。最小命令如下。yolo classify train \ modelyolov8n-cls.pt \ dataanimals_cls \ epochs60 \ imgsz224 \ batch64 \ projectrun_animals \ namecls_r224modelyolov8n-cls.pt是官方预训练权重10类28000张的数据量不足以让模型从随机初始化收敛到高精度加载ImageNet预训练权重比从零开始训快得多也不会出现前几个epoch loss完全不动的尴尬。data指向的是数据集根目录YOLO会以train和valid两个子目录名寻找数据所以第3章里划分目录时特意没有叫“val”而是叫“valid”就是为了对齐这个约定。imgsz224是224×224输入对JPG数据集来说性价比最高想追求更高精度可以试imgsz320或384但训练时间和显存都会明显上涨。batch64取决于显存越大的batch对分类任务越有利因为BatchNorm统计量更稳定。4.2 对28000张规模真正见效的6个参数同样一套命令参数不同效果能差出好几个点。下面列的是我在10类、28000张这种“类别少、每类样本多”场景下的默认参数组合。参数推荐值作用与理由imgsz224进阶可试320控制输入分辨率JPG压缩痕迹在小分辨率下影响较小320以上收益递减batch64或128分类任务batch越大BatchNorm越稳但受限于显存epochs60起步数据集不大60轮足够让模型收敛超过100轮大概率过拟合optimizerAdamW默认配合默认学习率对中等规模数据集最省心augment默认开启但关掉旋转动物图片旋转90度会引入上下颠倒的语义错误推荐mosaic和hsv增强seed固定随机种子保证每次实验可复现不然无法判断是数据问题还是随机性augment里最需要关掉的增强项是90度旋转和上下翻转。狗不会头朝下走路模型学到的特征如果依赖方向真实环境一换角度就崩。这个点我在鸟类识别项目里踩过开启旋转增强后验证集准确率高得离谱但测试一张倒置的鸟图时模型把它识别成了完全不同的类。另一个参数是workers在本地Linux环境可以设成CPU核数的一半Windows下设太高会反复崩线程属于平台差异不是模型问题。4.3 训练完成后的验证与单张推理训练结束后YOLO会在run_animals/cls_r224/weights/下生成best.pt和last.pt。不要急着拿last.pt上生产因为最后一轮往往不是验证集最优best.pt才是训练过程中的峰值模型。验证命令和单张推理命令分别是yolo classify val modelrun_animals/cls_r224/weights/best.pt dataanimals_cls yolo classify predict modelrun_animals/cls_r224/weights/best.pt sourcetest_imagesval命令会输出每个类别的top-1准确率混淆矩阵重点关注10个类里哪些互相混淆。按经验哺乳动物之间的混淆往往来自拍摄角度比如“狗”和“狐狸”在侧脸、背面角度下几乎无法区分鸟类内部混淆则多来自颜色纹理相似。单张推理输出文件会存到runs/classify/predict目录里面包含每张图的Top-5预测概率判断阈值一般设在0.5以上低于这个值说明该样本属于模型没见过的新场景需要纳入训练集或直接人工定性。5. 动物数据集避坑5个翻车现场与补救方案5.1 训练loss迟迟不降先怀疑坏图而不是模型现象第一个epoch loss还在1.0附近第二个epoch之后完全不下降甚至震荡上升。 原因数据集中存在大量损坏JPG、空白图或非动物图。爬虫类数据集常混入1×1像素占位图、验证码图、纯色背景图这类目标会持续拉低梯度质量。我在检查脚本里只统计了“打不开的文件”但“能打开但不是动物”的图需要单独挑出来。 解决先看训练日志里每个类的loss哪几个类loss不降就重点检查那类目录。快速做法是生成每张图的感知哈希并找出重复图再用CLIP或一个现成分类模型批量推理筛出置信度极低的样本人工看图。from PIL import Image, ImageFilter import imagehash # 计算感知哈希快速找出同图或近重复图 for img_path in sorted(cls_dir.glob(*.jpg)): with Image.open(img_path) as im: small im.resize((32, 32)).convert(L) small small.filter(ImageFilter.MedianFilter(size3)) h imagehash.phash(small) # 将h保存到列表后续按hamming距离聚类imagehash.phash对缩放和轻微压缩不敏感两张图只要内容相同无论尺寸和JPG质量如何哈希的汉明距离都会很小距离小于5基本可判定为重复图。清洗完再训练loss下降曲线会恢复正常。5.2 验证集指标好看、真实场景掉点背景泄漏现象验证集top-1准确率0.93但换成自己拍的真实照片后准确率不到0.5。 原因数据集的图像背景高度一致模型学到了背景纹理而不是动物本体。比如某类照片全是草地背景模型可能把“绿色像素比例高”当作判别特征。这种情况在从搜索引擎批量下载的图像里非常普遍。 解决训练时不要用全图直接resize输入而要做随机裁剪强制模型关注目标主体。YOLOv8分类默认带RandomResizedCrop但如果用了自定义Dataloader要把这个增强保留并调大裁剪范围比如scale(0.3, 1.0)。同时可以给背景增补样本从每类训练图中截取纯背景块作为负样本并打上一个“background”类让模型明确背景不是任何动物。5.3 读图颜色不对ICC profile与通道差异现象同一张图用PIL读出来颜色正常用OpenCV读出来泛绿或泛蓝训练出的模型在应用时对色调极敏感。 原因图像里嵌入了非sRGB的ICC profile不同库解释方式不同。更隐蔽的是部分JPG实际是CMYK模式保存的PIL转RGB时会做一次无色彩管理的直接映射导致颜色发闷。 解决在第2章的规范化阶段统一用PIL转RGB并做色彩管理转完用cv2.imdecode做一次抽样比对确认两个库读出来的像素均值差在5以内。生产环境读取图片时沿用同一套读取代码不要训练用PIL、推理用OpenCV。5.4 一开训练就OOM数据分辨率差异造成的显存翻倍现象显存明明够跑batch64但第一个迭代就OOM还没到模型加载阶段就崩了。 原因数据集中混入了超高清原图如6000×4000YOLO在不做预缩放的本地模式下会把原图先解码到内存再送到模型解码缓冲区和imgsz224的预期显存完全不在一个量级。 解决训练前先跑一遍第3章的规范化转存强制短边不超过1024。检查方法很简单预处理前后各跑一次w,h直方图把宽度超过2000的图占比从几十个百分点降到0。如果数据集已经分好目录转存时注意保持目录结构避免重新划分。5.5 中文目录和空格导致训练中断路径规范问题现象训练在数据加载阶段报错提示找不到文件或路径编码错误文件路径打印出来带中文或空格。 原因标注或者目录名使用了中文、全角字符、空格“狗/猫”这种目录在编码不匹配的容器里容易被解析成乱码。尤其YOLO在Windows下对中文路径支持不稳定。 解决数据集目录和类别名全部转成小写拉丁字母比如dog、cat、bird并严格使用下划线代替空格。这一步要最先做一旦训练中间切到Docker或云端环境再改路径会连带改标签文件工程量飙升。6. 榨干28000张JPG的价值三个进阶方向6.1 用分类权重做检测任务的预热分类模型训好后它学到的特征对后续检测任务有很大帮助。做法是把best.pt的骨干网络权重导出加载进YOLOv8检测模型作为预训练只随机初始化检测头。10类动物如果之后要做目标检测这个迁移路径能省掉大量从头预训练的时间。导出权重时要注意类别数量变化不会影响骨干层的shape只有分类头需要重置。6.2 用半监督筛选高置信样本扩充边界28000张图里未被充分利用的是那些“分类置信度不高”的样本。把全量数据用训练好的模型推理一遍挑出置信度在0.4~0.7之间的图人工复核后按类别重新放回训练集能修正原始数据集的标签噪声。这样做一轮迭代分类边界往往比重新训练一遍更干净也相当于对数据集本身做了一次清洗。6.3 把整个数据集变成图像检索底库分类任务之外这个数据集可以直接当作图像检索底库。把每张图过一遍骨干网络输出倒数第二层的特征向量用Faiss构建索引之后用户传一张“长得类似但类别未定义”的动物图系统通过向量检索返回最相近的已知样本。这比直接做多分类更灵活因为检索不要求类别集合封闭。我自己的习惯是把特征向量保存成npy文件并附上图像路径映射表不重复加载原图。这样28000张JPG就不仅是训练集而是变成一个可持续查询的本地知识库。这个方法在类别只有10个、但每类样本量大的数据集上效果最稳定。数据集的真实价值不在于一次性训完一个模型就封存而是通过反复清洗、扩充、复用让它持续为下游服务。我现在的做法是每个数据集到手都先做一次全量扫描和规范化再抽小样本试跑确认边界之后再放大投入。这套顺序帮我避开了绝大多数训练翻车希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →