Мы пытаемся запустить модель семантической сегментации на 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=path/to/deeplab/deeplabv3_mnv2_pascal_trainval/frozen_inference_graph.pb --input_arrays=ImageTensor --output_arrays=SemanticPredictions --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 Мб, но когда мы попытались протестировать модель с помощью официального инструмента для тестирования производительности, у нас возник следующий отчет об ошибке:
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)
Итак, как мы можем правильно преобразовать модель сегментации в формат 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 в качестве аргумента. на момент конвертации).
У меня такая же проблема. от https://github.com/tantara/JejuNet я вижу, что он успешно конвертировал модель в tflite. Я пишу ему в личку с просьбой о помощи, но, к сожалению, сейчас ответа нет.
Скинул JejuNet tflite, он сильно отличается от того, что мы преобразовали из официальной модели. входной узел - MobilenetV2 / MobilenetV2 / input и тип uint8 [1,256,256,3]. всего ОП только 71. а у нас 156
Теперь проблема решена? Если да, не могли бы вы рассказать, как решить. В моем случае я мог сгенерировать файл .tflite. но, когда я помещаю его в Jejunet, я получаю ошибку типа «java.lang.IllegalArgumentException: ByteBuffer не является допустимой моделью плоского буфера». По возможности поделитесь параметрами для преобразования .pb в .tflite. Если вы не используете JejuNet, подскажите, пожалуйста, что еще я могу использовать?
Я тоже столкнулся с этой проблемой. Похоже, что при преобразовании есть 2 проблемы:
Для решения ниже это проверено на:
Я предполагаю, что вы уже создали файл .pb с помощью файла export_model.py в папке deeplab и назвали этот файл deeplab_mobilenet_v2.pb. С этого момента:
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)
Убедитесь, что вы установили 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'
Запустите файл 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")
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
Если бы была возможность проголосовать много раз, я бы это сделал. Эти ответы сэкономили мне много времени!
Собственно, мы тоже пробовали то же самое и даже обсуждали с одним и тем же человеком. К сожалению, мы не смогли решить проблему. Но похоже, что проблема кроется в начальных слоях замороженного графа, где выполняются некоторые операции p-обработки. связанных с размером или регулировкой размера (ввод [1,?,?, 3], для принятия произвольного размера). Некоторые из них могут не поддерживаться tenorflow lite (который ожидает входов фиксированного размера). Может быть, если мы удаляем или пропускаем их, это может сработать. В противном случае нам, возможно, придется переобучить сеть после ее изменения.