7.16. 总结

本章介绍了当推理步骤成为流水线一部分时,OpenMV 应用程序会用到的 ml 模块的各个组成部分:

  • 概念 —— 用算术术语解释神经网络是什么(一组可训练算子的堆叠,将一个张量映射为另一个张量),机器学习相较于传统图像处理改变了什么(人工编写的总结算法消失了,取而代之的是从带标签数据中学习得到的权重),以及那个用寥寥几行 Python 代码运行人脸检测器的入门演示。

  • ml 模块 —— ml.Model 对象及其用于检查输入和输出张量的属性、它所接受的模型文件路径,以及这些文件存放的位置:用于直接从闪存执行的只读 ROMFS 分区,或者在加载时可将模型复制到 RAM 中的任何其他 MicroPython 文件系统。

  • 推理流水线 —— predict() 依次运行的三个阶段(预处理、引擎调度、后处理)、第一阶段的 Normalization 句柄、第三阶段的后处理器句柄,以及将摄像头运行的整数张量重新关联回网络训练时所基于的实数值的量化运算。

  • 推理引擎 —— TFLM(大多数摄像头运行的算子解释器)、CMSIS-NN(其在 Cortex-M 上所依赖的 SIMD 内核库),以及 NPU(AE3 上 Arm 的 Ethos-U55,配合 Vela 离线编译器;N6 上 ST 的 Neural-ART,配合 STAI 和 STEdgeAI)。引擎由摄像头固定决定,脚本无法选择。

  • 解码输出 —— 将原始输出张量转换为边界框、关键点或按类别列表的后处理器、用于合并重叠候选项的 NMS 类、展示如何通过在反量化之前进行阈值处理来保持解码快速的 YOLOv8 演示,以及当目录未涵盖某个模型时编写自定义解码器的协议。

7.16.1. 现在能做到什么

本章为以下三件事做了铺垫:

  • 加载并运行已训练的模型。 /rom/ 中的任何内容无需进一步准备即可使用;任何作为兼容 .tflite 从外部提供的内容,在针对目标摄像头的离线工具(AE3 用 Vela,N6 用 STEdgeAI)生成了正确的布局之后即可使用。

  • 解码任意输出张量。 当架构在目录中时,选择正确的后处理器是按部就班的:YOLOv8 模型用 YoloV8,BlazeFace 用 BlazeFace,以此类推。当架构不在目录中时,编写自定义后处理器 协议涵盖了相关约定,而 YOLOv8 演示 则是最清晰、可供参考复制的范例。

  • 对性能进行推断。 一个在 NPU 上以 30 FPS 运行的模型,在 Cortex-M7 上可能只能以 3 FPS 运行;二者之比取决于摄像头能将网络的多少部分从 CPU 上卸载下来。量化、ROMFS 放置、NPU 编译以及目标引擎的算子覆盖范围是四个调节杠杆,本章对每一个都作了介绍。

7.16.2. ML 与摄像头的其余部分协同工作

推理很少单独运行。image 模块捕获并预处理帧,ml 模块运行网络,而 ulab.numpy 则负责处理两者都没有内置功能的各种数值工作。一个典型的检测脚本会将三者结合起来:用 csi 捕获、可选地用 image 调整帧、运行 predict()、用 ml.postprocessing 中合适的模块对结果进行后处理,并借助 ulab.numpy 在后处理器返回的边界框之上完成应用程序所需的任何自定义数学运算。这三个模块共享相同的内存模型;在尽可能的情况下,它们之间的边界是零拷贝的。