3、图像分类基础:任务定义、常用数据集与评价指标

在进入 TinyML 图像分类模型转 RKNN 部署的实战之前,必须先夯实图像分类的理论地基。图像分类是计算机视觉中最基础、最核心的任务,它不仅是目标检测、语义分割等高级任务的前提,也是衡量一个嵌入式 AI 芯片(如 RK3566/RK3588 的 NPU)性能的标尺。本章将系统梳理图像分类的任务定义、两大主流数据集(CIFAR-10 与 ImageNet)的差异,以及准确率与混淆矩阵等评价指标的深层含义。理解这些内容,将直接决定你在后续章节中如何选择预训练模型、如何解读 RKNN 工具链输出的量化精度报告,以及如何定位部署后精度下降的根因。

图像分类知识框架与 RKNN 部署映射 1. 任务定义 • 输入:图像张量 (C×H×W) • 输出:类别概率分布 • 核心:特征提取 + 分类器 • 约束:Top-1 / Top-5 判定 2. 常用数据集 • CIFAR-10:32×32,10类 • ImageNet:224×224,1000类 • 数据规模 / 分辨率差异 • 预训练权重来源 3. 评价指标 • 准确率 Accuracy • 混淆矩阵 Confusion Matrix • 精确率 / 召回率 / F1 • 类别不均衡问题 RKNN 部署实战映射 • 模型选择:ImageNet 预训练 → 剪枝/蒸馏 → 转 RKNN • 数据校准:CIFAR-10/ImageNet 子集 → 量化校准集 • 精度验证:混淆矩阵 → 定位易混类别 → 针对性优化 • 部署监控:Top-1/Top-5 准确率 → NPU 运行时指标

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 模型转换时,务必在 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-10ImageNet对 RKNN 部署的影响
图像分辨率32×32224×224输入尺寸决定 NPU 计算量,224×224 是 RKNN 默认优化尺寸
类别数量101000输出层大小影响内存占用,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%。

操作流程(构建校准集):
  1. 从目标域数据集中随机抽取 200~500 张图像,确保覆盖所有类别。
  2. 将所有图像缩放到模型输入尺寸(如 224×224),并执行与训练时相同的预处理(归一化、通道转换)。
  3. 将图像保存为 npy 格式或直接使用 list 加载,供 rknn.config(quantized_dtype='asymmetric_quantized-8') 使用。
  4. 在 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 的模拟器,对验证集进行批量推理,生成预测结果与真实标签的混淆矩阵。具体步骤为:

  1. 加载 RKNN 模型,遍历验证集(建议至少 1000 张图像),记录每张图像的预测类别。
  2. 使用 Python 的 sklearn.metrics.confusion_matrix(y_true, y_pred) 生成矩阵。
  3. 使用 seaborn.heatmap 可视化,横轴为预测类,纵轴为真实类。
  4. 分析非对角线的高亮区域,找出混淆对。

例如,假设你的模型在"猫"与"狗"之间混淆严重,混淆矩阵显示有 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% 时,不要盲目增加校准集数量,而应先通过混淆矩阵定位问题类别。如果问题集中在少数易混淆类别,优先考虑混合量化或改进训练策略,而非全局降低量化精度。

风险提示:混淆矩阵只能反映模型在已知数据集上的表现。在 TinyML 部署中,由于嵌入式摄像头的光学畸变、光照变化与训练数据分布不同,实际部署时的混淆矩阵可能与 PC 端模拟结果有较大偏差。建议在部署后,采集 100~200 张现场真实图像,重新评估混淆矩阵,并据此决定是否需要在线增量学习或调整后处理逻辑。

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 代码后处理