Как преобразовать.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, как подсказывает Александр.