Замените входной конвейер tensorflow dataset на заполнитель после обучения

Я работаю с новым API tf.data.Dataset и не могу понять, как выполнить логический вывод. В конечном итоге я хочу преобразовать свою модель в график TensorRT и запустить ее на TX2, и все примеры я нашел предполагают, что у вас есть tf.placeholder для ввода. Вот псевдокод того, как я тренируюсь. [...] предназначен для использования в качестве заполнителя, поскольку я фактически не запускал код. Давайте не будем обсуждать модель, так как она просто приведена для примера:

import tensorflow as tf

# Setup iterator
datain = tf.data.FixedLengthRecordDataset(datafiles, record_bytes1)
labels = tf.data.FixedLengthRecordDataset(labelfiles, record_bytes2)
dataset = tf.data.Dataset.zip((datain, labels))
dataset = dataset.prefetch(batch_size)
dataset = dataset.repeat(n_epoch)
iterator = dataset.make_initializable_iterator()

sess = tf.Session()
sess.run(iterator.initializer)
[batch_x, batch_y] = iterator.get_next()

# Define model function (let's not debate model except as relevant to question)
def model_fn(xin):
    x0 = tf.transpose(tf.reshape(xin, [...], name='input'))
    w = tf.Variable(tf.truncated_normal([...], stddev=0.1))
    x1 = tf.nn.conv2d(x0, w, strides=[...], padding='VALID')
    b = tf.Variable(tf.constant(0.0, shape=[...]))
    x2 = tf.nn.bias_add(x1, b)
    x3 = tf.nn.relu(x2, name='output')
    return x3

# Setup training environment
model = model_fn(batch_x)
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model, labels=batch_y))
optimizer = tf.train.AdamOptimizer(learning_rate=1e-3).minimize(loss)

# Train Model
while True:
    try:
        sess.run(optimizer)
    except tf.errors.OutOfRangeError:
        break

# Save model
saver = tf.train.Saver(name='saver')
saver.save(sess, 'temp/path')

Мой вопрос в том, как мне получить это в TensorRT, не имея на входе tf.placeholder? Во всех примерах, которые я могу найти, в качестве входных данных используется tf.placeholder. Этот пример предполагает, что я могу заменить итератор на заполнитель, используя класс SavedModel, но я не могу найти никакой документации о том, как это сделать.

Спасибо!

Обновлено: Вот мое решение благодаря помощи ниже

from tensorflow.python.tools import optimize_for_inference_lib
import uff

# You can feed data to the IteratorGetNext node using feed_dict
input_node_name = 'iterator_scope_name/IteratorGetNext'
output_node_name = 'model_scope_name/output'

# Run inference on the trained model:
graph = tf.get_default_graph()
batch_x = graph.get_tensor_by_name(input_node_name + ':0')
networkout = graph.get_tensor_by_name(output_node_name + ':0')
testdata, testlabel = custom_data_reader_fn(data_folder)
# This will evaluate the model
label = sess.run(networkout, feed_dict={batch_x: testdata})

# Freeze model and create a UFF file:
graph_def = graph.as_graph_def() # Convert the graph to a serialized pb
frozen_graph_def = tf.graph_util.convert_variables_to_constants(sess,
    graph_def, [output_node_name])
opt_graph_def = optimize_for_inference_lib.optimize_for_inference(
    frozen_graph_def, [input_node_name], [output_node_name],
    tf.float32.as_datatype_enum)
uff.from_tensorflow(opt_graph_def, [output_node_name], quiet=False,
    output_filename='opt_model.uff')

который запишет файл UFF, который может использовать TensorRT. Самые большие проблемы, с которыми я столкнулся, были:

  1. Я не понимал, что операция optimize_for_inference_lib.optimize_for_inference заменила iterator на tf.placeholder.
  2. Я не знал, на какой узел передавать данные для оценки: вы можете передавать данные на узел IteratorGetNext.

Вы ограничены в использовании этой относительно низкоуровневой схемы обучения или считаете целесообразным решение, использующее tf.estimator для обучения и экспорта?

GPhilo 13.09.2018 20:43

если tf.estimator будет работать с TensorRT, я с радостью им воспользуюсь. Хотя я не уверен, что так будет.

John 13.09.2018 21:43

Насколько я понимаю, TensorRT работает с обученными графами. Оценщик поможет вам с обучением и экспортом графика, затем вы замораживаете его и импортируете в TensorRT. Я смогу правильно ответить только завтра, я постараюсь объяснить, как настроить различные фрагменты кода, необходимые для обучения и экспорта.

GPhilo 13.09.2018 21:50

Привет, GPhilo. У меня есть обученный граф, но он требует итератора. Я считаю, что если бы я мог просто понять, как наполнить график новыми данными или заменить итератор на tf.placeholder после обучения, я был бы настроен. Мне интересно посмотреть, как настроить его с помощью оценщика.

John 13.09.2018 22:28

Хорошо, если все, что вам нужно, это взгляните на это: github.com/tensorflow/tensorflow/blob/master/tensorflow/pyth‌ в /… вам нужно будет передать файл graph.txt, который должен быть в вашей папке контрольной точки, обязательно прочтите комментарии вверху об использовании не- замороженный график

GPhilo 13.09.2018 22:47

Взгляните на этот вопрос в обратном направлении (заполнитель -> итератор). Ответ в основном тот же.

P-Gn 14.09.2018 09:25
6
6
1 828
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

python freeze_graph.py \
--input_graph=temp/path/graph.pbtxt \
--input_checkpoint=temp/path/your_model_name.ckpt \
--output_graph=frozen_model.pb \
--output_node_names=name_of_the_output_tensor_you_want_to_use

Это создаст новый двоичный файл с именем frozen_model.pb, в котором операции Variable заменены операциями Const со значениями, загруженными из файла контрольной точки.

Затем вам нужно сгенерировать граф вывода с помощью:

python optimize_for_inference.py \
--input=frozen_model.pb \
--output=inference.pb \
--frozen_graph=True \
--input_names=IteratorGetNext
--output_names=name_of_the_output_tensor_you_want_to_use

Это заменит узел IteratorGetNext на заполнитель с плавающей точкой. Вы можете выбрать другой узел, и в этом случае просто измените имя. Вы также можете изменить тип сгенерированного заполнителя с помощью опции --placeholder_type_enum. В этом случае вам необходимо предоставить целочисленное значение, соответствующее типу данных, который вы хотите получить из DataType перечисление.

ЗАМЕТКА: Я сказал «теоретически», потому что на самом деле, проверяя сгенерированный начальный граф на основе теста, я обнаружил, что там все еще есть некоторые странные операции, которые на самом деле не нужны для вывода. Возможно, вам придется дополнительно обработать свой график с помощью nvidia Граф хирург или TF инструмент преобразования графа

Спасибо за ответ. Моя самая большая проблема заключалась в том, что я не знал: 1) на какой узел TensorFlow передавать данные (здесь это IteratorGetNext) и 2) не осознавая, что шаг optimize_for_inference фактически заменил IteratorGetNext заполнителем.

John 14.09.2018 15:08

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

GPhilo 14.09.2018 15:21

Согласовано. Я отредактировал свой вопрос, указав код для вывода и создания файла UFF для TensorRT. Спасибо за вашу помощь!

John 14.09.2018 17:05

@GPhilo Я попробовал optimize_for_inference, но он не заменил узел IteratorGetNext на заполнитель. Мне не хватает флага? Я имею в виду, что есть новый заполнитель, но похоже, что узлы загрузчика набора данных все еще присутствуют на графике, и когда я пытаюсь преобразовать модель с помощью внешнего интерфейса компилятора, он выдает исключение в ops IteratorGetNext и IteratorV2

lamo_738 23.07.2019 03:49

Какую версию TF вы используете? optimize_for_inference становится немного устаревшим, и, возможно, он может не работать с введенными новыми модификациями (я видел проблему GitHub, где вместо этого они рекомендуют использовать transform_graph)

GPhilo 23.07.2019 08:50

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