如何基于iMX8M Plus开发机器学习应用
- 关键词:iMX8M,NXP,NPU
- 摘要:NXP iMX8M Plus 作为其第一款支持神经网络运算硬件加速的处理器,提供对多种框架的支持,例如 ArmNN、TensorFlowLite、ONNX,eIQ Poral 工具可以使用户能够轻松地训练自己地模型,或者将现成的模型转换为适合在 iMX8M Plus 进行加速的模型。本文将介绍如何在 Toradex 的 Verdin iMX8M Plus 计算机模块上使用现成训练好的 TensorFlow Lite 模型开发深度学习应用,以及自行训练模型并借助 eIQ Poral 对模型进行转换使其适合在计算机模块上使用。
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,牺牲少量的精度换取更快速的计算。