资讯动态

CIFAR-10与CIFAR-100完全指南:从数据加载到模型精调

发布时间:2026/10/21 14:39:20 来源:尧图企业网站定制
很多人第一次接触图像分类都是先玩手写数字识别然后第二脚就会踩进 CIFAR 这个世界。CIFAR 数据集在计算机视觉领域几乎是绕不开的基准它比 MNIST 难不少又比 ImageNet 小太多于是成了从入门到进阶之间最顺手的那块垫脚石。这篇文章我想把 CIFAR-10 和 CIFAR-100 完整拆一遍从文件格式、加载方式到预处理、模型选型、精调技巧再到消融实验和迁移学习的进阶玩法全部写成可以直接照着做的经验。无论你是刚跑通 LeNet 的新手还是准备拿 CIFAR 做论文实验的研究生应该都能在里面找到点东西。1. 为什么 CV 圈都把 CIFAR 当度量衡数据集的出身和它的基本盘1.1 CIFAR-10 和 CIFAR-100 的硬参数对比很多教程喜欢把这两个数据集放在一起说因为它们来自同一个名字带CIFAR的学术计划格式上几乎一样但任务难度差了一截。先说硬参数CIFAR-10 一共 60000 张 32x32 的彩色图片10 个类别每个类别 6000 张训练集 50000 张测试集 10000 张。类别是飞机、汽车、鸟、猫、鹿、狗、青蛙、马、船、卡车这十类。CIFAR-100 同样是 60000 张 32x32 彩色图但类别数直接拉到 100 类每类只有 600 张其中 500 张训练、100 张测试。100 个细分类别还被归成了 20 个超类比如水生哺乳动物、鱼、花、食物容器、水果蔬菜、家用电器、家具、昆虫、大型食肉动物、大型人造户外事物、大型自然户外场景、大型杂食动物与草食动物、中型哺乳动物、非昆虫无脊椎动物、人类、爬行动物、小型哺乳动物、树木、车辆一、车辆二。如果你第一次见 CIFAR-100最容易产生的误解是类别多十倍难度线性增加十倍其实不是。CIFAR-100 的难点主要在于每类样本太少模型很难抓住类内共性而超类结构又给你留了一个挺有意思的监督线索。我之前带过几个同学做实验有人在 CIFAR-100 上硬堆了一个大 ResNet结果过拟合得一塌糊涂后来把超类信息加进去做分层损失效果立刻不一样。这个后面细说。从图像本身看CIFAR 的图片分辨率只有 32x32单看数字好像比 224x224 的 ImageNet 小很多但不要被骗了。32x32 像素下一个猫可能只有十几个像素的眼睛、几撮毛的纹理模型要在这么低的分辨率下区分猫和狗、卡车和汽车难度并不低。MNIST 是 28x28 灰度图背景基本是干净的CIFAR 是 32x32 彩色图背景有天空、草地、室内陈设等大量干扰信息这也是它比 MNIST 难的本质原因。1.2 为什么说它是理想基线研究社区里几乎默认了一件事任何新模型、新训练技巧、新正则化方法先在 CIFAR-10 上报个数字大家就能立刻评估你这个方法大概什么水平。这就是一个度量衡的作用。原因也很现实CIFAR-10 只需要单张消费级显卡几分钟到一两个小时就能完成一次完整训练迭代成本低到可以反复试错而 ImageNet 动辄几十个小时、多卡并行一次实验的代价太高不适合做快速验证。另外CIFAR 的类别设计本身覆盖了常见视觉任务中的典型挑战有细粒度区分汽车 vs 卡车、猫 vs 狗有纹理差异青蛙 vs 鸟有形态差异马 vs 鹿有背景混淆船 vs 飞机。你在 MNIST 上根本遇不到这种类间相似的问题但在 CIFAR 上你能很直观地看到模型的分类边界在哪里崩掉。还有一个容易被忽略的点CIFAR 的训练集和测试集划分是固定的任何论文只要用这个划分跑出来的准确率就有可比性。这跟那些需要自己切分的数据集不一样省掉了你的划分和我的划分不同所以结果没法比的扯皮。所以它天然适合当基准也适合做模块级别的消融实验。2. 数据文件结构拆解手写一个不依赖框架的 CIFAR 加载器2.1 官方文件里到底存的是什么下载 CIFAR 数据的时候你会看到不同版本最常见的是 Python 版和二进制版。Python 版是 pickle 序列化成的文件直接用 pickle 模块就能读二进制版是纯字节流适合 C/C 或者想彻底搞懂底层结构的人。CIFAR-10 的 Python 版包含五个训练文件data_batch_1.bin 到 data_batch_5.bin每个文件 10000 张图还有一个 test_batch.bin也是 10000 张。每个文件解包后是一个 Python dict键有三个bdata、blabels、bbatch_label。其中 bdata 的 shape 是 (10000, 3072)每一行是一张图的全部像素3072 32x32x3按通道顺序排列前 1024 个是红色通道中间 1024 个是绿色通道最后 1024 个是蓝色通道。CIFAR-100 的结构稍有不同只有 train 和 test 两个文件train 里有 50000 张图test 里有 10000 张图。dict 里的键是 bdata、bfine_labels 和 bcoarse_labels。fine_labels 是 100 类的细标签coarse_labels 是 20 类的超类标签。如果只取 fine_labels 而不去管 coarse_labels等于把一个更难的细粒度任务扔给模型很多新手在这里吃了暗亏。二进制版本的布局更原始一点每个样本是一个 3073 字节的块第一个字节存放标签CIFAR-10 是 0~9CIFAR-100 的 train 里是 0~99 的细标签剩下 3072 字节按 RGB 顺序排布。整个 train.bin 文件就是 50000 个这样的块拼在一起。说实话我现在很少直接用二进制版但理解它有助于彻底搞懂一张图在磁盘上到底长什么样。2.2 两套格式、三行代码加载器的落地写法我平时最常用的是 pickle 版本因为在 Python 里可以直接读成一个 dict省去手动解析字节的麻烦。下面这个函数足够应付 CIFAR-10 和 CIFAR-100import pickle import numpy as np def load_cifar_pickle(file_path, cifar100False): with open(file_path, rb) as f: d pickle.load(f, encodingbytes) images d[bdata].reshape(-1, 3, 32, 32) # 官方存储顺序是 R, G, B 三通道先转成 N,H,W,C 更方便后面画图 images images.transpose(0, 2, 3, 1) if cifar100: fine_labels np.array(d[bfine_labels]) coarse_labels np.array(d[bcoarse_labels]) return images, fine_labels, coarse_labels labels np.array(d[blabels]) return images, labels # CIFAR-10 用法 train_images, train_labels load_cifar_pickle(data_batch_1.bin)如果非要读二进制版也不复杂def load_cifar10_binary(file_path): raw np.fromfile(file_path, dtypenp.uint8) samples raw.reshape(-1, 3073) labels samples[:, 0].astype(np.int64) images samples[:, 1:].reshape(-1, 3, 32, 32).transpose(0, 2, 3, 1) return images, labels这里有一个我建议养成的习惯凡是读 CIFAR 之后要训练把图像先转成 float 型再归一化别直接拿 uint8 喂给模型。深度学习框架虽然内部会自动做类型转换但你自己手动控制类型能避免不少隐性问题。2.3 通道顺序最容易栽跟头的细节加载 CIFAR 的时候翻车概率最高的一件事就是通道顺序。官方存储是 RGB但不同框架的默认布局不一样TensorFlow 早期是 NHWCPyTorch 的卷积层默认是 NCHW。如果你用 OpenCV 读图它读出来的是 BGR再和 CIFAR 原始数据混在一起模型会学到一堆奇奇怪怪的颜色特征最后在测试集上怎么调都上不去。我见过不止一个人代码长得没问题loss 也在降但准确率就是卡在 70% 上下不去排查半天发现是通道顺序写错把 R 和 B 换了。解决方案是在数据加载阶段就定死一个内部标准我习惯统一转成 NHWC也就是 (N, H, W, C)然后在使用时根据框架再转一次。PyTorch 里直接torch.tensor(images).permute(0, 3, 1, 2)转成 NCHW 就行。3. 喂给模型前的三道工序归一化、增强和超类标签的妙用3.1 归一化全局均值和通道均值的区别CIFAR 图像像素值范围是 0 到 255直接塞给神经网络不是不行但收敛速度和稳定性都会差一些。常用的做法是减均值再除以标准差。这里有个选择用全局均值还是按通道分别算均值。我建议按通道算因为三通道的分布本来就不同统一处理会抹掉通道间的统计差异。具体数字在不同版本里略有差异但大致是下面这套我自己在 CIFAR-10 上经常用mean [0.4914, 0.4822, 0.4465] std [0.2470, 0.2435, 0.2616] def normalize(images): images images.astype(np.float32) / 255.0 images (images - mean) / std return images如果你懒得自己算PyTorch 的 torchvision.transforms 里已经有现成的 transform。但不要直接套用别人的 mean/std 数字到 CIFAR-100 上虽然差得不多但严格来说 CIFAR-100 的统计量和 CIFAR-10 并不完全一致想要结果严谨就自己算一遍。有个点需要强调归一化是对每个像素独立操作不改变图像的空间结构所以可以放心地先做数据增强再做归一化或者先归一化再做增强也可以但要注意增强过程是否引入新的像素值范围。比如 CutOut 这种直接把区域填成 0 的操作如果放在归一化之后做填 0 相当于填了负均值含义就不对了。我自己的惯例是先归一化再在归一化后的张量上做增强填 0 区域按填充值统一逻辑处理保证一致性。3.2 增强组合的性价比排序如果你只能加两个增强我强烈建议加随机裁剪加水平翻转。CIFAR 图片是 32x32先把四周 pad 4 个像素变成 40x40再随机裁剪回 32x32配合 50% 概率的水平翻转这一个组合就能让 ResNet 在 CIFAR-10 上凭空涨两到三个点而且几乎不增加训练时间。再往上加性价比由高到低大致是CutOut随机挖掉一块方形区域用平均值或零填充让模型不至于过度依赖局部纹理。MixUp把两张图和对应标签按比例混合相当于一种平滑正则训练 epoch 稍微多一点效果更明显。CutMixMixUp 的变种把一张图的一块区域贴到另一张图上标签也按面积比例混合对分类任务挺管用。AutoAugment / RandAugmentGoogle 那套自动搜索出来的增强策略效果可以但训练时间会长不少。想在 CIFAR 上刷高分的可以上想快速验证想法就没必要。有一个红线要记住验证集永远不要用随机增强最多做归一化。我曾经手滑把 RandomCrop 写进了验证流程结果每次评估结果都在 88% 到 93% 之间乱跳害我白白排查了一个下午。3.3 CIFAR-100 超类被低估的监督信号CIFAR-100 的 20 个超类一直是个被很多人忽略的资源。你可以把超类标签当作额外的监督信号比如设计一个双头网络一个头输出细分类别另一个头输出超类类别两个损失加权求和。这样模型必须同时按大类别和小类别两个粒度组织特征空间通常比只用细标签训出来的特征更鲁棒。另外一个用法是拿超类做错误分析。我在一个图像分类 Demo 里试过模型把狗误分类成猫虽然细分类别错了但如果它预测的超类是中型哺乳动物说明模型的语义理解其实是对的只是精细区分能力不够。这种分析在论文里特别有用能证明你的方法不是靠某个类别的运气涨点而是整体特征质量变好了。4. 模型选型路线图从 LeNet 到 ViT 的真实复现记录4.1 带 BN 的迷你 CNN一小时跑完的起点如果你刚开始接触 CIFAR不要一上来就上 ResNet 或者 Transformer先用一个一两个小时内能跑完的迷你 CNN 把流程走通。最朴素的 LeNet 结构其实不太适合 CIFAR因为它没有批归一化层收敛慢对学习率又敏感。我的建议是在 LeNet 基础上加两个东西每个卷积层后面接 BatchNorm2d激活换成 ReLU这就够用了。一个参考结构卷积层32 通道3x3 BN ReLU再接一个卷积层64 通道3x3 BN ReLU然后 2x2 最大池化再重复一轮最后全局平均池化接全连接层。这个模型参数量大约几十万在 CIFAR-10 上配合基础增强能跑到 80% 以上。它最大的价值不是精度而是让你在几分钟内完成从数据到模型的闭环后面换任何结构都不慌。4.2 ResNet-18 和 ResNet-56为什么默认选它我做 CIFAR 实验时的默认起点是 ResNet-18而不是原版论文里的 ResNet-20 或 ResNet-56。原因很实际ResNet-18 在 torchvision 里有现成实现结构和源码都好找参数量约 1100 万单卡 1080 上跑 100 个 epoch 大概只要半小时到一小时精度在基础增强下能到 93% 左右再配上 CutOut 和 MixUp 可以摸到 95% 以上。ResNet-56 是 CIFAR 论文里更常用的专用结构因为它是针对 32x32 输入设计的残差层堆叠没有降采样太快导致信息丢失的问题。但 torchvision 没有直接的 ResNet-56 实现需要自己拼或者找第三方代码对新手来说不如 ResNet-18 顺手。如果你追求更极致的性能可以试 WideResNet。它把网络变宽而不是变深同样参数量下准确率往往更高WideResNet-28-10 在 CIFAR-10 上配合强增强能到 96% 上下是很多论文刷基线的最爱。不过训练时间和显存占用也上去了适合你已经把调试流程走顺了再去碰。4.3 ViT 在 32x32 图上的复现门槛与建议Vision Transformer 这类纯 Transformer 结构在 CIFAR 上也能跑但门槛明显比 CNN 高。32x32 的图片切 patch常见做法是 patch size 4x4一共产出 64 个 patch序列长度比 ImageNet 上的 196 个 patch 短不少计算量其实还好真正的问题是数据量太少。ViT 没有卷积那种天然的局部归纳偏置在小数据集上从头训练很容易欠拟合结果往往打不过 ResNet。我的建议是分两步走先用 ImageNet 预训练的 ViT 权重做微调32x32 的图通过插值放大或者直接调整 patch embed 层来适配效果通常不错如果你想验证一个关于 Transformer 结构的新想法再考虑在 CIFAR 上从头训练但要把数据增强拉满加 MixUp、CutMix、RandAugment 这些epoch 也要给足。我自己在 CIFAR-10 上从头训一个 ViT-Small折腾了好几天最终精度也就是和 ResNet-18 打平但代码复杂度和调试成本翻了好几倍。想清楚你要的是什么别为了用 Transformer 而用 Transformer。4.4 一张表看懂各模型的性能量级下面这张表是我自己多次实验得到的大致区间不同框架、不同初始化、不同 epoch 设定都会造成浮动不要当精确 benchmark 去引但作为选型的参考很够用。模型结构参数量量级CIFAR-10 约准基础增强CIFAR-10 约准强增强训练时间量级单卡迷你 CNN带 BN几十万80%~83%85% 左右10~20 分钟ResNet-18约 1100 万93%~94%95%~96%30~60 分钟ResNet-56约 85 万93% 左右95% 左右40~90 分钟WideResNet-28-10约 3600 万94%~95%96%~97%1~2 小时ViT-Small微调预训练约 2200 万97% 以上98% 左右1 小时左右ViT-Small从头训练约 2200 万90% 左右93%~95%1~2 小时看这张表你会发现一个现象模型变大带来的收益在 CIFAR-10 上很快就饱和了从 ResNet-18 到 WideResNet-28-10准确率才涨一两个点但参数量和训练时间涨了好几倍。如果你只是想快速验证方法ResNet-18 是性价比之王。5. 精调阶段翻车现场学习率规划、过拟合识别与隐性数据泄漏5.1 学习率节奏warmup cosine decay 的经验值CIFAR 跑到 90% 以上之后真正限制你刷分的往往不是模型结构而是训练配置。我常用的配置如下SGD Momentum 0.9weight decay 5e-4batch size 128epoch 200 到 300初始学习率 0.1前 5 个 epoch 做 warmup 从 0 线性升到 0.1然后 cosine annealing 降到接近 0。这个组合在 ResNet 系模型上非常稳定基本不会崩。为什么用 warmup早期 batch 统计量不稳定一上来就给 0.1 的大学习率容易让 loss 瞬间爆炸尤其是 BN 层还没跑稳的时候。为什么用 cosine decay 而不是 step decaycosine 的降速更平滑在 CIFAR 这种中等规模数据集上训练后期不会有明显平台期往往最后十几个 epoch 还在涨点。我对比过 step decay 和 cosine decay在同样的 epoch 数下cosine 普遍高 0.5~1 个点。AdamW 能不能用也能用但要注意 weight decay 的系数和 SGD 不是一个量级。在 CIFAR 上我观察到AdamW 的收敛速度快但最终精度通常比好好调的 SGD 低一点除非你配合很长的训练计划和更激进的正则化。如果只是想快速看结果AdamW 也不是不行但要有个心理预期。5.2 用 train/test gap 判断过拟合程度新手最容易问的一个问题怎么看模型过没过拟合最朴素也最管用的办法就是记录训练集准确率和测试集准确率之差。CIFAR-10 上如果训练集已经接近 100%测试集只有 88%这个近 12 个点的 gap 就是非常明确的过拟合信号。反过来如果两边都只有 70%那可能是欠拟合问题出在模型容量或训练时间上而不是正则化。正常的健康状态是训练集 98% 左右测试集 93%~95%gap 在 3 到 5 个点之间。如果 gap 太大了第一反应不是换模型而是先加数据增强再加 weight decay最后才考虑 Dropout 或减少模型容量。我在实践中发现 CIFAR 上最强的正则化手段不是 Dropout反而是 MixUp 和 CutOut 这类数据层面的扰动它们改变了训练样本的分布让模型学到更平滑的决策边界。还有个小技巧如果训练 loss 一直在降但测试准确率停滞多半是优化器把训练集背下来了。这时候可以把训练集里随机抽一部分出来当验证集用验证 loss 判断要不要提前停止而不是在测试集上反复横跳。5.3 隐性数据泄漏反复用测试集选模型的危害这件事我想单独拎出来说因为它太常见了。很多人做完一轮实验发现测试集准确率不够高就回去调超参再跑一轮再测一下测试集来回十几次终于调出一个 95% 的成绩。这个 95% 是真实可复现的吗不能说完全假但它已经是被同一批测试集筛出来的结果存在过拟合测试集的风险。正确的做法是把原始训练集再切出一小部分当验证集比如从 50000 张里切出 5000 张剩下 45000 张训练。所有超参调整、增强策略对比、模型选择全在验证集上做最后只碰一次测试集。我在自己实验里严格遵循这个流程之后论文里的数字稳定了很多因为成绩不是靠反复试出来的运气而是方法本身真的有效。另外一个很容易被忽略的泄漏源是数据增强的预处理统计量。比如你用全量数据算 mean 和 std再去做数据归一化然后拿同一份数据训练这其实引入了极轻微的数据依赖。虽然实际影响很小但在要求严谨的消融实验里正确的姿势是先只统计训练集的 mean/std再应用到训练集和测试集。6. CIFAR 的进阶用法消融实验、迁移学习与边缘场景试验6.1 消融实验的正确姿势如果你打算把 CIFAR 实验写进论文或者技术报告消融实验的规范性直接决定结论的可信度。我见过不少想当然的做法每跑一组实验换一次随机种子训练 epoch 数还不一样最后拿出来的对比表格根本没法解释精度差异到底是来自方法还是来自运气。我的经验是三个固定固定随机种子、固定数据增强、固定 epoch 数。随机种子至少跑 3 个取平均和标准差这样出的数字才有统计意义。有个朋友曾经连续两次跑同一个 ResNet-18 配置一次 93.6%一次 92.8%差距接近一个点如果只看单次结果很容易把方法 A 比方法 B 涨的那零点几个点误判成真实提升。另外消融实验最好从去掉你的改动开始先建立一个强 baseline再逐项加回模块。CIFAR 上做这件事特别方便因为一轮训练只要几十分钟你可以很轻松地把所有组合都试一遍。6.2 迁移学习ImageNet 权重遇到 32x32 的插值问题很多人拿 CIFAR 做迁移学习实验时都会卡在一个细节上ImageNet 预训练权重是为 224x224 设计的CIFAR 是 32x32怎么喂进去常见做法是把 32x32 的图用双线性插值放大到 224x224再走标准预训练模型。这个做法简单但有一个问题放大后的图其实变糊了原本低频信息被放大高频纹理被插值平滑掉模型看到的数据分布和 ImageNet 预训练时看到的并不完全一样。更精细的做法是修改模型输入层比如把网络第一个卷积或者 patch embed 层的权重视为可重新初始化的部分用 32x32 输入直接接受其余权重加载预训练。这种方式在 CNN 里容易实现效果也不错。另外一个关键点是迁移学习的初始学习率要比从头训练小因为预训练权重已经在一个合理区域太大的步子容易把学好的特征冲乱。我一般用 0.01 到 0.03 的量级配合 cosine decay20 到 50 个 epoch 就能在 CIFAR-10 上拿到相当不错的分数。6.3 半监督、对抗样本与特征可视化的试验场CIFAR 除了当监督分类基准还有一个隐藏价值它是半监督学习和对抗攻击研究的低成本试验场。半监督场景下你可以从 50000 张训练图里只拿一小部分做有标注训练剩下的当作无标注数据跑一致性正则或伪标签方法。32x32 的图片让这类实验不至于太慢而且类别数适中评估指标直观。对抗样本研究也喜欢用 CIFAR因为它比 MNIST 难很多能区分防御方法真的有效还是在简单数据上刷数字。我自己在 CIFAR-10 上做过 FGSM 和 PGD 攻击的对比实验发现很多在 MNIST 上看起来效果很好的防御方法到 CIFAR 上一下就露馅了。如果你在写健壮性相关的内容CIFAR 是比 MNIST 靠谱得多的平台。特征可视化也是 CIFAR 的一个强项32x32 的图比较小用 Grad-CAM 画热力图的时候结果很干净类别区域清晰不像 ImageNet 那么大尺寸需要做很多后处理。想做解释性研究的话CIFAR 是一个收敛速度快的起点适合先把方法思路跑通再迁移到大图上。最后说一个我自己的习惯每次拿到一个新的模型结构或者训练技巧我都会先在 CIFAR-10 上用最朴素的配置跑一遍看看它到底是涨点还是掉点。如果这个技巧在 CIFAR 上都没显著效果那大概率在更大更复杂的数据集上也不会有惊喜。反过来一旦在 CIFAR 上扎实地验证过后面去碰 ImageNet 或者真实业务数据我心里是踏实的。要玩转一个数据集关键不是记住那几个准确率数字而是彻底搞懂它每个字节、每根通道、每类样本背后的脾气。祝你在 CIFAR 这条路上少踩几个坑早日把属于自己的 baseline 跑得板板正正。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑