作者:Alexey Perminov、Tatiana Khanova、Grigory Serebryakov
在之前的文章中,我们探讨了如何将 Pytorch 模型转换为 OpenVINO 并运行,以及OpenVINO 工具包中可用的深度学习模型优化工具。
今天,让我们看看如何使用 TensorFlow 训练的模型并部署到 OpenVINO 以进行运行。
概述
- 设置环境
- 准备 TensorFlow 模型
- 将模型转换为中间表示格式
- 在 OpenVINO 中运行模型推理
- 结论
设置环境
首先,我们需要准备一个 python 环境:Python 3.5 或更高版本(根据系统要求),我们需要 virtualenv
python3 -m venv ~/venv/tf_openvino source ~/venv/tf_openvino/bin/activate
然后让我们安装所需的包
pip3 install --upgrade pip setuptools pip3 install -r requirements.txt
这里 requirements.txt 包含以下包
numpy tqdm tensorflow-cpu==1.15 argparse scipy imageio moviepy
我们需要做的第二件事是使用官方安装说明安装最新版本的 OpenVINO 工具包(在我的情况下为 Linux)。请记住设置所需的环境变量
source /opt/intel/openvino/bin/setupvars.sh
将此操作添加到 shell 初始化脚本或虚拟环境激活脚本中可能很有用,以便默认情况下触发它。
或者,这里您可以找到一个 Google Colab 笔记本,其中包含环境设置和文章中的主要复现步骤。
准备 TensorFlow 模型
曾经希望一位著名的艺术家为您的心爱的小猫画一幅画吗?随着深度神经网络中工具的演变——您做到了。最初在艺术风格的神经算法中提出的神经风格迁移算法可以实现您的愿望。其想法是利用神经网络提取图像内容并将其与使用的表示(风格)分离。然后,我们将使用提取的风格并将其与任意图像组合,以获得令人印象深刻的结果,这些结果由原始图像的内容和所需的艺术风格生成的合成图像。
图像风格迁移示例
在上面的示例中,您可以看到 J. M. W. 特纳的“弥诺陶尔的沉船”绘画的艺术风格是如何转移到参考小猫图像(由Dương Nhân提供)。要执行此类技巧,我们需要一个经过训练的 TensorFlow 模型。我们可以从头开始准备和训练模型,但让我们获取一个预训练模型并使用此仓库中的快速风格迁移模型。它非常适合我们的目的。
引用的存储库提供了多个模型检查点,每个检查点都针对不同的艺术风格图像进行了训练,可以在这里下载。通常,TensorFlow 检查点包含训练期间使用的模型权重和计算图元数据。要将模型部署到生产环境中并将其用于推理,我们需要获取冻结图。让我们克隆仓库并使用一个简单的 python 脚本来做到这一点
def main(checkpoint_path, input_shape, out_graph_name): # Init graph and session to be used g = tf.Graph() soft_config = tf.compat.v1.ConfigProto(allow_soft_placement=True) with g.as_default(), g.device('/cpu'), tf.compat.v1.Session(config=soft_config) as sess: # Placeholder variable for graph input img_placeholder = tf.compat.v1.placeholder(tf.float32, shape=input_shape, name='img_placeholder') # The model from the repo transform.net(img_placeholder) # Restore model from checkpoint saver = tf.compat.v1.train.Saver() saver.restore(sess, checkpoint_path) # Freeze graph from the session. # "add_37" is the actual last operation of graph frozen = tf.compat.v1.graph_util.convert_variables_to_constants(sess, sess.graph_def, ["add_37"]) # Write frozen graph to a file graph_io.write_graph(frozen, './', out_graph_name, as_text=False) print(f'Frozen graph {out_graph_name} is saved!')
脚本的完整代码可以在这里下载。
只需将脚本放在模型仓库的根文件夹中,并使用以下参数执行它
python get_frozen_graph.py --checkpoint models/wreck.ckpt
在上面的代码片段中,我们执行了所需的 TensorFlow 图预初始化,并使用tf.Saver()从检查点恢复模型数据。然后我们将转换后的冻结图写入文件。
请注意,冻结图转换需要输出图操作的名称,在本例中为“add_37”。对于任意模型,您可以通过简单地打印网络节点或在Netron之类的工具中浏览模型来找到输出操作。
将模型转换为中间表示格式
好的,现在我们有了冻结图,接下来是什么?至于PyTorch 模型,要在 OpenVINO 推理引擎中运行推理,我们必须将模型转换为中间表示 (IR) 格式。幸运的是,OpenVINO 模型优化器内置了对 TensorFlow 模型转换的支持。您可以在此OpenVINO 页面上查看当前支持的 TensorFlow 操作集。
在开始之前,我们应该配置模型优化器(如果您在 OpenVINO 安装过程中跳过了此步骤)。您可以在此处找到配置说明。
由于我们准备好的冻结图已经包含了有关模型的所有必要信息,例如所需的输入形状和输出节点名称,因此我们可以使用默认参数运行模型优化器
mo_tf.py --input_model inference_graph.pb
如果转换成功,我们将获得包含结果 IR 模型描述的`inference_graph.xml`和包含模型权重数据的`inference_graph.bin`。如果转换不成功,最好从检查目标框架(在本例中为 TensorFlow)的支持层开始。可能需要稍微更改模型架构或为 OpenVINO实现自定义层。
在 OpenVINO 中运行模型推理
让我们准备一个使用 OpenVINO 推理引擎初始化、IR 模型加载和对提供的图像进行推理的简单 python 脚本。此脚本的完整版本也可在这里找到。
首先,我们导入所需的包并定义一个用于参数解析的函数。
import os import cv2 import argparse import time import numpy as np from openvino.inference_engine import IECore from tqdm import tqdm IMG_EXT = ('.png', '.jpg', '.jpeg', '.JPG', '.JPEG') def parse_args(): """Parses arguments.""" parser = argparse.ArgumentParser(description='OpenVINO inference script') parser.add_argument('-i', '--input', type=str, default='', help='Directory to load input images, path to a video or ' 'skip to get stream from the camera (default).') parser.add_argument('-m', '--model', type=str, default='./models/inference_graph.xml', help='Path to IR model') return parser.parse_args()
下一个函数用于 OpenVINO 推理初始化和中间表示模型加载。我们获取 .xml 和 .bin 模型文件的路径,读取它们并将模型加载到推理引擎中。之后,我们可以将其用于推理。
def load_to_IE(model): # Getting the *.bin file location model_bin = model[:-3] + "bin" # Loading the Inference Engine API ie = IECore() # Loading IR files net = ie.read_network(model=model, weights=model_bin) input_shape = net.inputs["img_placeholder"].shape # Loading the network to the inference engine exec_net = ie.load_network(network=net, device_name="CPU") print("IR successfully loaded into Inference Engine.") return exec_net, input_shape
OpenVINO 允许我们使用两种推理请求:同步——每个后续请求仅在先前请求完成后执行,异步——多个请求由多个执行器同时执行。在本例中,我们使用同步推理请求接口
def sync_inference(exec_net, image): input_blob = next(iter(exec_net.inputs)) return exec_net.infer({input_blob: image})
在主函数中,我们首先准备将用于风格迁移的图像列表,然后初始化推理引擎
def main(args): if os.path.isdir(args.input): # Create a list of test images image_filenames = [os.path.join(args.input, f) for f in os.listdir(args.input) if os.path.isfile(os.path.join(args.input, f)) and f.endswith(IMG_EXT)] image_filenames.sort() else: image_filenames = [args.input] exec_net, net_input_shape = load_to_IE(args.model) # We need dynamically generated key for fetching output tensor output_key = list(exec_net.outputs.keys())[0]
对于每个输入图像,我们将其调整为网络的输入大小并使用 cv2.dnn.blobFromImage 转换为所需的张量格式。然后,最有趣的部分——推理请求,然后进行简单的后处理。
for image_num in tqdm(range(len(image_filenames))): image = cv2.imread(image_filenames[image_num]) image = cv2.resize(image, (net_input_shape[3], net_input_shape[2])) X = cv2.dnn.blobFromImage(image, swapRB=True) out = sync_inference(exec_net, image=X) result_image = np.squeeze(np.clip(out[output_key], 0, 255).astype(np.uint8), axis=0).transpose((1, 2, 0))
最后,我们显示结果图像。
cv2.imshow("Out", cv2.cvtColor(result_image, cv2.COLOR_RGB2BGR)) cv2.waitKey(0) cv2.destroyWindow("Out") if __name__ == "__main__": main(parse_args())
让我们运行脚本,指定要应用风格迁移的图像的输入目录和转换后的 IR 模型
python openvino_inference.py -i ./images/ -m ./models/inference_graph.xml
带有转移风格的结果图像将显示在弹出窗口中。
性能比较
作为最后一步,让我们比较原始 TensorFlow 和转换为 OpenVINO 推理管道的推理时间。为此,我在推理调用周围添加了时间戳测量:在 TensorFlow 的情况下为会话运行调用,在 OpenVINO 的情况下为同步推理请求。在 100 个相同大小(720x1024x3)的图像上平均,每个图像的性能结果非常相似(以秒为单位,CPU:Intel® Core™ i5-8265U CPU @ 1.60GHz x 8)
OpenVINO_CPU Inference time: Mean: 1.554 Min: 1.444 Max: 1.979 TensorFlow_Cpu Inference time: Mean: 1.933 Min: 1.827 Max: 2.080
结论
在这篇简短的文章中,我们了解了如何轻松地转换 TensorFlow 模型并在 OpenVINO 推理引擎环境中运行。此外,我们还了解了神经风格迁移算法的应用,并尝试将其应用于任意图像。我们已经证明,OpenVINO 提供了相当大的加速,并允许我们在相当普通的硬件上运行即使是最苛刻的 DL 算法。我们希望这是一次有趣且有益的旅程。
________________________________________
获取英特尔® OpenVINO™ 工具套件
贡献——如果您有任何关于如何改进产品的想法,我们欢迎您为开源的 OpenVINO™ 工具套件做出贡献。
想了解更多信息?加入对话,讨论英特尔的社区论坛中所有关于深度学习和 OpenVINO™ 工具套件的内容。
英特尔、英特尔标识和其他英特尔商标是英特尔公司或其子公司的商标。
性能因使用、配置和其他因素而异。在www.Intel.com/PerformanceIndex了解更多信息。
________________________________________
性能结果基于截至显示在配置中的日期的测试,可能无法反映所有公开发布的更新。请参阅备份以了解配置详细信息。没有任何产品或组件可以绝对安全。
测试日期:2020 年 12 月 23 日
完整的系统配置详细信息:Ubuntu 18.04,Intel® Core™ i5-8265U CPU @ 1.60GHz x 8
设置详细信息:OpenVINO™ 工具套件版本 2020.4
谁进行了测试:Alexey Perminov,OpenCV.AI
英特尔技术可能需要启用硬件、软件或服务激活。
________________________________________
© 英特尔公司。英特尔、英特尔标识和其他英特尔商标是英特尔公司或其子公司的商标。