есть ли простой способ использовать функции из tf.данные.Набор данных.от генератора с пользовательской моделью fn (оценка) в tensorflow

Я использую api набора данных tensorflow для моих учебных данных, input_fn и генератора для tf.данные.Набор данных.API для from_generator

def generator():
    ......
    yield { "x" : features }, label


def input_fn():
    ds = tf.data.Dataset.from_generator(generator, ......)
    ......
    feature, label = ds.make_one_shot_iterator().get_next()
    return feature, label

затем я создал пользовательский model_fn для моей оценки с некоторым кодом, таким как:

def model_fn(features, labels, mode, params):
    print(features)
    ......
    layer = network.create_full_connect(input_tensor=features["x"], 
    (or layer = tf.layers.dense(features["x"], 200, ......)
    ......

при обучении :

estimator.train(input_fn=input_fn)

однако код не работает, так как параметр features для функции model_fn-это что - то:

Тензор ("IteratorGetNext: 0", dtype=float32, device= / device: CPU: 0)

код " особенности ["x"] " потерпит неудачу и скажет мне:

......"site-packages\tensorflow\python\ops\array_ops.py", строка 504, in _SliceHelper конец.добавить(s + 1) TypeError: должен быть str, а не int

если я изменю input_fn на:

input_fn = tf.estimator.inputs.numpy_input_fn(
  x={"x": np.array([[1,2,3,4,5,6]])},
  y=np.array([1]),

код продолжается, потому что функции теперь дикт.

Я искал код для оценки и нашел, что он использует некоторую функцию, такую как

features, labels = self._get_features_and_labels_from_input_fn(
      input_fn, model_fn_lib.ModeKeys.TRAIN)

для извлечения объектов и меток из input_fn, но я понятия не имею, почему он передает мне(model_fn) два разных типа данных объектов с помощью разных реализаций набора данных, если я хочу использовать свой режим генератора, то как использовать этот тип (IteratorGetNext) объектов ?

спасибо за любую помощь!

[обновлено]

я внес некоторые изменения в код,

def generator():
    ......
    yield features, label

def input_fn():
    ds = tf.data.Dataset.from_generator(generator, ......)
    ......
    feature, label = ds.make_one_shot_iterator().get_next()
    return {"x": feature}, label

однако, все еще не удалось в tf.слои.плотный, теперь он сказал

"вход 0 слоя dense_1 несовместим со слоем: его ранг не определен, но для слоя требуется определенный ранг."

хотя черт дикт :

'x': tf.Тензор 'IteratorGetNext:0' shape=неизвестный dtype=float64

в правильном случае, это что-то :

'x': tf.Тензор 'random_shuffle_queue_DequeueMany:1' shape=(128, 6) dtype=float64

я узнал подобное использование от

https://developers.googleblog.com/2017/09/introducing-tensorflow-datasets.html

def my_input_fn(file_path, perform_shuffle=False, repeat_count=1):
   def decode_csv(line):
      ......
      d = dict(zip(feature_names, features)), label
      return d

   dataset = (tf.data.TextLineDataset(file_path)

но нет официального примера для случая генератора, который возвращает итератор в пользовательский model_fn.

1 ответов


по словам примеры использования from_generator генератор возвращает значения положить в набор данных, а не дикт функций. Вместо этого вы строите dict в input_fn.

изменение кода следующим образом должно заставить его работать:

def generator():
    ......
    yield features, label

def input_fn():
    ds = tf.data.Dataset.from_generator(generator, ......)
    ......
    feature, label = ds.make_one_shot_iterator().get_next()
    return {"x": feature}, label

ответ на обновление:

ваш код терпит неудачу, потому что тензор, сгенерированный итератором Dataset.from_generator не имеет статического shape defined (так как генератор смог, в принципе, возвратить данные с различными формами). Предполагая, что ваши данные действительно всегда имеют одинаковую форму,можно назвать feature.set_shape(<the_shape_of_your_data>) до returning от input_fn (см. edit blow для правильного способа сделать это).

Edit:

как вы указали в комментарии tf.data.Dataset.from_generator() имеет третий параметр, который задает форму выходного тензора, поэтому вместо feature.set_shape() просто передайте форму как output_shapes на from_generator().