Как преобразовать.pb в формат TFLite?

Я скачал retrained_graph.pb а также retrained_labels.txt файл модели, которую я обучал в когнитивной службе Azure. Теперь я хочу создать приложение для Android с использованием этой модели, и для этого мне нужно преобразовать его в формат TFLite. Я использовал Toco, и я получаю следующую ошибку:

ValueError: Invalid tensors 'input' were found.

Я в основном следую этому руководству и у меня возникли проблемы на шаге 4, и я скопировал код терминала: https://heartbeat.fritz.ai/neural-networks-on-mobile-devices-with-tensorflow-lite-a-tutorial-85b41f53230c

2 ответа

Я делаю дикое предположение здесь, может быть, вы вошли input_arrays=input, Что не может быть правдой. Используйте этот скрипт, чтобы узнать имя ваших входных и выходных массивов вашего замороженного вывода

import tensorflow as tf
gf = tf.GraphDef()   
m_file = open('frozen_inference_graph.pb','rb')
gf.ParseFromString(m_file.read())

with open('somefile.txt', 'a') as the_file:
    for n in gf.node:
        the_file.write(n.name+'\n')

file = open('somefile.txt','r')
data = file.readlines()
print "output name = "
print data[len(data)-1]

print "Input name = "
file.seek ( 0 )
print file.readline()

В моем случае это:

output name: SemanticPredictions
input name: ImageTensor

Вы можете использовать утилиту tflite_convert, которая является частью пакета tenorflow 1.10 (или выше).

Простое использование для вывода с плавающей точкой примерно так:

tflite_convert \
    --output_file=/tmp/retrained_graph.tflite \
    --graph_def_file=/tmp/retrained_graph.pb \
    --input_arrays=input \
    --output_arrays=output

Где вход и выход - это входные и выходные тензоры вашего графика тензорного потока

import tensorflow as tf
gf = tf.GraphDef()
m_file = open('frozen_inference_graph.pb','rb')
for n in gf.node:
    print( n.name )

первый - input_arrays; последние имена - output_arrays (может быть больше одного зависит от количества выходных данных модели)

мой вывод

  • image_tensor <--- input_array
  • В ролях
  • Препроцессор / карта /Shape Препроцессор / карта /strided_slice/stack
  • Препроцессор / карта /strided_slice/stack_1
  • ,
  • ,
  • ,
  • Постпроцессор /BatchMultiClassNonMaxSuppression/ карта /
  • TensorArrayStack_5 / TensorArrayGatherV3
  • Постпроцессор /Cast_3
  • Постпроцессор /Squeeze
  • добавить / г
  • Добавлять
  • Detection_boxes <--- output_array
  • обнаружение_счета <--- output_array
  • detection_multiclass_scores
  • определение_классов <--- output_array
  • num_detections <--- output_array
  • raw_detection_boxes
  • raw_detection_scores

Если вы используете TF2, то для публикации квантованного файла.pb сработает следующее.

import tensorflow as tf
converter = tf.compat.v1.lite.TFLiteConverter.from_frozen_graph(
    graph_def_file = 'path/to/frozen_inference__graph.pb', 
    input_arrays = ['Input_Tensor_Name'],
    output_arrays = ['Output_Tensor_Name'] 
)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_model = converter.convert()
with tf.io.gfile.GFile('model.tflite', 'wb') as f:
  f.write(tflite_model)

если вы хотите полное квантование int8, тогда

import tensorflow as tf
converter = tf.compat.v1.lite.TFLiteConverter.from_frozen_graph(
    graph_def_file = 'path/to/frozen_inference__graph.pb', 
    input_arrays = ['Input_Tensor_Name'],
    output_arrays = ['Output_Tensor_Name'] 
)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
image_shape=(input_width,input_height,no_of_channels) #change it according to your need
def representative_dataset_gen():
    for i in range(10):
        # creating fake images
        image = tf.random.normal([1] + list(image_shape))
        yield [image]

converter.representative_dataset = tf.lite.RepresentativeDataset(representative_dataset_gen)
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] # For EdgeTPU, no float ops allowed
converter.inference_input_type = tf.uint8
converter.inference_output_type = tf.uint8

tflite_model = converter.convert()
with tf.io.gfile.GFile('model.tflite', 'wb') as f:
  f.write(tflite_model)

Большинство ответов здесь оказываются неработающими из-за проблем с версией. Это сработало для меня:

Примечание: сначала найдите имя входного и выходного слоев с помощью Netron, как я уже упоминал здесь. В моем случае ониinput а также output.

!pip install tensorflow-gpu==1.15.0

# Convert
!toco --graph_def_file /content/yolo-v2-tiny-coco.pb \
    --output_file yolo-v2-tiny-coco.tflite \
    --output_format TFLITE \
    --inference_type FLOAT \
    --inference_input_type FLOAT \
    --input_arrays input \
    --output_arrays output

Кроме того, согласно удивительной работе zldrobit, вы также можете получить улучшенную квантованную версию этой модели TFLite как:


# Now let's quantize it
!toco --graph_def_file /content/yolo-v2-tiny-coco.pb \
    --output_file quantized-yolo-v2-tiny-coco.tflite \
    --output_format TFLITE \
    --inference_type FLOAT \
    --inference_input_type FLOAT \
    --input_arrays input \
    --output_arrays output \
    --post_training_quantize

Чтобы запустить конвертер tflite на вашем локальном компьютере, вам понадобятся bazel и toco.

И если вы прочитали некоторые проблемы в GitHub, в некоторых версиях Tensrflow tflite вызывает много проблем. Чтобы решить эту проблему, некоторые рекомендуют использовать tf-nightly!

Чтобы избежать всего этого, просто используйте Google Colab для преобразования вашего.pb в.lite или.tflite.

Поскольку в Colab появилась возможность загрузки файлов в текущее ядро, я думаю, что это самый простой способ, не беспокоясь о других пакетах и ​​их зависимостях.

Вот блокнот Colab:

https://drive.google.com/file/d/1lDcttsmZC0Y6dXxwe0EVZUsyVoR8HuR-/view?usp=sharing

Вы можете загрузить файл.pb в текущий сеанс двумя способами:

i) (Простой способ) После запуска первой ячейки в указанном выше ноутбуке диск будет установлен. Итак, в левой части экрана перейдите в столбец файлов и щелкните правой кнопкой мыши папку, в которую хотите загрузить файл.pb, и выберите "Загрузить". Затем используйте команды "ls" и "cd", чтобы войти в папку и запустить ячейку конвертера tflite.

ii) Запустите ячейку с помощью команды files.upload(), нажмите "Обзор" и выберите файл.pb на локальном компьютере.

После загрузки файла укажите его путь к переменной localpb, а также имя модели.lite. Затем просто запустите ячейку с командой TFLiteConverter.

И вуаля. На вашем диске должна появиться tflite-модель. Просто щелкните его правой кнопкой мыши и загрузите на свой локальный компьютер, чтобы выполнить выводы.

Ошибка указывает на то, что вы не ввели правильный

--input_arrays

Из Руководства разработчика TF Lite я цитирую:

" Задать аргументы input_array и output_array непросто. Самый простой способ найти эти значения - изучить график с помощью TensorBoard ".

Использование Tensorboard тоже не сложно, просто запустив эту команду

tensorboard --logdir=path/to/log-directory

Посмотреть TensorBoard на

localhost:6006   

Подставляя Mul за input исправил это для меня.

IMAGE_SIZE=299
tflite_convert \
  --graph_def_file=tf_files/retrained_graph.pb \
  --output_file=tf_files/optimized_graph.lite \
  --input_format=TENSORFLOW_GRAPHDEF \
  --output_format=TFLITE \
  --input_shape=1,${IMAGE_SIZE},${IMAGE_SIZE},3 \
  --input_array=Mul \
  --output_array=final_result \
  --inference_type=FLOAT \
  --input_data_type=FLOAT

Без базеля вы можете попробовать следующий код

pip uninstall tensorflow
pip install tf-nightly
pip show protobuf

Если protobuf версии 3.6.1, перейдите к установке предварительной версии 3.7.0.

pip uninstall protobuf
pip install protobuf==3.7.0rc2 

Я все еще не мог заставить версию командной строки работать. Он продолжал возвращать ошибку: "tflite_convert: error: –input_arrays и –output_arrays требуются с –graph_def_file", хотя оба параметра были предоставлены. Это сработало в Python, однако.

import tensorflow as tf

graph_def_file = "model.pb"
input_arrays = ["model_inputs"]
output_arrays = ["model_outputs"]

converter = tf.lite.TFLiteConverter.from_frozen_graph(
        graph_def_file, input_arrays, output_arrays)
tflite_model = converter.convert()
open("converted_model.tflite", "wb").write(tflite_model)

Я следую за своим предыдущим ответом, вы можете использовать следующий скрипт для преобразования вашей обученной модели на ssd mobilenet в tflte, используя

python object_detection/export_tflite_ssd_graph \
    --pipeline_config_path ssd_0.75_export/pipeline.config \
    --trained_checkpoint_prefix ssd_0.75_export/model.ckpt \
    --output_directory ssd_to_tflite_output

Для этого вам сначала нужно будет присутствовать в папке исследований API обнаружения объектов тензорного потока и изменить путь / имя файла в соответствии со своими именами. Если эта работа не завершена, попробуйте запустить этот сценарий из папки исследования и повторите попытку:

protoc object_detection/protos/*.proto --python_out=.
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim

Импортировать тензор потока как тф

!tflite_convert \
--output_file "random.tflite" \
--graph_def_file "pb file path" \
--input_arrays "input tensor name" \
--output_arrays "output tensor name"    

Скорее всего, потому, что в процессе переподготовки тензоры ввода и вывода были переименованы. Если это переобученный график inceptionv3, попробуйте использовать Mul в качестве имени входного тензора и final_result в качестве имени выходного тензора.

bazel run --config=opt //tensorflow/contrib/lite/toco:toco -- \
    ... other options ...
    --input_shape=1,299,299,3 \
    --input_array=Mul \
    --output_array=final_result

Подобная настройка, если вы используете tflife_convert, как подсказывает Александр.

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