无法测试和部署Deeplabv3-mobilenetv2 Tensorflow-Lite分割模型以进行推理

时间:2018-11-09 15:47:11

标签: android tensorflow tensorflow-lite deeplab

我们正在尝试使用deeplabv3和mobilenetv2在android上运行语义分割模型。我们在bazel的帮助下遵循了使用TOCO和tflite_convert的官方tensorflow lite转换过程。源冻结图是从官方TensorFlow DeepLab Model Zoo获得的

我们能够使用以下命令成功转换模型:-

  

CUDA_VISIBLE_DEVICES =“ 0” toco --output_file = toco256.tflite   --graph_def_file =路径/到/deeplab/deeplabv3_mnv2_pascal_trainval/frozen_inference_graph.pb   --input_arrays =图像张量器--output_arrays =语义预测--input_shapes = 1,256,256,3 --inference_input_type = QUANTIZED_UINT8 --inference_type = FLOAT --mean_values = 128 --std_dev_values = 127 --allow_custom_ops --post_training_quantize

tflite文件的大小约为2.25 Mb。但是,当我们尝试使用官方基准测试工具测试该模型时,它失败并显示以下错误报告:-

bazel run -c opt tensorflow/contrib/lite/tools/benchmark:benchmark_model -- --graph=`realpath toco256.tflite`
INFO: Analysed target //tensorflow/contrib/lite/tools/benchmark:benchmark_model (0 packages loaded).
INFO: Found 1 target...
Target //tensorflow/contrib/lite/tools/benchmark:benchmark_model up-to-date:
  bazel-bin/tensorflow/contrib/lite/tools/benchmark/benchmark_model
INFO: Elapsed time: 0.154s, Critical Path: 0.00s
INFO: 0 processes.
INFO: Build completed successfully, 1 total action
INFO: Running command line: bazel-bin/tensorflow/contrib/lite/tools/benchmark/benchmark_model '--graph=path/to/deeplab/venINFO: Build completed successfully, 1 total action
STARTING!
Num runs: [50]
Inter-run delay (seconds): [-1]
Num threads: [1]
Benchmark name: []
Output prefix: []
Warmup runs: [1]
Graph: path/to/venv/tensorflow/toco256.tflite]
Input layers: []
Input shapes: []
Use nnapi : [0]
Loaded model path/to/venv/tensorflow/toco256.tflite
resolved reporter
Initialized session in 45.556ms
Running benchmark for 1 iterations 
tensorflow/contrib/lite/kernels/pad.cc:96 op_context.dims != 4 (3 != 4)
Node number 24 (PAD) failed to prepare.

Failed to invoke!
Aborted (core dumped)

我们也尝试了相同的命令,但不包括'allow_custom_ops'和'post_training_quantize'选项,甚至使用了与1,513,513,3相同的输入大小;但是结果是一样的。

此问题似乎与以下github问题类似:  (https://github.com/tensorflow/tensorflow/issues/21266)。但是,在最新版本的TensorFlow中,该问题应该已解决。

型号:http://download.tensorflow.org/models/deeplabv3_mnv2_pascal_trainval_2018_01_29.tar.gz Tensorflow版本:1.11 Bazel版本:0.17.2 操作系统:Ubuntu 18.04

Android应用程序也无法正确加载模型(tflite解释器)

那么,如何将细分模型正确转换为可在Android设备上进行推理的tflite格式?

更新:-

使用tensorflow 1.12,我们遇到了一个新错误:

$ bazel run -c opt tensorflow/lite/tools/benchmark:benchmark_model -- --graph=`realpath /path/to/research/deeplab/venv/tensorflow/toco256.tflite`

    tensorflow/lite/kernels/depthwise_conv.cc:99 params->depth_multiplier * SizeOfDimension(input, 3) != SizeOfDimension(filter, 3) (0 != 32)
    Node number 30 (DEPTHWISE_CONV_2D) failed to prepare.

此外,当使用来自Tensorflow Deeplab model zoo的,相同模型的新版本(3 Mb .pb文件),depth_multiplier = 0.5时,我们得到了另一个错误:-

F tensorflow/lite/toco/graph_transformations/propagate_fixed_sizes.cc:116] Check failed: dim_x == dim_y (3 vs. 32)Dimensions must match

在这种情况下,我们使用了与上述相同的命令进行tflite转换;但是我们甚至无法生成一个'tflite'文件作为输出,这似乎与深度倍增值有关(即使我们尝试给出depth_multiplier也是如此)参数作为转换时的参数)。

2 个答案:

答案 0 :(得分:0)

我有同样的问题。来自https://github.com/tantara/JejuNet的消息,我看到他已成功将模型转换为tflite。我向他求助,可惜目前没有任何回应。

答案 1 :(得分:0)

我也遇到了这个问题。转换中似乎有2个问题:

  • 输入张量具有动态形状,即[?,?,?,3]
  • pad_to_bounding_box节点部件不会自动转换为静态形状

对于以下解决方案,已在以下位置进行了测试:

  • Tensorflow 1.15
  • Ubuntu 16.0.4

解决方案

我假设您已经使用deeplab文件夹中的export_model.py文件创建了一个.pb文件,并将其命名为deeplab_mobilenet_v2.pb。从这里开始:

步骤1:优化推理

python3 optimize_for_inference.py \
        --input "path/to/your/deeplab_mobilenet_v2.pb" \
        --output "path/to/deeplab_mobilenet_v2_opt.pb" \
        --frozen_graph True \
        --input_names ImageTensor \
        --output_names SemanticPredictions \
        --placeholder_type_enum=4

placeholder_type_enum = 4是uint8数据类型(dtypes.uint8.as_datatype_enum)

步骤2:应用图形转换工具

确保已安装bazel并已从github下载tensorflow r1.15分支。然后从tensorflow回购中制作transform_graph工具:

bazel build tensorflow/tools/graph_transforms:transform_graph

然后运行transform_graph工具(确保将形状设置为您用作输入的任何形状):

bazel-bin/tensorflow/tools/graph_transforms/transform_graph \
--in_graph="/path/to/deeplab_mobilenet_v2_opt.pb" \
--out_graph="/path/to/deeplab_mobilenet_v2_opt_flatten.pb" \
--inputs='ImageTensor' \
--outputs='SemanticPredictions' \
--transforms='
    strip_unused_nodes(type=quint8, shape="1,400,225,3")
    flatten_atrous_conv
    fold_constants(ignore_errors=true, clear_output_shapes=false)
    fold_batch_norms
    fold_old_batch_norms
    remove_device
    sort_by_execution_order'

步骤3:旁路pad_to_bounding_box节点并输入静态信息

运行以下python文件,确保将model_filepath,save_folder和save_name更改为适合您需要的任何内容。

import tensorflow as tf
import numpy as np
from tensorflow.contrib import graph_editor as ge

def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
    """
    Freezes the state of a session into a pruned computation graph.

    Creates a new computation graph where variable nodes are replaced by
    constants taking their current value in the session. The new graph will be
    pruned so subgraphs that are not necessary to compute the requested
    outputs are removed.
    @param session The TensorFlow session to be frozen.
    @param keep_var_names A list of variable names that should not be frozen,
                          or None to freeze all the variables in the graph.
    @param output_names Names of the relevant graph outputs.
    @param clear_devices Remove the device directives from the graph for better portability.
    @return The frozen graph definition.
    """
    graph = session.graph
    with graph.as_default():
        freeze_var_names = list(set(v.op.name for v in tf.global_variables()).difference(keep_var_names or []))
        output_names = output_names or []
        output_names += [v.op.name for v in tf.global_variables()]
        input_graph_def = graph.as_graph_def()
        if clear_devices:
            for node in input_graph_def.node:
                node.device = ""
        frozen_graph = tf.graph_util.convert_variables_to_constants(
            session, input_graph_def, output_names, freeze_var_names)
        return frozen_graph

def load_convert_save_graph(model_filepath, save_folder, save_name):
    '''
    Lode trained model.
    '''
    print('Loading model...')
    graph = tf.Graph()
    sess = tf.InteractiveSession(graph = graph)

    with tf.gfile.GFile(model_filepath, 'rb') as f:
        graph_def = tf.GraphDef()
        graph_def.ParseFromString(f.read())

    print('Check out the input placeholders:')
    nodes = [n.name + ' => ' +  n.op for n in graph_def.node if n.op in ('Placeholder')]
    for node in nodes:
        print(node)

    # Define input tensor
    input = tf.placeholder(np.uint8, shape = [1,400,225,3], name='ImageTensor')

    tf.import_graph_def(graph_def, {'ImageTensor': input}, name='')

    print('Model loading complete!')

    # remove the pad to bounding box node
    name = "pad_to_bounding_box"
    print(name)
    sgv = ge.make_view_from_scope(name, tf.get_default_graph())
    print("\t" + sgv.inputs[0].name)
    for node in sgv.inputs:
        print("name in = " + node.name)
    for node in sgv.outputs:
        print("name out = " + node.name)
    print("\t" + sgv.outputs[len(sgv.outputs)-1].name)
    sgv = sgv.remap_inputs([0])
    sgv = sgv.remap_outputs([len(sgv.outputs)-1])
    (sgv2, det_inputs) = ge.bypass(sgv)


    frozen_graph = freeze_session(sess,
                              output_names=['SemanticPredictions'])
    tf.train.write_graph(frozen_graph, save_folder, save_name, as_text=False)


load_convert_save_graph("path/to/deeplab_mobilenet_v2_opt_flatten.pb", "/path/to", "deeplab_mobilenet_v2_opt_flatten_static.pb")

第4步:转换为Tflite

tflite_convert \
  --graph_def_file="/path/to/deeplab_mobilenet_v2_opt_flatten_static.pb" \
  --output_file="/path/to/deeplab_mobilenet_v2_opt_flatten_static.tflite" \
  --output_format=TFLITE \
  --input_shape=1,400,225,3 \
  --input_arrays="ImageTensor" \
  --inference_type=FLOAT \
  --inference_input_type=QUANTIZED_UINT8 \
  --std_dev_values=128 \
  --mean_values=128 \
  --change_concat_input_ranges=true \
  --output_arrays="SemanticPredictions" \
  --allow_custom_ops

完成

您现在可以运行tflite模型