首页/新闻资讯/正文详情

动物图片数据集JPG实战:10类28K图像从清洗到分类器训练

发布时间:2026/9/24 18:10:54 来源:云帆数科 栏目:资讯中心
动物图片数据集JPG实战:10类28K图像从清洗到分类器训练
简介这是一份面向计算机视觉初学者与模型训练爱好者的动物图片数据集覆盖狗、猫、马、蜘蛛、蝴蝶、鸡、羊、牛、松鼠、大象共10个类别适合用于图像分类、迁移学习及数据增强等实验场景。资源包共约2000个文件以jpeg与jpg图像为主另有少量png图片及1个py脚本压缩包整体约586MB主目录按类别分文件夹存放每类图像数量在2K至5K之间便于直接按标签读取与划分训练集、验证集。目前已有790人学习下载可作为课程作业、练手项目或算法对比的现成素材。读者可借此快速搭建多分类基线模型验证卷积网络、预训练微调等方案效果并利用脚本辅助完成数据整理与预处理省去自行爬取与清洗图像的繁琐环节。1. 动物图片数据集 JPG10类28K图像从拿到压缩包到跑通第一个分类器你从某个渠道拿到一个名为「动物图片数据集 JPG10类28K图像」的压缩包解压后是一堆按类别分好的文件夹每个文件夹里塞满 JPG。这时候真正的问题才刚开始这 28K 张图到底能不能直接喂给模型类别是否均衡图片尺寸是否统一有没有损坏文件、重复图、灰度图混在 RGB 里我见过太多人拿到数据集直接ImageFolder一把梭训练到一半 loss 不降回头查才发现某个类里混进了几十张标注错误的图。这个数据集的价值不在于「图多」而在于它是一个体量适中、类别清晰、适合做迁移学习与数据管线验证的起点——10 类、28K 量级单卡几十分钟能跑完一个 epoch既不会小到过拟合看不出问题也不会大到调一次参等半天。它适合三类人刚入门想完整走一遍「数据清洗→划分→训练→评估」的人想验证自己那套增强策略、采样策略是否有效的人以及需要一个小规模基准来快速对比不同 backbone 的人。下面我按自己实际处理的顺序把这条链路拆开讲。2. 先摸清家底10 类 28K 图像的目录结构与统计口径拿到任何图像数据集第一件事不是写模型而是写统计脚本。很多人跳过这步后面所有「玄学」问题都源于此。你需要知道每个类的样本数、图片宽高分布、通道模式、文件完整性。这些数字决定了你后面要不要做重采样、要不要统一 resize、要不要剔除异常样本。2.1 用 Python 扫一遍目录输出类别分布与尺寸直方图假设解压后的根目录叫animals10下面直接是类别文件夹。下面这段脚本会遍历所有 JPG统计每类数量、尺寸分布、通道数并标记无法读取的文件。import os from collections import defaultdict, Counter from PIL import Image import numpy as np root animals10 exts (.jpg, .jpeg, .JPG, .JPEG) class_count Counter() size_counter Counter() mode_counter Counter() bad_files [] widths, heights [], [] for cls in sorted(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): if not fname.endswith(exts): continue fpath os.path.join(cls_dir, fname) try: with Image.open(fpath) as im: w, h im.size mode im.mode im.verify() # 检测截断文件 except Exception as e: bad_files.append((fpath, str(e))) continue class_count[cls] 1 size_counter[(w, h)] 1 mode_counter[mode] 1 widths.append(w) heights.append(h) print(类别分布:, dict(class_count)) print(通道模式:, dict(mode_counter)) print(宽 min/median/max:, np.min(widths), np.median(widths), np.max(widths)) print(高 min/median/max:, np.min(heights), np.median(heights), np.max(heights)) print(最常见尺寸 top5:, size_counter.most_common(5)) print(损坏文件数:, len(bad_files)) for p, e in bad_files[:10]: print( , p, e)逻辑说明im.verify()是关键它不真正解码像素只检查文件头与数据完整性速度快能在训练前把截断的 JPG 揪出来。size_counter用(w,h)元组做键能直接看出尺寸是否统一。参数上exts我特意把大小写都列上因为很多数据集从不同来源拼凑扩展名大小写混乱是常态。跑完后你大概率会看到两种情况之一要么尺寸高度统一比如都是 224×224 附近说明已经过预处理要么宽高差异很大那 resize 策略就得认真设计。类别分布如果最大类与最小类差距超过 2 倍后面训练时就要考虑带权采样或类平衡增强。2.2 判断是否需要清洗重复图、灰度图、极小图三类问题统计结果里如果mode_counter出现L或RGBA说明混入了灰度图或带透明通道的图。灰度图直接转 RGB 即可但透明通道要小心——直接convert(RGB)会把透明区域填成黑色如果原图主体边缘依赖透明可能引入伪影。常见做法是先合成到白底再转 RGB。极小图比如宽或高小于 64是另一个坑。它们 resize 到 224 后会严重模糊相当于给模型喂噪声。我一般会设一个阈值把短边小于 64 的图单独列出来人工抽看或直接剔除。重复图检测用感知哈希pHash比 MD5 更实用因为同一张图可能被存成不同质量。下面这段用imagehash库快速找近似重复import imagehash from PIL import Image import os hashes {} dups [] 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: with Image.open(fpath) as im: h imagehash.phash(im.convert(RGB)) except Exception: continue if h in hashes: dups.append((fpath, hashes[h])) else: hashes[h] fpath print(近似重复对数量:, len(dups)) for a, b in dups[:10]: print(a, -, b)参数说明phash的默认 hash 尺寸是 8对轻微缩放、压缩不敏感。如果重复对很多说明数据集里存在同一张图的多个副本训练时必须去重否则验证集可能泄漏训练集内容指标虚高。3. 划分训练/验证/测试集别让同一张图跨集出现数据划分看似简单但图像数据集最容易翻车的地方就在这里。如果你先随机划分再去做增强或者划分时没考虑重复图验证集指标会好得离谱上线就崩。正确顺序是先去重再划分最后各自做增强。3.1 按类别分层抽样的划分脚本与固定随机种子分层抽样保证每个类在训练/验证/测试中的比例一致避免某个类在验证集里一张都没有。下面脚本按 7:1.5:1.5 划分并固定种子保证可复现。import os, shutil, random from collections import defaultdict random.seed(42) src_root animals10_clean # 去重清洗后的目录 dst_root animals10_split split_ratio {train: 0.7, val: 0.15, test: 0.15} for cls in os.listdir(src_root): cls_dir os.path.join(src_root, cls) if not os.path.isdir(cls_dir): continue files [f for f in os.listdir(cls_dir) if f.lower().endswith((.jpg, .jpeg))] random.shuffle(files) n len(files) n_train int(n * split_ratio[train]) n_val int(n * split_ratio[val]) splits { train: files[:n_train], val: files[n_train:n_train n_val], test: files[n_train n_val:] } for split, flist in splits.items(): out_dir os.path.join(dst_root, split, cls) os.makedirs(out_dir, exist_okTrue) for f in flist: shutil.copy(os.path.join(cls_dir, f), os.path.join(out_dir, f)) print(cls, total, n, train, len(splits[train]), val, len(splits[val]), test, len(splits[test]))逻辑说明random.seed(42)是后悔药没有它你第二次划分结果不同实验无法对比。按类循环保证分层。shutil.copy保留原文件避免后续增强污染原始数据。参数上7:1.5:1.5 适合 28K 量级——训练集约 19.6K验证和测试各约 4.2K足够评估。3.2 用 ImageFolder 和 DataLoader 验证划分结果划分完别急着训练先用ImageFolder加载一遍确认每个 split 的类别数和样本数符合预期同时检查是否有空文件夹。from torchvision import datasets, transforms from torch.utils.data import DataLoader tf transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), ]) for split in [train, val, test]: ds datasets.ImageFolder(os.path.join(dst_root, split), transformtf) dl DataLoader(ds, batch_size32, shuffleFalse, num_workers4) x, y next(iter(dl)) print(split, classes, len(ds.classes), samples, len(ds), batch, x.shape, y.shape)参数说明Resize(256)加CenterCrop(224)是验证/测试阶段的标准做法先缩到短边 256 再中心裁剪保留主体。训练阶段则应该用RandomResizedCrop(224)做增强。num_workers4根据你机器 CPU 核数调整太少会拖慢数据加载太多会争抢资源。如果某个 split 的len(ds.classes)不是 10说明有类别文件夹为空或命名不一致回去检查目录。4. 训练管线搭建从增强策略到类别不平衡处理数据准备好了接下来是训练管线。这个数据集 10 类 28K单卡完全能跑但增强策略和采样策略直接决定最终精度。我一般先用一个轻量 backbone 跑通再换大的。4.1 训练增强与验证增强的差异配置训练增强要「狠」验证增强要「稳」。下面是我常用的配置针对动物图片颜色抖动和随机裁剪对纹理、姿态变化有帮助。from torchvision import transforms train_tf transforms.Compose([ transforms.RandomResizedCrop(224, scale(0.6, 1.0)), transforms.RandomHorizontalFlip(p0.5), transforms.ColorJitter(brightness0.3, contrast0.3, saturation0.3, hue0.05), transforms.RandomRotation(15), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), ]) val_tf 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]), ])参数说明scale(0.6, 1.0)允许裁到原图 60% 区域模拟遮挡和不同距离。hue0.05要小动物毛色是重要特征色相大幅偏移会破坏语义。RandomRotation(15)对动物姿态合理但别超过 30 度否则背景出现黑边。Normalize 的均值方差是 ImageNet 统计值用预训练权重时必须一致。4.2 类别不平衡时的 WeightedRandomSampler 用法如果第 2 章统计发现最大类是最小类的 2 倍以上直接训练会让模型偏向多数类。两种解法带权采样或类权重损失。带权采样更常用因为它让每个 batch 内类别更均衡。import numpy as np from torch.utils.data import WeightedRandomSampler from torchvision import datasets train_ds datasets.ImageFolder(os.path.join(dst_root, train), transformtrain_tf) targets [s[1] for s in train_ds.samples] class_counts np.bincount(targets) class_weights 1.0 / class_counts sample_weights [class_weights[t] for t in targets] sampler WeightedRandomSampler( weightssample_weights, num_sampleslen(sample_weights), replacementTrue ) train_loader DataLoader(train_ds, batch_size32, samplersampler, num_workers4)逻辑说明class_weights是类别频率的倒数样本权重取其所属类的权重。replacementTrue表示有放回采样少数类会被重复抽到。num_samples设成训练集大小保证一个 epoch 见到的样本数与原来一致。注意用了 sampler 就不能再设shuffleTrue两者冲突。4.3 用预训练 ResNet 跑通第一个 baseline管线搭好后先用 ResNet18 或 ResNet50 跑一个 baseline。冻结 backbone 先训分类头再解冻微调是省时且稳的做法。import torch import torch.nn as nn from torchvision import models device torch.device(cuda if torch.cuda.is_available() else cpu) model models.resnet18(weightsmodels.ResNet18_Weights.IMAGENET1K_V1) for p in model.parameters(): p.requires_grad False model.fc nn.Linear(model.fc.in_features, 10) model model.to(device) criterion nn.CrossEntropyLoss() optimizer torch.optim.Adam(model.fc.parameters(), lr1e-3) for epoch in range(5): 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() print(epoch, epoch, done)参数说明weightsIMAGENET1K_V1加载预训练权重别用pretrainedTrue旧写法。冻结所有参数只训fc学习率可以设大一点 1e-3。跑 5 个 epoch 后解冻全部学习率降到 1e-4 再微调。如果显存够batch size 可以上 64 或 128配合学习率线性缩放。5. 避坑与排查处理这个数据集时最常见的 5 个翻车现场这一章是我自己踩过的坑按「现象 → 原因 → 解决」写你遇到时可以直接对照。现象一训练 loss 震荡不降验证精度卡在 10% 左右。原因通常是标签与文件夹名不对应或者ImageFolder读到的类别顺序和你以为的不一致。解决打印train_ds.class_to_idx确认映射关系再抽几张图连同标签可视化人眼核对。现象二验证精度异常高测试集却崩了。原因是重复图跨集泄漏或者同一张图的增强版本同时出现在训练和验证。解决划分前做 pHash 去重划分后再用哈希交集检查三个 split 之间是否有重复。现象三训练时突然报OSError: image file is truncated。原因是部分 JPG 下载不完整。解决第 2 章的im.verify()能提前发现如果已经开训在 Dataset 的__getitem__里加 try/except 跳过坏图并记录日志。现象四GPU 利用率低训练速度慢。原因多半是num_workers设太小或磁盘 IO 瓶颈。解决num_workers设为 CPU 核数的 2/3如果图片存在机械硬盘先拷到 SSD开启pin_memoryTrue。现象五换了 backbone 后精度反而下降。原因可能是新 backbone 的输入归一化参数不同或者学习率没重新调。解决确认每个 backbone 对应的预处理配置微调时先用小学习率 warmup 几个 epoch。注意这五条里重复图泄漏和标签错位是最隐蔽的建议在正式训练前花十分钟跑一遍检查脚本比训到一半再回头查省事得多。6. 把 28K 图像用出更高价值渐进式分辨率训练与错误分析baseline 跑通后如果你想让这个数据集发挥更大作用我推荐两个进阶方向渐进式分辨率训练和系统化错误分析。前者能在不换模型的前提下涨点后者能告诉你下一步该补什么数据。渐进式分辨率训练的思路是先用小分辨率如 128快速训几个 epoch让模型学到粗粒度特征再逐步升到 224 甚至 288 微调。这样做的好处是前期计算量小、收敛快后期高分辨率精修细节。实现上只需在训练循环里按 epoch 切换 transformdef build_train_tf(size): return transforms.Compose([ transforms.RandomResizedCrop(size, scale(0.6, 1.0)), transforms.RandomHorizontalFlip(), transforms.ColorJitter(0.3, 0.3, 0.3, 0.05), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), ]) schedule [(128, 3), (160, 3), (224, 5)] # (分辨率, epoch 数) for size, epochs in schedule: train_ds.transform build_train_tf(size) train_loader DataLoader(train_ds, batch_size64, samplersampler, num_workers4) for epoch in range(epochs): # 正常训练循环 pass参数说明scale保持不变分辨率提升时裁剪区域绝对像素变大模型能看到更多细节。学习率在切换分辨率时建议降一半避免破坏已学特征。这个策略在 28K 量级上通常能比固定 224 高 1 到 2 个百分点。错误分析则是把验证集上预测错误的样本全部导出按「真实类 → 预测类」分组看混淆矩阵里哪些类对最容易混。动物数据集里猫和狗、狼和狐狸这类视觉相似的类往往是重灾区。把错分样本抽出来人眼看你会发现问题可能出在背景主导比如所有「马」的图都在草地上模型学的是草地、标注错误、或者图像质量太差。针对性地补数据或做背景增强比盲目加 epoch 有效得多。我自己的习惯是每跑完一个模型必做一次错误分析把 top-50 高置信度错分样本存到一个文件夹里下次调参前先翻一遍。这个习惯帮我省下了大量无效实验时间。希望帮到你。本文还有配套的精品资源点击获取

相关推荐

LangChain+ChatGLM-6B本地知识库问答系统搭建实战
LangChain+ChatGLM-6B本地知识库问答系统搭建实战

简介:这是一个基于LangChain与ChatGLM-6B等系列大模型的本地知识库自动问答系统源码包,面向计算机、人工智能、自动化等专业学生及开发者,可用于课程设计、课程大作业或毕业设计,也适合刚接触RAG检索增强生成的读者入门。项目为个… · 2026/9/24 18:10:54

学生成绩预测实战:从特征工程到模型调优的完整指南
学生成绩预测实战:从特征工程到模型调优的完整指南

简介:这是一套基于 Python 的学生成绩预测机器学习入门项目,面向数据科学初学者、教育统计爱好者及需要完成课设作业的高校学生。项目围绕影响学生成绩的多项因素展开,利用 CSV 中的国籍、年级、举手次数、出勤人数、学习时数等字段&#xff… · 2026/9/24 18:10:41

WinUtil:Windows 批量装软件、调优化、管更新策略完整指南
WinUtil:Windows 批量装软件、调优化、管更新策略完整指南

WinUtil:Windows 批量装软件、调优化、管更新策略完整指南 【免费下载链接】winutil Chris Titus Techs Windows Utility - Install Programs, Tweaks, Fixes, and Updates 项目地址: https://gitcode.com/GitHub_Trending/wi/winutil 装一台 Windows 电脑为… · 2026/9/24 18:10:35

COMSOL天然气水合物两相渗流模拟与文献复现全流程解析
COMSOL天然气水合物两相渗流模拟与文献复现全流程解析

天然气水合物,也就是大家常说的“可燃冰”,听起来离我们很远,但真做起相关实验和模拟来,又是另一回事了。我做这个课题最直观的感受是:在实验室里做天然气水合物两相渗流实验,成本高、周期长、重复性还差&a… · 2026/9/24 20:30:00

xarray与address_space:从页缓存索引到writeback的完整解析
xarray与address_space:从页缓存索引到writeback的完整解析

做Linux内核开发和文件系统调优的人,迟早会跟struct xarray和struct address_space打交道。这两个结构一个管数据怎么按索引存取,一个管文件页缓存怎么落地,配合起来就是读写文件最核心的那条路。很多人第一次看源码时,看到addres… · 2026/9/24 20:30:00

Windows任务栏还原与设置大全:跑偏、消失、卡死一次解决
Windows任务栏还原与设置大全:跑偏、消失、卡死一次解决

1. 咦,任务栏怎么跑上面去了? 很多人开机后突然发现,自己的任务栏不在屏幕底部了,而是跑到了屏幕的左侧、右侧或者顶部。更常见的是,明明昨天还好好的,今天一开机,任务栏就从下面“搬家”了。作… · 2026/9/24 20:30:00

9款AI论文辅助工具实测:开题报告高效写作完整指南
9款AI论文辅助工具实测:开题报告高效写作完整指南

又是一年开题季。本科生写开题报告,最磨人的往往不是“写”本身,而是选题怎么收敛、文献哪里找、框架怎么搭、研究方法怎么选——这些环节既考验信息的检索和整理能力,又考验对研究逻辑的理解。2026年了,AI工具已经不再是“聊天玩… · 2026/9/24 20:30:00

AI治理五大技术路线:从规则配置到决策闭环的演进
AI治理五大技术路线:从规则配置到决策闭环的演进

1. 这不是又一个“AI治理”口号,而是数据团队正在经历的真实分水岭2026年刚开年,我连续参加了三场不同行业的数据治理闭门会——金融、制造、医疗各一场。有意思的是,每场开场前茶歇时,听到最多的一句话是:“你们用的哪… · 2026/9/24 20:29:54

隐马尔可夫模型(HMM)实战解析:时序解码与状态推断
隐马尔可夫模型(HMM)实战解析:时序解码与状态推断

1. 这不是数学游戏,是解决真实问题的“时间序列解码器” 你有没有遇到过这样的场景:手机语音助手听清了你每个字的发音,却把“我要订明天早上的高铁票”识别成“我要订明天早上的高贴票”;医院里,医生根据病人连续三天… · 2026/9/24 20:29:54

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13

1D-CNN时间序列建模实战:从Conv1d原理到工业落地
1D-CNN时间序列建模实战:从Conv1d原理到工业落地

简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26

柔软的L:汉语语流中被忽视的舌肌张力控制
柔软的L:汉语语流中被忽视的舌肌张力控制

1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码