Как эффективно подать данные в обученную модель tf.estimator и получить прогноз?Проблема в предикате - PullRequest
0 голосов
/ 24 апреля 2019

Среда: Win10, Python 3.6.8, Tensorflow-GPU 1.13.1

У меня есть модель, основанная на tf.estimator.DNNRegressor, которую я обучал локально. Теперь у меня возникла проблема с получением функции предиката для работы с данными в реальном времени. У меня это работает, читая CSV-файл с одной записью, но я хотел бы передать массив данных или какую-то другую форму данных из памяти и сделать прогноз модели.

Вот фрагмент кода:

tf.enable_eager_execution()

model = tf.estimator.DNNRegressor(
    hidden_units=[128,128],
    feature_columns=feature_columns,
    model_dir=model_dir)

def predict_input_fn():
test_array = np.array([-0.057,-0.0569]) # shortened, normally 56 floats
    defaults = [tf.float32] * 56
    filenames = ['./prediction.csv']
    dataset_old = tf.data.experimental.CsvDataset( # this works
        filenames=filenames,
        record_defaults=defaults)
    dataset = tf.data.Dataset.from_tensor_slices(test_array) # this doesn't :(
    dataset = dataset.batch(1)
    features = tf.data.experimental.get_single_element(dataset)
    return dict(zip(feature_names, features)), None

predictor = model.predict(input_fn=predict_input_fn)
print(next(predictor))

Я получаю следующую ошибку, хотя активное выполнение включено:

TypeError: Тензорные объекты являются итеративными, только если включено активное выполнение. Чтобы перебрать этот тензор, используйте tf.map_fn.

Формат данных, который я передаю для обучения, - это 56 переменных float32 в качестве объектов и 1 переменная float32 в качестве метки. Как уже упоминалось, он прекрасно работает при использовании функции tf.data.experimental.CsvDataset (), но я не могу понять, как использовать базовый массив.

Я пытался поместить массив в массив контейнеров, используя стандартную функцию make_one_shot_iterator () в наборе данных, используя .constant (), чтобы попытаться построить тензор перед передачей его в tenor_slices. Изучил документы и все примеры, которые я могу найти, но все еще не могу заставить их работать.

Немного борясь, любая помощь будет принята с благодарностью.

Полный код ниже:

import tensorflow as tf
# import tensorflowjs as tfjs
import json
import numpy as np

tf.enable_eager_execution()

model_dir = './dnn3/'

feature_columns = []
feature_names = []
feature_spec = {}

for i in range(56):
    feature_columns.append(tf.feature_column.numeric_column(key="jkey"+str(i)))
    feature_names.append("jkey"+str(i))
    feature_spec["jkey"+str(i)] = tf.FixedLenFeature([1],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)

def train_input_fn():
    defaults = [tf.float32] * 57
    filenames = ['./training.csv'] # can add to this array
    dataset = tf.data.experimental.CsvDataset(
        filenames=filenames,
        record_defaults=defaults)
    dataset = dataset.shuffle(1000000)
    dataset = dataset.repeat(1000) # epochs
    dataset = dataset.batch(128)
    iter = dataset.make_one_shot_iterator()
    next = iter.get_next()
    features = next[:-1]
    label = next[-1]
    return dict(zip(feature_names, features)), label

def eval_input_fn():
    defaults = [tf.float32] * 57
    filenames = ['./evaluation.csv']
    dataset = tf.data.experimental.CsvDataset(
        filenames=filenames,
        record_defaults=defaults)
    dataset = dataset.shuffle(10000)
    dataset = dataset.repeat(100)
    dataset = dataset.batch(100)
    iter = dataset.make_one_shot_iterator()
    next = iter.get_next()
    features = next[:-1]
    label = next[-1]
    return dict(zip(feature_names, features)), label

def predict_input_fn():
    test_array = [[-0.057,-0.0569,-0.0569,-0.0759,-0.0568,-0.0379,-0.0379,-0.0567,-0.0946,0.0378,0.0566,0.0755,0,0,0,0,-0.0189,0,0,0,0,0.0379,0.0378,0.0568,0,0.0378,0,0.0758,0.0379,0.0379,0.057,0.0758,0.0379,0.0381,-0.152,0.2089,-0.0952,0.0568,-0.2485,.4667,-0.0803,-0.0775,-0.0832,-0.054,-0.0989,0.0063,0.0037,-0.0342,0.0007,0.0281,0.0187,-0.0065,0.0423,0.078,-0.0285,-0.0093],[-0.057,-0.0569,-0.0569,-0.0759,-0.0568,-0.0379,-0.0379,-0.0567,-0.0946,0.0378,0.0566,0.0755,0,0,0,0,-0.0189,0,0,0,0,0.0379,0.0378,0.0568,0,0.0378,0,0.0758,0.0379,0.0379,0.057,0.0758,0.0379,0.0381,-0.152,0.2089,-0.0952,0.0568,-0.2485,.4667,-0.0803,-0.0775,-0.0832,-0.054,-0.0989,0.0063,0.0037,-0.0342,0.0007,0.0281,0.0187,-0.0065,0.0423,0.078,-0.0285,-0.0093]]
    defaults = [tf.float32] * 56
    filenames = ['./prediction.csv']
    dataset2 = tf.data.experimental.CsvDataset(
        filenames=filenames,
        record_defaults=defaults)
    test_tensor = tf.constant(test_array)
    #test_dict = dict(zip(feature_names, test_array))
    dataset = tf.data.Dataset.from_tensor_slices(test_tensor)
    dataset = dataset.batch(1)
    features = tf.data.experimental.get_single_element(dataset)
    return dict(zip(feature_names, features)), None

model = tf.estimator.DNNRegressor(
    hidden_units=[128,128],
    feature_columns=feature_columns,
    model_dir=model_dir)

def train():
    for i in range(5):
        model.train(input_fn=train_input_fn, steps=10000)
        eval_result = model.evaluate(input_fn=eval_input_fn)
        print(eval_result)

def train_eval():
    train_spec = tf.estimator.TrainSpec(train_input_fn,max_steps=20000)
    eval_spec = tf.estimator.EvalSpec(eval_input_fn)
    tf.estimator.train_and_evaluate(model,train_spec,eval_spec)

def save():
    save_dir = model.export_savedmodel(export_dir_base=model_dir+'saved', serving_input_receiver_fn=serving_input_receiver_fn)
    print('Saved to ',save_dir)

def predict():
    predictor = model.predict(input_fn=predict_input_fn)
    print(next(predictor))

predict()
# tfjs.converters.save_keras_model(model, './tfjs/')

И полный ответ об ошибке:

WARNING:tensorflow:From C:\Users\jimba\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow\python\framework\op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.
Instructions for updating:
Colocations handled automatically by placer.
Traceback (most recent call last):
  File "train.py", line 93, in <module>
    predict()
  File "train.py", line 91, in predict
    print(next(predictor))
  File "C:\Users\jimba\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow_estimator\python\estimator\estimator.py", line 609, in predict
    input_fn, model_fn_lib.ModeKeys.PREDICT)
  File "C:\Users\jimba\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow_estimator\python\estimator\estimator.py", line 967, in _get_features_from_input_fn
    result = self._call_input_fn(input_fn, mode)
  File "C:\Users\jimba\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow_estimator\python\estimator\estimator.py", line 1079, in _call_input_fn
    return input_fn(**kwargs)
  File "train.py", line 67, in predict_input_fn
    return dict(zip(feature_names, features)), None
  File "C:\Users\jimba\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow\python\framework\ops.py", line 442, in __iter__
    "Tensor objects are only iterable when eager execution is "
TypeError: Tensor objects are only iterable when eager execution is enabled. To iterate over this tensor use tf.map_fn
...