3、图像分类基础:任务定义、常用数据集与评价指标
在进入 TinyML 图像分类模型转 RKNN 部署的实战之前,必须先夯实图像分类的理论地基。图像分类是计算机视觉中最基础、最核心的任务,它不仅是目标检测、语义分割等高级任务的前提,也是衡量一个嵌入式 AI 芯片(如 RK3566/RK3588 的 NPU)性能的标尺。本章将系统梳理图像分类的任务定义、两大主流数据集(CIFAR-10 与 ImageNet)的差异,以及准确率与混淆矩阵等评价指标的深层含义。理解这些内容,将直接决定你在后续章节中如何选择预训练模型、如何解读 RKNN 工具链输出的量化精度报告,以及如何定位部署后精度下降的根因。
3.1 图像分类任务定义:从输入张量到类别概率
3.1.1 核心原理:分类器的本质是概率映射
图像分类(Image Classification)的任务是给定一张输入图像,由算法模型判断该图像所属的类别标签。从数学角度看,这是一个从高维像素空间到离散标签空间的映射函数 \( f: \mathbb{R}^{C \times H \times W} \rightarrow \{1, 2, ..., K\} \),其中 \( C \) 为通道数(灰度图为1,RGB图为3),\( H \) 和 \( W \) 为图像高度与宽度,\( K \) 为类别总数。现代深度学习分类器(如 MobileNet、ResNet)并不直接输出硬标签,而是输出一个 \( K \) 维的向量,每个元素表示该样本属于对应类别的概率。最终通过 Softmax 函数将网络输出的 logits 归一化为概率分布,取概率最大的索引作为预测类别。
在 TinyML 场景下,这个定义有两点特殊约束。第一,输入分辨率通常被压缩至 224×224(ImageNet 标准)或更小的 96×96、64×64,以适应 NPU 的算力与内存带宽。第二,输出层必须与训练时的类别数严格一致。例如,如果你用 CIFAR-10 训练了一个 10 类模型,部署到 RKNN 后,输出张量形状就是 [1, 10],每个值对应一个类别的置信度。若你后续想增加类别,必须重新训练并重新转换 RKNN 模型,不能直接修改输出层。
3.1.2 判断方法:如何界定一个任务是否属于图像分类
在实际项目中,区分图像分类与目标检测、图像分割非常重要,因为这会直接影响模型架构选型与 RKNN 的算子支持。判断标准有三条:输出粒度(整图一个标签 vs 每个像素一个标签 vs 每个目标一个框)、目标数量(单目标 vs 多目标)、空间位置(是否需要定位)。如果任务只需要回答"这张图里有什么",且不关心物体在哪个位置,那就是图像分类。例如,质检流水线判断"零件表面是否有划痕"是二分类;而"划痕在零件的哪个区域"则属于目标检测或分割。
| 任务类型 | 输出形式 | 典型模型 | RKNN 部署要点 |
|---|---|---|---|
| 图像分类 | 类别概率向量 [1, K] | MobileNetV2, EfficientNet | 输出层为全连接 + Softmax,NPU 支持良好 |
| 目标检测 | 边界框 + 类别 + 置信度 | YOLOv5, SSD | 需要解码 NMS,RKNN 需自定义后处理 |
| 语义分割 | 逐像素类别图 [H, W] | UNet, DeepLabV3 | 上采样算子需关注 NPU 兼容性 |
3.1.3 案例拆解:RKNN 部署中的输出张量解读
假设你已在 PC 端训练好一个 MobileNetV2 模型,类别为"猫、狗、鸟"三类。在转换为 RKNN 模型后,通过 RKNN Toolkit 的 inference 接口输入一张 224×224 的猫图,返回的 outputs 是一个形状为 [1, 3] 的浮点数组,例如 [0.92, 0.05, 0.03]。此时,你需要在后处理代码中执行 argmax 操作,得到索引 0,对应"猫"。但要注意,RKNN 在 NPU 上默认使用 int8 量化 推理,输出的概率值并非直接是 0~1 的浮点数,而是经过反量化后的近似值。因此,在嵌入式 C 代码中,你需要读取 int8 输出,乘以 scale 并加上 zero_point,才能得到正确的概率分布。这个细节是 TinyML 部署中最常见的精度"假摔"原因之一。
rknn.config() 中设置 target_platform='rk3566' 等具体芯片型号,并开启 optimization_level=3。同时,在 PC 端仿真推理时,对比 rknn.inference(inputs=[img]) 与 PyTorch 原始模型的输出差异,若 Top-1 类别不一致,先检查预处理(归一化、通道顺序)是否一致,再检查量化精度。
3.2 常用数据集:CIFAR-10 与 ImageNet 的工程差异
3.2.1 核心原理:数据集决定模型能力的上限
数据集是图像分类模型的"教材"。CIFAR-10 与 ImageNet 是学术界和工业界最常用的两个基准,它们之间的差异不仅是规模,更代表了两种典型的应用场景。CIFAR-10 包含 60000 张 32×32 的彩色图像,共 10 个类别(飞机、汽车、鸟、猫、鹿、狗、青蛙、马、船、卡车),每类 6000 张。由于分辨率极低,CIFAR-10 适合快速验证模型架构和训练策略,但不适合直接部署到真实场景。ImageNet(ILSVRC2012)包含约 128 万张训练图像和 5 万张验证图像,分辨率为 224×224,覆盖 1000 个类别。它是绝大多数预训练模型(如 PyTorch 的 torchvision 模型)的默认训练集,模型在此数据集上的 Top-1 准确率直接反映了其特征提取能力的强弱。
3.2.2 对比分析:如何根据项目需求选择数据集
在 TinyML 项目实战中,你几乎不会直接用 CIFAR-10 或 ImageNet 的原始数据训练最终模型,而是使用它们的预训练权重进行迁移学习。选择依据如下:如果目标类别数较少(如 10~50 类)且图像内容相对简单(如工业零件、简单图标),可以从 CIFAR-10 训练一个轻量模型,但更推荐使用 ImageNet 预训练的 MobileNetV2 作为 backbone,冻结前几层,微调最后几层。如果目标类别数超过 100 类,或者图像包含复杂纹理(如植物叶片、皮肤病变),则必须使用 ImageNet 预训练模型,否则模型难以收敛。
| 对比维度 | CIFAR-10 | ImageNet | 对 RKNN 部署的影响 |
|---|---|---|---|
| 图像分辨率 | 32×32 | 224×224 | 输入尺寸决定 NPU 计算量,224×224 是 RKNN 默认优化尺寸 |
| 类别数量 | 10 | 1000 | 输出层大小影响内存占用,1000 类全连接层约 4MB 参数 |
| 数据量 | 6 万张 | 128 万张 | 预训练权重质量差异巨大,ImageNet 权重泛化性更强 |
| 适用场景 | 教学实验、快速验证 | 真实场景迁移学习 | 部署时需根据数据集统计量计算 mean/std 归一化参数 |
3.2.3 实战场景:构建 RKNN 量化校准集
RKNN 在将浮点模型转换为 int8 定点模型时,需要一组"校准集"(Calibration Dataset)来统计激活值的分布范围。这组数据通常从训练集或验证集中随机抽取 200~500 张图像。这里有一个关键决策:校准集应该来自哪个数据集?如果你使用 ImageNet 预训练模型微调后部署,建议从你的目标域数据(而非 ImageNet 原始验证集)中抽取校准集。例如,你的项目是识别电路板上的电子元器件,那么校准集应包含 200 张不同光照、角度下的电路板照片。这是因为校准集的数据分布越接近真实部署环境,量化后的精度损失越小。反之,若直接使用 ImageNet 验证集做校准,由于域差异,量化后模型在电路板数据上的 Top-1 准确率可能下降 5%~10%。
- 从目标域数据集中随机抽取 200~500 张图像,确保覆盖所有类别。
- 将所有图像缩放到模型输入尺寸(如 224×224),并执行与训练时相同的预处理(归一化、通道转换)。
- 将图像保存为 npy 格式或直接使用 list 加载,供
rknn.config(quantized_dtype='asymmetric_quantized-8')使用。 - 在
rknn.build(do_quantization=True, dataset='calib.txt')中指定校准集路径。
3.3 评价指标:准确率与混淆矩阵的深度解读
3.3.1 核心原理:准确率的局限性与混淆矩阵的价值
准确率(Accuracy)定义为预测正确的样本数占总样本数的比例,公式为 \( Accuracy = \frac{TP + TN}{TP + TN + FP + FN} \)。在类别均衡的数据集上,准确率是一个直观的指标。但在 TinyML 实际部署中,类别不均衡是常态。例如,工业质检中"良品"占 95%,"缺陷品"占 5%,一个永远预测"良品"的模型也能达到 95% 准确率,但这毫无实用价值。此时,混淆矩阵(Confusion Matrix)能提供更细粒度的信息:它是一个 \( K \times K \) 的矩阵,行表示真实类别,列表示预测类别。矩阵对角线元素表示正确分类的数量,非对角线元素表示错误分类的模式。通过混淆矩阵,你可以快速发现哪些类别之间容易混淆(如"猫"与"狗"),从而针对性地增加数据或调整损失函数权重。
3.3.2 判断方法:如何用混淆矩阵指导 RKNN 调优
在 RKNN 部署后,你通常会得到一份量化精度报告,其中包含 Top-1 和 Top-5 准确率。但这份报告是整体性的,无法告诉你具体哪些类别出了问题。正确做法是:在 PC 端使用 RKNN Toolkit 的模拟器,对验证集进行批量推理,生成预测结果与真实标签的混淆矩阵。具体步骤为:
- 加载 RKNN 模型,遍历验证集(建议至少 1000 张图像),记录每张图像的预测类别。
- 使用 Python 的
sklearn.metrics.confusion_matrix(y_true, y_pred)生成矩阵。 - 使用
seaborn.heatmap可视化,横轴为预测类,纵轴为真实类。 - 分析非对角线的高亮区域,找出混淆对。
例如,假设你的模型在"猫"与"狗"之间混淆严重,混淆矩阵显示有 30 张猫图被预测为狗。此时,你可以检查 RKNN 的量化配置文件,看这两个类别的激活值分布是否在量化时被压缩。如果问题出在量化,可以尝试使用 混合量化(hybrid quantization),对最后一层全连接层保持 float16,其余层用 int8。
3.3.3 案例拆解:一个完整的精度诊断闭环
背景与约束:某智能门锁项目需要在 RK3566 上部署一个 10 类人脸表情识别模型(生气、厌恶、恐惧、开心、中性、悲伤、惊讶等)。团队使用 MobileNetV2 在 FER2013 数据集上微调,PC 端浮点模型 Top-1 准确率为 72%。转换为 RKNN int8 模型后,Top-1 准确率降至 63%,下降了 9 个百分点,超出预期。
初始现象:整体准确率下降,但不确定是哪些类别退化。团队最初怀疑是量化精度不足,试图通过增大校准集(从 200 张增至 1000 张)来改善,但效果甚微。
分析判断过程:生成混淆矩阵后发现,"恐惧"与"惊讶"两个类别的混淆率极高,有 40% 的"恐惧"样本被预测为"惊讶"。进一步分析发现,这两个类别在 FER2013 数据集中本身标注噪声较大,且人脸表情在低分辨率(48×48)下视觉特征极为相似。量化后,由于 int8 的精度损失,这种细微差异被进一步放大。
实际操作步骤:
- 步骤 1:在训练阶段引入标签平滑(Label Smoothing)和焦点损失(Focal Loss),降低对易混淆类别的过自信。
- 步骤 2:在 RKNN 转换时,对最后两层(全连接层和 Softmax 层)使用
custom_quantize_layer指定为 float16。 - 步骤 3:重新生成校准集,专门从"恐惧"和"惊讶"类别中多抽取 50 张图像,使校准集类别分布更均衡。
结果对比:经过上述三步优化后,Top-1 准确率回升至 69%,其中"恐惧"类别的召回率从 45% 提升至 68%。代价是模型文件增大约 0.3MB(因部分层保持 float16),推理时间增加约 2ms,但仍满足实时性要求。
复盘经验:当 RKNN 量化后精度下降超过 5% 时,不要盲目增加校准集数量,而应先通过混淆矩阵定位问题类别。如果问题集中在少数易混淆类别,优先考虑混合量化或改进训练策略,而非全局降低量化精度。
3.4 常见误区与总结复盘
3.4.1 误区一:将准确率作为唯一指标
在 TinyML 项目中,准确率只是起点。例如,一个模型在测试集上准确率为 90%,但在 NPU 上推理时,由于 int8 量化,准确率降至 85%。此时,你需要关注的是精度下降幅度,而非绝对准确率。如果下降幅度在 2% 以内,通常可接受;若超过 5%,则需深入分析。此外,对于多类别任务,应同时关注每个类别的召回率(Recall)和精确率(Precision),特别是安全关键场景(如医疗、自动驾驶),漏检的代价远高于误检。
3.4.2 误区二:忽视数据集的域差异
很多开发者直接使用 ImageNet 预训练模型,然后用自己的数据微调,却忽略了 ImageNet 图像的统计特性(如平均像素值 mean=[0.485, 0.456, 0.406],标准差 std=[0.229, 0.224, 0.225])。在 RKNN 部署时,如果预处理代码中的归一化参数与训练时不匹配,会导致输入分布偏移,即使模型权重完全正确,输出概率也会失真。务必在 RKNN 的 rknn.config(reorder_channel='0 1 2') 和 rknn.batch_size 设置中,与训练脚本保持完全一致的预处理流程。
3.4.3 误区三:混淆矩阵只用于论文,不用于工程
实际上,混淆矩阵是 RKNN 部署调试中最强大的工具之一。当你发现 NPU 上的推理结果与 PC 端不一致时,通过混淆矩阵可以快速判断是系统性偏差(所有类别准确率均匀下降,多为量化尺度问题)还是局部性偏差(特定类别混淆,多为特征相似或数据不均衡)。前者可以通过调整量化参数解决,后者则需要从训练数据或模型结构入手。
| 复盘维度 | 关键行动 | 交付物 |
|---|---|---|
| 任务定义 | 明确输出类别数、输入分辨率、Top-1/Top-5 需求 | 模型输入输出规格文档 |
| 数据集 | 选择预训练权重、构建校准集、统计 mean/std | 校准集文件、预处理代码 |
| 评价指标 | 生成混淆矩阵、计算各类别 Precision/Recall | 精度报告、混淆矩阵热力图 |
| RKNN 映射 | 配置量化参数、混合精度、验证推理一致性 | RKNN 模型、C 代码后处理 |