本节摘要:架构再好,也要在像样的战场检验。本节把图像分类实验的三件套盘清楚:主流数据集怎么选、数据增强怎么给模型扩视野、精度指标怎么才算靠谱,并附一份可直接照搬的轻量分类训练脚本。
3.2 给了能打的架构,本节关起门来把"战场规矩"定好:在什么数据集上、用什么增强、拿什么指标评。它承接第2章的评估话题,但完全落在视觉语境内,也为 3.4 的目标检测与分割埋一支预备队。
图像分类的"跑道"是预置数据集,足够多的样本、固定的类别数、公认的划分方式,让不同模型能公平比试。最常用的三档:MNIST 一上来就是 28×28 手写数字、10 类,几十兆就能装下,直接拿它跑通整套流程;CIFAR-10 是 32×32 彩色图、10 类常见物(猫、狗、卡车、飞机等),运算量适中,是经典模型验证场;ImageNet 则是 224×224、上百个类的大战,冠军之争曾是深度学习的晴雨表。三个数据集难度递增,用途从"跑通"到"打榜"各不相同。
| 数据集 | 尺寸与类别 | 难度 | 典型用途 |
|---|---|---|---|
| MNIST | 28×28 灰度,10 类 | 低 | 跑通流程、教学 |
| CIFAR-10 | 32×32 彩色,10 类 | 中 | 原型验证、对比模型 |
| ImageNet | 224×224 彩色,大类别 | 高 | 打榜、预训练底座 |
选数据集时还有个常被忽略的点:测试集划分必须干净。训练时反复用测试集调参,等于把答案偷看了;所以正式策略仍是训练/验证/测试三分,只有最终的最终才碰测试集(回顾 2.2)。
真实项目的样本永远不够。数据增强不做别的,就是对训练图做随机小变形,让模型看到同一张图的许多翻版:随机水平翻转、随机裁剪、微调亮度与对比度等。这些变形本身不改变类别(狗翻个面还是狗),却逼模型学到"不管姿态怎么变都认得出"的不变特征——一手治样本不足,一手防过拟合,正好接上第2章的教训。
增强的窗口把握很讲究:裁剪太狠会把核心特征切掉,让模型学岔;翻转也要看任务——手写数字翻转就成了别的字,绝不能乱翻。工程上常先保守(只做轻度翻转裁剪),验证集反映欠拟合再逐步加码。
图像分类最常见的指标是顶一准确率(Top-1 Acc),即预测最可能的类别恰好对。但对类别多、易混淆的赛道,还流行看 Top-5——前五个预测里只要含正确类就算对,能更宽容地衡量模型"心里有数"。别一味追最高准确率:模型在 A 数据集顶天高、换个赛道就翻车的情况常有,更稳的评法是把多次随机种子下的均值和方差都看一眼,挑"既高又稳"的那个。
在这里把"加载数据 → 增强 → 建模 → 训练 → 评估"串成一份可运行的骨架:
import tensorflow as tf import numpy as np (x_tr, y_tr), (x_te, y_te) = tf.keras.datasets.cifar10.load_data() x_tr, x_te = x_tr.astype("float32")/255.0, x_te.astype("float32")/255.0 model = tf.keras.Sequential([ tf.keras.layers.Conv2D(32, (3,3), activation="relu", input_shape=(32,32,3)), tf.keras.layers.MaxPooling2D((2,2)), tf.keras.layers.Conv2D(64, (3,3), activation="relu"), tf.keras.layers.MaxPooling2D((2,2)), tf.keras.layers.Flatten(), tf.keras.layers.Dense(10, activation="softmax"), ]) # 顺手的增强:随机翻转与偏移 aug = tf.keras.Sequential([ tf.keras.layers.RandomFlip("horizontal"), tf.keras.layers.RandomTranslation(0.1, 0.1), ]) model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"]) model.fit(aug(x_tr), y_tr, epochs=10, validation_split=0.1, batch_size=32) loss, acc = model.evaluate(x_te, y_te) print("测试准确率:", round(acc, 4))
aug(...) 这一行是数据增强的骨架:喂给模型的是增强后的图,模型每轮看到的世界都会略有不同。跑完看验证损失曲线是否和训练曲线靠拢(回顾 2.2 的判据),就能判断该不该加正则化或提早停止。
放在整个视觉任务里,这只是一块跳板:同样的卷积底座,稍加改造就能去做检测(把整图问题改成框问题)和分割(把整图问题改成逐像素问题),这正是 3.4 的内容。所以 3.3 的目标不是拿个漂亮的准确率,而是把"数据—增强—模型—评估"这整条流水跑熟。
代码能跑起来只是开始,真正看出门道的是训练日志。第2章 2.2 说过看训练与验证曲线的差值,这里落到视觉实操:若二者靠拢得漂亮,说明增强或正则给得合适;若验证劈头就高,往往不是增强不够,而是数据没喂对或模型太小;若训练一路贴地、验证掉头向上,就该降容量或加正则、或者早点停。这时调的是 batch size、学习率、卷积核个数、增强强度,而不是一开始就去搜那些无关紧要的数。
还有个视觉特有的提醒:把验证集当"指挥棒"时,务必顺着增强的窗口走——验证时不要做训练那样的大裁剪,否则毁掉评估。图像分类的评估和训练经常因为"增强口径不一致"而自欺,这是3.3 全节最值得记牢的一条实操细节。
给定 MNIST、CIFAR-10 和一个"要不要翻转"的问题:为何手写数字不能乱翻转、CIFAR-10 却能水平翻转?想清楚再翻答案——数字翻转会把 6 变 9、9 变 6,语义直接扭曲;而自然物体水平翻面仍是同类。这条判断力,正是你往后给任何视觉任务配增强时都要带着的思维。