Создание набора данных тензорного потока, который выводит dict

У меня есть dict с «метаданными» для моего набора данных вида {'m1': array_1, 'm2': array_2, ...}.. Каждый из массивов имеет форму (N, ...), где N - количество выборок.

Вопрос: можно ли создать tf.data.Dataset, который выводит словарь {'meta_1': sub_array_1, 'meta_2': sub_array_2, ...} для каждой итерации набора данных iterator.get_next ()? Здесь sub_array_i должен содержать i-е метаданные для одного пакета, поэтому должен иметь форму (batch_sz, ...).

До сих пор я пробовал использовать tf.data.Dataset.from_generator (), вот так:

N = 100
# dictionary of arrays:
metadata = {'m1': np.zeros(shape=(N,2)), 'm2': np.ones(shape=(N,3,5))} 
num_samples = N

def meta_dict_gen():
    for i in range(num_samples):
        ls = {}
        for key, val in metadata.items():
            ls[key] = val[i]
        yield ls

dataset = tf.data.Dataset.from_generator(meta_dict_gen, output_types=(dict))

Проблема с этим, похоже, в output_types=(dict). Приведенный выше код вызывает у меня

TypeError: Ожидаемый тип данных для аргумента 'Tout', а не ‹class 'dict'>.


Я использую tenorflow 1.8 и python 3.6.


person dasWesen    schedule 02.07.2018    source источник
comment
Нет, это невозможно. Наборы данных - это последовательности элементов, каждый из которых может состоять из одного или нескольких тензоров (с учетом вложенных структур), имеющих фиксированный тип и форму (хотя форма может быть указана только частично). Единственная вариация, которую они допускают, - это то, хотите ли вы создавать плотные или разреженные тензоры. Имейте в виду, что графики TensorFlow должны быть независимыми от языка, поскольку они могут использоваться на разных языках, поэтому собственные типы, такие как словари, не могут напрямую поддерживаться. Однако вы можете добавлять свои метаданные в каждый элемент, если структура фиксирована.   -  person jdehesa    schedule 02.07.2018
comment
Итак, можно иметь выходной кортеж со всеми метаданными в виде отдельных тензоров внутри, но невозможно сохранить заголовки? Хорошо, тогда я найду обходной путь. Спасибо за разъяснения!   -  person dasWesen    schedule 02.07.2018
comment
На самом деле, насколько я помню, снова взглянув на руководство, вы можете назвать кортежи как выходные данные итератора (см. Структура набора данных), что не совсем то же самое, что dict, но вроде как близко. Однако он показывает вам пример для from_tensor_slices, я посмотрю, есть ли способ сделать то же самое с _2 _...   -  person jdehesa    schedule 02.07.2018
comment
Итак, поцарапайте это, вы можете делать то, что хотите (см. Ответ). Операции с графами по-прежнему работают на уровне тензора, но API набора данных действительно реализует эту функциональность (я думал, что поведение вложенности работает только для кортежей).   -  person jdehesa    schedule 02.07.2018
comment
Да, похоже, что до сих пор это работает, также в сочетании (заархивировано) с другими наборами данных. Даже если у одних тензоров есть «заголовки», у других нет. Большое спасибо!   -  person dasWesen    schedule 02.07.2018


Ответы (1)


Таким образом, на самом деле можно делать то, что вы намереваетесь, вам просто нужно указать содержимое dict:

import tensorflow as tf
import numpy as np

N = 100
# dictionary of arrays:
metadata = {'m1': np.zeros(shape=(N,2)), 'm2': np.ones(shape=(N,3,5))}
num_samples = N

def meta_dict_gen():
    for i in range(num_samples):
        ls = {}
        for key, val in metadata.items():
            ls[key] = val[i]
        yield ls

dataset = tf.data.Dataset.from_generator(
    meta_dict_gen,
    output_types={k: tf.float32 for k in metadata},
    output_shapes={'m1': (2,), 'm2': (3, 5)})
iter = dataset.make_one_shot_iterator()
next_elem = iter.get_next()
print(next_elem)

Выход:

{'m1': <tf.Tensor 'IteratorGetNext:0' shape=(2,) dtype=float32>,
 'm2': <tf.Tensor 'IteratorGetNext:1' shape=(3, 5) dtype=float32>}
person jdehesa    schedule 02.07.2018
comment
Мило спасибо! Я не знал об именованных выходах; это, кажется, отлично справляется со своей задачей. Спасибо - person dasWesen; 02.07.2018