Невозможно протестировать и развернуть модель сегментирования deeplabv3-mobilenetv2 tenorflow-lite для вывода

Мы пытаемся запустить модель семантической сегментации на Android с использованием deeplabv3 и mobilenetv2.Мы следовали официальной процедуре преобразования тензорного потока в lite, используя TOCO и tflite_convert с помощью bazel. Исходный замороженный график был получен из официального 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 --inference_type=FLOAT --mean_values ​​=128 --std_dev_values ​​=127 --allow_custom_ops --post_training_quantize

Размер файла tflite составлял около 2,25 Мб. Но когда мы попытались протестировать модель с использованием официального инструмента для тестирования производительности, произошел сбой со следующим сообщением об ошибке:-

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 interpretr)

Итак, как мы можем правильно преобразовать модель сегментации в формат tflite, который можно использовать для вывода на устройстве Android?

ОБНОВИТЬ:-

Используя тензор потока 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.

Кроме того, при использовании более новой версии той же модели (файл 3 МБ.pb) с глубиной_множителя =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' в качестве вывода. Кажется, это проблема со значениями множителя глубины.(Даже мы пытались дать параметр deep_multiplier в качестве аргумента на момент конвертации).

1 ответ

Я тоже столкнулся с этой проблемой. Похоже, что при преобразовании есть 2 проблемы:

  • Входной тензор имеет динамическую форму, то есть [?,?,?,3]
  • Часть узла pad_to_bounding_box не преобразуется автоматически в статическую форму

Для решения ниже это проверено на:

  • Tensorflow 1.15
  • Ubuntu 16.0.4

Решение

Я предполагаю, что вы уже создали файл.pb с помощью файла export_model.py в папке deeplab и назвали этот файл 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 и загрузили ветку tensorflow r1.15 с github. Затем создайте инструмент 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

У меня такая же проблема. с https://github.com/tantara/JejuNet Я вижу, что он успешно преобразовал модель в tflite. Я пишу ему в помощь, но, к сожалению, ответа пока нет.

Другие вопросы по тегам