如何基于iMX8M Plus开发机器学习应用
By Toradex 胡珊逢
NXP iMX8M Plus 作为其第一款支持神经网络运算硬件加速的处理器,提供对多种框架的支持,例如 ArmNN、TensorFlowLite、ONNX,eIQ Poral 工具可以使用户能够轻松地训练自己地模型,或者将现成的模型转换为适合在 iMX8M Plus 进行加速的模型。本文将介绍如何在 Toradex 的 Verdin iMX8M Plus 计算机模块上使用现成训练好的 TensorFlow Lite 模型开发深度学习应用,以及自行训练模型并借助 eIQ Poral 对模型进行转换使其适合在计算机模块上使用。
深度学习应用开发流程中,一个重要的环节就是训练模型。这不仅需要合理地调整参数,还需要大量的样本数据以及充足算力的计算机。因此使用训练好的模型通常是一个不错的选择,尤其是在项目初期缺少样本数据的阶段。TensorFlow Hub 提供了丰富的资源。这里我们将使用 ssd_mobilenet_v1 模型,以及一个使用 Python 开发的物体识别例程介绍如何使用这些现成的模型。
Toradex 部分的默认 BSP 中没有集成深度学习所需的软件,但可以通过 Yocto Project 非常容易将 NXP 深度学习软件集成到 Verdin iMX8M Plus BSP 中,具体方法可以参考该文章。
然后下载包含 metadata 的模型文件,使用压缩工具直接解压下载的 tflite 文件(例如 lite-model_ssd_mobilenet_v1_1_metadata_2.tflite)即可获得标签文件 labelmap.txt,该文件中存放了能够识别物体的名字。在应用中我们将会使用该文件来显示所识别物体。模型下载页面介绍了输入和输出数据的结构。例如需要输入 RGB 色彩格式数据。输出数据部分包含被识别物体在图片中的位置,所属分类,对应分类的可信度等。
下面代码为初始化 ssd_mobilenet 模型,并获取关于该模型的基本信息,例如输入图片的大小,后面将摄像头采集到的图片调整对应尺寸。
-------------------------------------
# Load the Tensorflow Lite model.
interpreter = tflite.Interpreter(model_path=PATH_TO_CKPT)
interpreter.allocate_tensors()
# Get model details
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
height = input_details[0]['shape'][1]
width = input_details[0]['shape'][2]
-------------------------------------
将采集到的数据放入模块进行推演运算。
-------------------------------------
# Perform the actual detection by running the model with the image as input
interpreter.set_tensor(input_details[0]['index'],input_data)
interpreter.invoke()
-------------------------------------
最后获取被识别物体的位置,名称和相应的可信度。
-------------------------------------
boxes = interpreter.get_tensor(output_details[0]['index'])[0]
classes = interpreter.get_tensor(output_details[1]['index'])[0]
scores = interpreter.get_tensor(output_details[2]['index'])[0]
-------------------------------------
使用OpenCV 默认的配置读取摄像头时性能不是很理想,因此结合 Verdin iMX8M Plus 本身硬件特点,使用适当的 gstreamer pipeline 进行读取。
-------------------------------------
cv2.VideoCapture(" v4l2src device=/dev/video0 ! image/jpeg,width=1280,height=720,framerate=30/1 ! jpegdec ! videoconvert ! appsink", cv2.CAP_GSTREAMER)
-------------------------------------
最后通过下面命令启动应用程序。
-------------------------------------
root@verdin-imx8mp:~# export XDG_RUNTIME_DIR=/run/user/0
root@verdin-imx8mp:~# python3 tf-lite-detection-webcam.py --modeldir /home/root/PyOpenCV --graph lite-model_ssd_mobilenet_v1_1_metadata_2.tflite --labels labelmap.txt --resolution 1280x720
-------------------------------------
Verdin iMX8M Plus 可以通过 NPU 对应 TF Lite 进行硬件加速,能够实现以40 fps 左右的速度进行物体识别。
在更多的时候,我们可能需要自行采集原始数据并对其进行标记,然后训练模型。下面我们将使用 TensorFlow 分类识别 ECG 心电信号。这过程中会介绍如何在 PC 上使用 MIT-BIH心律失常数据库训练一个 TensorFlow 模型,然后使用 eIQ 将其转换为适合 iMX8M Plus 的 TensorFlow Lite 模型。
首先现从上面链接下载 Python 代码和心律数据。删除已经训练好的模块 ecg_model.h5,然后在 PC 上执行下面命令重新训练模型。根据 PC 性能,这过程会持续一段时间,最后重新生成 ecg_model.h5 文件。
-------------------------------------
$ python3 ecg.py
-------------------------------------
打开 eIQ 工具,使用默认配置将其转化为 TensorFlow Lite 模型 ecg_model.tflite。
在模型转换后输入和输出的数据格式也会发生相应额变化,例如输入固定为 1*300*1。
因此在代码中使用 reshape 函数对数据重新排列。
获得模型对每个心律信号可信度最高的预测。
结合数据库中实际诊断的结果生成一张对比矩阵图。
代码运行期间也记录以一些数据,如总共处理的 27657 个心电信号,首次运行时需要对 iMX8M Plus 的 NPU 进行 warmup,因此耗时为 177ms。其后则能够以 7.5ms 处理每个心电信号。
-------------------------------------
Total 27657signlas
First 10 inferences' time: 177.1 ms
First 10 inferences' time: 7.5 ms
First 10 inferences' time: 7.5 ms
First 10 inferences' time: 7.5 ms
-------------------------------------
总结
Verdin iMX8M Plus 得益于 NPU 能高效地处理神经网络计算。上面是一些简单的演示介绍,为了更好地发挥 NPU 性能,还需要对神经网络模块进行优化。通常现成的模型都是针对算力充足的 PC 所训练,甚至是 GPU 加速。而作为嵌入式系统处理器 iMX8M Plus,还需要兼顾功耗,NPU 算力也无法和桌面级 GPU 相提并论。对模型的优化就显得尤为重要,常见的方法如 quantization,牺牲少量的精度换取更快速的计算。
提交
Verdin AM62 LVGL 移植
基于 NXP iMX8MM 测试 Secure Boot 功能
隆重推出 Aquila - 新一代 Toradex 计算机模块
Verdin iMX8MP 调试串口更改
NXP iMX8MM Cortex-M4 核心 GPT Capture 测试