概述
神经网络经过训练,能够识别包括火灾或火焰在内的图像,可以使火灾探测系统更可靠且更具成本效益。本教程演示如何使用新发布的 Python API 用于 Arm NN 推理引擎,将图像分类为”Fire”而不是”非火灾”。
什么是臂 NN 和 PyArmNN?
ARM NN是 CPU、GPU 和 NPO 的推理引擎。它在设备上执行 ML 模型,以便根据输入数据进行预测。Arm NN 支持有效转换现有神经网络框架,如 TensorFlow Lite、TensorFlow、ONNX 和 Caffe,允许它们高效运行,无需修改臂 Cortex-A CPU、Arm Mali GPU 和 Arm Ethos NPO。
PyArmNN 是新开发的用于 Arm NN SDK 的 Python 扩展。在本教程中,我们将使用 PyArmNN API 运行火灾探测图像分类模型 fire_detection.tflite,并将推理性能与树莓派上的 TensorFlow Lite 进行比较。
Arm NN 提供 TFLite 解析器 armnnTfLiteParser,这是一个用于将 TensorFlow Lite FlatBuffers 文件定义的神经网络加载到 Arm NN 运行时的库。我们将使用 TFLite 解析器来分析”Fire”与”非火灾”图像分类的火灾检测模型。
我们需要什么?
- 树莓派。我测试与树莓派 4 与树栖 10 操作系统.Pi 设备由 Arm Cortex-A72 处理器提供支持,该处理器可以利用 Arm NN SDK 的强大功能来加速 ML 性能。
- 在继续项目设置之前,您需要签出并为您的树莓派构建 Arm NN 版本 19.11 或更高版本。说明在这里。
- PyArmNN 封装
- fire_detection.tflite,从本教程生成并转换为 TensorFlow 精简模型。
使用 PyArmNN 运行 ML 推理
要在设备上运行 ML 模型,我们的主要步骤是:
- 导入 pyarmnn 模块
- 加载输入图像
- 创建解析器并加载网络
- 选择后端、创建运行时并优化模型
- 执行推理
- 解释和报告输出
导入 pyarmnn 模块
98264px;左图:35.9722 px;”>
xxxxxxxxxx
进口丸
从PIL导入映像
进口皮阿姆恩作为安
1px;”•将 numpy 导入为 np
导入cv2
打印(f"使用 ARMNN _ann 工作。ARMNN_VERSION*")
我们的模型是浮点模型。我们必须将输入图像值缩放到 -1 到 1 的范围。
xxxxxxxxx
2222px;”>
解析器argparse.参数分析器(
formatter_class=阿加帕。参数默认帮助物质)
解析器.add_argument(
"-图像"帮助=需要"图像文件的文件路径"=True)
args解析器.parse_args()
1px;”• 加载图像。
图像cv2。imread(args. .图像)
图像cv2。调整大小(图片, (128128)
图像np.数组(图像dtype=np.浮动32/255.0
打印(图像.大小)
创建分析器并加载网络
使用 Armn NN 时,下一步是创建将用于加载网络文件的解析器对象。Arm NN 具有用于各种模型文件类型的解析器,包括 TFLite、ONNX、Caffe 等
在此示例中,我们将创建一个 TfLite 解析器,以便从指定的路径加载我们的 TensorFlow Lite 模型:
xxxxxxxxx
解析器安.ITfLiteParser()
网络解析器.创建网络从二进制文件('
tflite’)
获取输入绑定信息
创建后,解析器用于提取网络的输入信息。
我们可以通过调用GetSubgraphInputTensorNames() 提取所有输入名称,然后使用它们获取输入绑定信息。在此示例中,由于我们的模型只有一个输入层,我们使用input_names[0] 来获取输入张数,然后使用此字符串检索输入绑定信息。
输入绑定信息包含有关输入的所有基本信息,它是一个元组,由可绑定层(输入、输出)的整数标识符和张量信息(数据类型、量化信息、维度数量、总数)组成。元素)。
xxxxxxxxx
2222px;”>
graph_id0
input_names解析器.获取子图输入tensor名称(graph_id)
input_binding_info解析器.获取网络输入绑定信息(graph_idinput_names=0+)
input_tensor_idinput_binding_info=0|
input_tensor_infoinput_binding_info=1|
9896px;”>
张子 ID: [input_tensor_id],
张数信息: [input_tensor_info]
""")
选择后端、创建运行时和优化模型
指定可以优化网络的后端列表。
xxxxxxxxx
2222px;”>
选项ann.创建选项()
运行时安。IRuntime(选项)
• 列表中前面的后端选项具有较高的首选项。
首选回端= =ann。后端 Id("CpuAcc"ann.后端 Id("CpuRef")|
opt_network消息ann
获取设备规格(),安。优化器选项())
将优化的网络加载到运行时
在运行时上下文中加载优化的网络。LoadNetwork() 为层创建特定于后端的工作负载。
xxxxxxxxx
net_id=运行时。负载网络(opt_network)
打印(f"已加载网络, id_net_id}")
input_tensors安.make_input_tensors(*input_binding_info*, *图像*)
获取输出绑定信息并使输出张力
与输入绑定信息类似,我们可以从解析器中检索输出张量名称并获取绑定信息。
在我们的示例中,认为图像分类模型只有一个输出,因此它只使用返回的列表中的名字,并且可以轻松地扩展到output_names上的多个输出循环。
9722px;”>
xxxxxxxxx
• 使用图层名称获取输出图层的输出绑定信息。
output_names解析器.获取子输出tensor名称(graph_id)
output_binding_info解析器.获取网络输出绑定信息(0output_names=0+)
1px;”[output_tensors ]安.make_output_tensors(=output_binding_info*)
执行推理
运行时上下文的性能推理 Enqueueat() 函数对加载的网络执行推理。
xxxxxxxxx
队列工作量(0, input_tensors, output_tensors)
输出output_tensor_info安。from_output_tensor(output_tensors=0+1*)
打印(f"输出张量信息: [output_tensor_info]")
下面是我们完整的 Python 代码predict_pyarmnn.py:
创建选项()
运行时 = ann。IRuntime(选项)
• 列表中前面的后端选项具有较高的首选项。
首选回端 = _ann。后端Id(”CpuAcc”),安。后端 Id(”CpuRef”)*
opt_network,消息 = Ann。优化(网络、首选后端、运行时)。获取设备规格(),安。优化器选项())
• 将优化的网络加载到运行时。
net_id,= = 运行时。加载网络(opt_network)
打印(f”已加载网络,id_net_id]”
• 创建用于推理的输入张力。
input_tensors = 安.make_input_tensors([input_binding_info],[图像])
• 使用图层名称获取输出图层的输出绑定信息。
output_names = 解析器。获取子图输出名称(graph_id)
output_binding_info = 解析器。获取网络输出绑定信息(0,output_names{0})
output_tensors = 安.make_output_tensors([output_binding_info])
运行。队列工作量(0、input_tensors、output_tensors)
输出,output_tensor_info = ann.from_output_tensor(output_tensors{0}{1})
打印(f”输出张量信息:[output_tensor_info]”
打印(输出)
j = np.argmax(输出)
如果 j = 0:
打印(”非火灾”)
还:
打印(”火”)”数据朗=”文本/x-python”*
xxxxxxxxx
1px;”•进口 PIL
从PIL导入映像
进口pyarmnn作为安
将numpy导入为np
导入cv2
进口阿根特
ARMNN_VERSION*))
#Load图像
解析器argparse.参数分析器(
formatter_class=阿加帕。参数默认帮助物质)
解析器.add_argument(
1px;”[ -图像’,帮助=“图像文件的文件路径”,需要=True)
args解析器.parse_args()
图像cv2。imread(args. .图像)
图像cv2。调整大小(图片, (128128)
图像np
浮动32)/ 255.0
打印(图像.形状)
• ONNX、Caffe 和 TF 解析器也存在。
解析器安.ITfLiteParser()
网络解析器.创建网络从二进制文件('./fire_detection.tflite')
9896px;”>
input_names解析器.获取子图输入tensor名称(graph_id)
input_binding_info解析器.获取网络输入绑定信息(graph_idinput_names=0+)
input_tensor_idinput_binding_info=0|
input_tensor_infoinput_binding_info=1|
打印(f"""
9896px;”>
张数信息: [input_tensor_info]
""")
• 创建将执行推理的运行时对象。
选项ann.创建选项()
运行时安。IRuntime(选项)
首选回端= =ann。后端 Id("CpuAcc"ann.后端 Id("CpuRef")|
opt_network消息ann。优化(网络首选后端运行时。获取设备规格安。优化器选项())
• 将优化的网络加载到运行时。
net_id=运行时
9896px;”>
打印(f"已加载网络, id_net_id}")
• 创建用于推理的输入张力。
input_tensors安.make_input_tensors(*input_binding_info*, *图像*)
• 使用图层名称获取输出图层的输出绑定信息。
output_names解析器.获取子输出tensor名称(graph_id)
1px;”[output_binding_info =解析器。获取网络输出绑定信息(0, output_names=0*)
output_tensors安.make_output_tensors(=output_binding_info*)
运行时。队列工作量(0input_tensorsoutput_tensors)
输出output_tensor_info安。from_output_tensor(output_tensors=0+1*)
打印(f"输出张量信息: [output_tensor_info]")
9896px;”>
jnp.argmax(输出)
如果j0:
印刷("非火")
其他:
印刷("火")
从命令行运行 Python 脚本:
cheeli.com.cn/wp-内容/上传/2020/03/13094343-158322290026.png”样式-“宽度:300px;”/>
xxxxxxxxxx
$ python3-- 图像
Jpg
20190800
15616,
1000449152|
1283)
000000, 量化偏移: 0, 数值维度: 2, 数字元素: 2|
0.00323252*
非火
在我们的示例中,类 0 的可能性为 0.9967675,而类 1 的可能性为 0.00323252,在映像中未检测到火灾。
PyArmNN vs 张力流精简版性能基准测试
作为下一步,我们将测试 PyArmNN 和 TensorFlow Lite Python API 在树莓派上的性能。
TensorFlow Lite 使用解释器执行推理。解释器使用静态图形排序和自定义(不太动态的)内存分配器。要了解如何使用 Python API 加载和运行模型,请参阅 TensorFlow Lite文档。
为了进行性能基准测试,使用我们的火灾检测模型进行了推断。在我们的示例中,我们只运行一次推理。我们还可以多次运行模型,并采用平均推断时间。下面是我们的predict_tflite.py 代码:
参数分析器(
formatter_class\argparse。参数默认帮助物质)
解析器.add_argument()
“-图像”,帮助=”图像文件的文件路径”,需要\True)
args = 解析器.parse_args()
图像 = cv2.imread(args.image)
图像 = cv2.调整大小(图像,(宽度、高度))
图像 = np.expand_dims(图像,轴=0)
如果floating_model:
图像 = np.array(图像,dtype_np.float32) / 255.0
• 在图像上测试模型。
解释器.set_tensor(input_details[0]”索引”,图像)
开始 = 计时器()
解释器.invoke()
结束 = 计时器()
打印(”已运行时间是”,(结束-开始)=1000,”ms”)
• 函数”get_tensor()”返回张量数据的副本。
• 使用”张”来获取指向张条的指针。
output_data = 解释器.get_tensor(output_details{0}”索引”)
印刷(output_data)
j = np.argmax(output_data)
如果 j = 0:
打印(”非火灾”)
还:
打印(”火”)”数据朗=”文本/x-python”*
xxxxxxxxx
9896px;”>
进口阿根特
导入io
导入时间
导入cv2
将numpy导入为np
从PIL导入映像
从时间导入default_timer作为计时器
1px;”>
• 加载 TFLite 模型并分配张量。
翻译tf.精简。口译员(model_path="./fire_detection.tflite")
口译员。allocate_tensors()
• 获取输入和输出张量。
input_details翻译。get_input_details()
get_output_details()
[,高度,宽度,]input_details=0="形状"
floating_model错误
如果input_details=0="dtype"np。浮动32:
floating_model真实
解析器argparse.参数分析器(
参数默认帮助物质)
解析器.add_argument(
"-图像"帮助=需要"图像文件的文件路径"=True)
args解析器.parse_args()
图像cv2。imread(args. .图像)
图像cv2。调整大小(图像, (宽度高度)
expand_dims(图像,轴=0)
如果floating_model:
图像np.数组(图像dtype=np.浮动32/255.0
• 在图像上测试模型。
口译员。set_tensor(input_details=0="索引"图像)
9896px;”>
口译员。调用()
端计时器()
打印(''运行时间是', (结束-开始)=1000'ms'
• 函数"get_tensor()"返回张量数据的副本。
• 使用"张"来获取指向张条的指针。
get_tensor(output_details=0=“索引”*)
印刷(output_data)
jnp.阿格马克斯(output_data)
如果j0:
印刷("非火")
其他:
印刷("火")
xxxxxxxxxx
$ python3-- 图像./图像/746.jpg
609188: E
运行时间是38.02500700112432 ms
9.9900925e-01*
火
我们扩展predict_pyarmmnn.py 使用相同的代码进行推理基准测试。
xxxxxxxxx
2222px;”>
启动计时器()
运行时。队列工作量(0input_tensorsoutput_tensors)
端计时器()
打印(''运行时间是', (结束-开始=1000'ms')
再次运行 Python 脚本:
224445023108274 ms
输出张量信息: TensorInfo_DataType: 1, 已量化: 0, 量化ScaleScale: 0.000000, 量化偏移: 0, 数值: 2, 数值: 2]
[0.0009907632, 0.99900925]
火”数据朗=”文本/x-sh”*
xxxxxxxxx
$ python3-- 图像./图像/746.jpg
20190800
9896px;”>
15616,
1000449152|
id=0
21.224445023108274 ms
100022|
1px;”[0.0009907632, 0.99900925]
火
从结果中,您可以使用 PyArmNN API 观察推理性能增强。
后续步骤和有用资源
本教程演示如何使用 Arm NN Python API 将图像分类为”火”与”非火灾”。您还可以使用它作为处理其他类型的神经网络的起点。
要了解有关 Arm NN 的更多信息,请查看以下资源: