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

Мы пытаемся запустить модель семантической сегментации на android с помощью deeplabv3 и mobilenetv2. Мы следовали официальной процедуре преобразования tensorflow 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 --input_arrays = ImageTensor --pesput_IZE_Type_input_arrays = 1,28input_arrays - --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_20/ a> Версия Tensorflow: 1.11 Версия Bazel: 0.17.2 ОС: Ubuntu 18.04

Также приложение Android не смогло правильно загрузить модель (интерпретатор tflite)

Итак, как мы можем правильно преобразовать модель сегментации в формат 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.

Кроме того, при использовании более новой версии той же модели (файл .pb 3 МБ) с depth_multiplier = 0,5 из tensorflow deeplab модель зоопарка, мы получили другую ошибку: -

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 в качестве аргумента. на момент конвертации).


person anilsathyan7    schedule 09.11.2018    source источник


Ответы (2)


Я тоже столкнулся с этой проблемой. Похоже, что при преобразовании есть 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

person Wout_bb    schedule 29.11.2019
comment
Если бы была возможность проголосовать много раз, я бы это сделал. Эти ответы сэкономили мне много времени! - person guneykayim; 16.11.2020

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

person Alpha    schedule 23.11.2018
comment
Собственно, мы тоже пробовали то же самое и даже обсуждали с тем же человеком. К сожалению, мы не смогли решить проблему. Но похоже, что проблема кроется в начальных слоях замороженного графа, где выполняются некоторые операции p-обработки. связанных с размером или регулировкой размера (ввод [1,?,?, 3], для принятия произвольного размера). Некоторые из них могут не поддерживаться tenorflow lite (который ожидает входов фиксированного размера). Может быть, если мы удаляем или пропускаем их, это может сработать. В противном случае нам, возможно, придется переобучить сеть после ее изменения. - person anilsathyan7; 24.11.2018
comment
Скинул JejuNet tflite, он сильно отличается от того, что мы преобразовали из официальной модели. входной узел - MobilenetV2 / MobilenetV2 / input и тип uint8 [1,256,256,3]. всего ОП только 71. а у нас 156 - person Alpha; 26.11.2018
comment
Теперь проблема решена? Если да, не могли бы вы рассказать, как решить. В моем случае я мог сгенерировать файл .tflite. но, когда я помещаю его в Jejunet, я получаю ошибку вроде java.lang.IllegalArgumentException: ByteBuffer не является допустимой моделью плоского буфера. По возможности поделитесь параметрами для преобразования .pb в .tflite. Если вы не используете JejuNet, подскажите, пожалуйста, что еще я могу использовать? - person Rajesh_Saladi; 19.04.2019