TensorFlow: как делать прогнозы по SavedModel?

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

F1 : FLOAT32
F2 : FLOAT32
F3 : FLOAT32
L1 : FLOAT32

Итак, скажем, я хочу передать значения 20.9, 1.8, 0.9, чтобы получить один прогноз FLOAT32. Как мне это сделать? Мне удалось успешно загрузить модель, но я не уверен, как получить к ней доступ, чтобы сделать прогнозный вызов.

with tf.Session(graph=tf.Graph()) as sess:
    tf.saved_model.loader.load(
        sess,
        [tf.saved_model.tag_constants.SERVING],
        "/job/export/Servo/1503723455"
    )

    # How can I predict from here?
    # I want to do something like prediction = model.predict([20.9, 1.8, 0.9])

Этот вопрос не является дубликатом вопроса, размещенного здесь. Этот вопрос посвящен минимальному примеру выполнения вывода для SavedModel любого класса модели (не только tf.estimator) и синтаксису указания имен входных и выходных узлов.


person jshapy8    schedule 26.08.2017    source источник
comment
Смотрите мое последнее редактирование о том, почему это не дубликат.   -  person jshapy8    schedule 13.09.2017
comment
проверьте подробный ответ с tensorflow 1.7 здесь stackoverflow.com/a/52222383/5904928   -  person Aaditya Ura    schedule 07.09.2018


Ответы (4)


Предполагая, что вам нужны прогнозы в Python, SavedModelPredictor вероятно, самый простой способ загрузить SavedModel и получить прогнозы. Предположим, вы сохранили свою модель следующим образом:

# Build the graph
f1 = tf.placeholder(shape=[], dtype=tf.float32)
f2 = tf.placeholder(shape=[], dtype=tf.float32)
f3 = tf.placeholder(shape=[], dtype=tf.float32)
l1 = tf.placeholder(shape=[], dtype=tf.float32)
output = build_graph(f1, f2, f3, l1)

# Save the model
inputs = {'F1': f1, 'F2': f2, 'F3': f3, 'L1': l1}
outputs = {'output': output_tensor}
tf.contrib.simple_save(sess, export_dir, inputs, outputs)

(Входные данные могут быть любой формы и даже не обязательно должны быть заполнителями или корневыми узлами на графике).

Затем в программе Python, которая будет использовать SavedModel, мы можем получить такие прогнозы:

from tensorflow.contrib import predictor

predict_fn = predictor.from_saved_model(export_dir)
predictions = predict_fn(
    {"F1": 1.0, "F2": 2.0, "F3": 3.0, "L1": 4.0})
print(predictions)

Этот ответ показывает, как получать прогнозы в Java, C++ и Python (несмотря на то, что вопрос ориентирован на оценщиков, ответ на самом деле применим независимо от того, как создается SavedModel).

person rhaertel80    schedule 13.09.2017
comment
Очевидно, что simple_save не совместим с кодом построения графа, когда входные данные для модели считываются из входных файлов с использованием tf.data.Dataset и его итератора, потому что для simple_save требуются тензоры, а не пустые массивы. Кроме того, пространство имен изменено на tf.saved_model, а не на tf.contrib. Мой код может быть проблемой. Известный пример рабочего кода с использованием модели, обученной с использованием набора данных и сохраненной с помощью simple_save, отлично подходит для @mrry. - person Geoffrey Anderson; 07.09.2018
comment
Очевидно, еще одна несовместимость simple_save связана с кодом построения графиков, который вводит разреженные массивы numpy, а первая строка кода построения графиков — это tf.stack, потому что это разреженная матрица. Итак, куда вы поместите tf.stack вне кода построения графа? Известный пример рабочего кода с использованием модели, вызывающей tf.stack и сохраненной с помощью simple_save, был бы превосходным, если бы @mrry - person Geoffrey Anderson; 07.09.2018
comment
@GeoffreyAnderson Звучит достойно отдельного вопроса; не забудьте опубликовать фрагменты кода, который вы используете. - person rhaertel80; 09.09.2018
comment
Просто обратите внимание, что это может больше не работать в TensorFlow 2.0. По крайней мере, импорт мог измениться. - person Eric McLachlan; 15.12.2020

Для всех, кому нужен рабочий пример сохранения обученной постоянной модели и ее обслуживания без обслуживания тензорного потока, я задокументировал здесь https://github.com/tettusud/tensorflow-examples/tree/master/estimators

  1. Вы можете создать предиктор из tf.tensorflow.contrib.predictor.from_saved_model( exported_model_path)
  2. Подготовить ввод

    tf.train.Example( 
        features= tf.train.Features(
            feature={
                'x': tf.train.Feature(
                     float_list=tf.train.FloatList(value=[6.4, 3.2, 4.5, 1.5])
                )     
            }
        )    
    )
    

Здесь x — это имя ввода, которое было задано в input_receiver_function во время экспорта. например:

feature_spec = {'x': tf.FixedLenFeature([4],tf.float32)}

def serving_input_receiver_fn():
    serialized_tf_example = tf.placeholder(dtype=tf.string,
                                           shape=[None],
                                           name='input_tensors')
    receiver_tensors = {'inputs': serialized_tf_example}
    features = tf.parse_example(serialized_tf_example, feature_spec)
    return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)
person sudharsan tk    schedule 05.12.2017

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

with tf.Session(graph=tf.Graph()) as sess:
    tf.saved_model.loader.load(
        sess,
        [tf.saved_model.tag_constants.SERVING],
        "/job/export/Servo/1503723455"
    )

    prediction = sess.run(
        'prefix/predictions/Identity:0',
        feed_dict={
            'Placeholder:0': [20.9],
            'Placeholder_1:0': [1.8],
            'Placeholder_2:0': [0.9]
        }
    )

    print(prediction)

Здесь вам нужно знать имена того, какими будут входные данные вашего прогноза. Если вы не дали им неф в своем serving_fn, то по умолчанию они будут Placeholder_n, где n — n-й элемент.

Первый строковый аргумент sess.run — это имя цели предсказания. Это зависит от вашего варианта использования.

person jshapy8    schedule 27.08.2017
comment
Почему мы не можем передать несколько значений каждому заполнителю, что-то вроде пакета или входных данных? prediction = sess.run( 'prefix/predictions/Identity:0', feed_dict={ 'Placeholder:0': [20.9, 11.3], 'Placeholder_1:0': [1.8, 2.6], 'Placeholder_2:0': [0.9, 0.76] } ) - person Nitin; 13.11.2019

Конструктор tf.estimator.DNNClassifier имеет аргумент с именем warm_start_from. Вы можете дать ему имя папки SavedModel, и он восстановит ваш сеанс.

person udifuchs    schedule 07.09.2018
comment
Папка warm_start_from содержит контрольную точку или SavedModel? Они не то же самое. - person meelo; 29.11.2018