在本教程中,我将演示如何将用 TF 2.0 编写的预训练网络转换为适合推理的优化网络,该网络采用一些高级体系结构。目的是使用OpenCV 的Dnn 模块在C++运行模型,但优化的模型可以在 Python 中使用,初始模型可以使用 TensorRT 运行。
在 TF 2.0 中训练模型后,我寻找一种优化模型进行推理的简单方法。但是,我没有找到一个地方,指导我如何做到这一点在TF 2.0,因为TF删除了他们的支持在冻结优化的图形,从所有投诉堆积在StackOverflow(例如,1,2)。
有很多解决方案写在不同的互联网论坛。我正在写一个指南,关于我发现最简单的方法。
系统规格
阿纳康达3 4.4€,
张力2.0,
OpenCV 4.1.2°,
您可能还喜欢:
张力流简介。
开始
在网络实现中,我使用了:
- 数据集和迭代器 (
tf.data.dataset
。 - 占位符 (
tf.placeholder
。 - 卷积 (
tf.layers.conv2d
). - 深度卷积 ( 和
tf.nn.depthwise_conv2d
td.nn.bias_add
) - 雷卢6
tf.nn.relu6
() - 批处理规范化
tf.layers.batch_normalization
()。 - 平展
tf.layers.flatten
() - 软最大值
tf.nn.softmax
()。 - 全球平均数 (
tf.layers.average_pooling2d
。
培训后,我们希望将模型导出到 .pb 文件,以在推理时运行。Tensorflow 具有用于发布模型的简单代码 API:
tf.saved_model.simple_save(sess,path,inputs,outputs)
但是,这将导出许多文件中的完整模型,包括图形 def、变量,并且不会删除摘要,这在推理时是不必要的。这限制了使用 GPU 的性能,因为不必要的网络组件通常在 CPU 上运行。
在 TF 2.0 之前,最佳做法是:
- 冻结模型(将图形 def 与检查点组合在一起,并将所有变量转换为仅一个 pb 文件中的 const)
- 优化冻结图形进行推理,包括:
- 删除未使用的节点。
- 将算术和表达式折叠到常量。
- 删除标识,不进行操作操作。
- 将批处理规范化折叠成简单的乘法。
- 按执行顺序排序,这是在 OpenCV 中运行它所必需的
com/张力流/张力流/斑点/主/拉伸流/工具/graph_transforms/README.md”rel=”无跟踪”目标=”_blank”=图形变换工具,并集成在 TensorFlow 工具库中。直到 TF2.0,TF 删除了他们的支持和图形使用代码,因为 tf.compact1.graph_util
基本上是空的。相反,他们希望开发人员使用保存模型API。但是,其他库和推理模块不支持它,TF 用户需要打破他们的头,以找到优化其模型的方法。
我将详细说明我所做的,以冻结我的模型:
提前编写代码以适合推理
使用名为 的标志 Inference
。
对于迭代器使用:
xxxxxxx
1px;”[ X,y=迭代器.get_next()
is_training=tf。占位符(tf.布尔名称="is_training")
其他:
X =tf。 占位符(tf.浮点32,形状=...
y=tf。占位符(tf.浮点32,形状=...
is_training =tf。 常数(tf。布尔名称="is_training")
它有助于从开发开始考虑推论。例如,我在训练期间修改了平均池的实现,从使用 average_pooling2d
到只使用 reduce_sum
,这更简单,将在更多的平台上运行。
您还可以在此标志下为摘要和文件编写器添加处理。不要在后期培训时删除它们,只是不要添加它们:)
在 TF 2.0 中训练模型
保存模型的检查点,使用:
tf.train.Saver(tf.all_varibles()). save(sess,path)
使用以下功能保存模型的图形定义:
Tf.train.write_graph(sess.graph,path)
使用张量流 1.15 创建新环境,并运行以下代码:
xxxxxxx
蛇,工具导入freeze_graph,optimize_for_inference_lib
freeze_graph.freeze_graph(input_graph_path,input_saver_def_path ="
输入二进制=false,checkpoint_path=checkpoint_path,
output_nodes="预测"*,restore_op_name""
文件名tensor_名=""clear_devices=false,")
图形定义()
与tf。gfile.打开(冻结图形路径"rb"为f:
数据2readf.读取()
输入图。解析从String(数据 2read)
输出图optimize_for_inference_lib。
optimize_for_inference(输入图, [输入节点名称],
1px;”[ tf.浮点32.作为数据类型枚举)
与tf。gfile.FastGFile(优化的图形路径'w'作为f :
f. .写入(输出图)。序列化到串())
此代码应工作得完美无缺,但无法处理我的特定模型。我有例外:
“Didn’t find expected Conv2D input to bn”
这很奇怪,我开始研究我的代码,以及问题是否在我的网络中,或者环境的变化。
最后,我发现这不是我的假设。我发现 TF1.15 代码没有更新与最新的图形转换工具代码在其 inference_lib
。代码的问题是假定批处理规范化接受 Conv2D 操作作为输入。但是,在我的网络中,我使用偏置, BiasAdd
在应用批处理规范化之前使用生成的操作
在尝试修复 Bug 之前,我联机搜索,并看到它已在 GitHub 中得到处理,但它未在 TF 中更新,也不会更新,因为它已在 TF2.0 中删除。
我修改了 TF 代码,并在 以下文件中修补了文件:
%installation python folder%/tensorflow/python/tools/optimjzed_for_inference_
lib
com/rangit3/片段/blob/master/optimize_for_inference_lib.py”rel=”不跟随”目标=”_blank”=代码。修复后,我的代码不会返回任何错误。
我希望本指南将帮助有人在那里转换用TF2.0编写的模型在推理时运行。
祝你好运:)
在我的下一篇文章中,我将演示如何在C++ OpenCV 和 Python 中的 TF 上的 OpenCV 上进行推理时运行优化的图形。我会标杆他们(提示:在CPU上,他们是相当相等的)。