Подключите пользовательский входной конвейер к модели tf - PullRequest
0 голосов
/ 15 мая 2018

В настоящее время я пытаюсь заставить простую модель тензорного потока обучаться по данным, предоставленным пользовательским конвейером ввода. Это должно работать максимально эффективно. Хотя я прочитал много уроков, я не могу заставить его работать.

ДАННЫЕ

Мои тренировочные данные разделены на несколько CSV-файлов. Файл «a.csv» содержит 20 сэмплов, а «b.csv» содержит 30 сэмплов соответственно. Они имеют одинаковую структуру с одинаковым заголовком:

feature1; feature2; feature3; feature4
0.1; 0.2; 0.3; 0.4
...

(без меток, как для автоэнкодера.)

КОД

Я написал входной конвейер и хотел бы передать данные из него в модель. Мой код выглядит так:

import tensorflow as tf

def input_pipeline(filenames, batch_size):
    dataset = tf.data.Dataset.from_tensor_slices(filenames)

    dataset = dataset.flat_map(
        lambda filename: (
                tf.data.TextLineDataset(filename)
                 .skip(1)
                 .shuffle(10)
                 .map(lambda csv_row: tf.decode_csv(
                         csv_row, 
                         record_defaults=[[-1.0]]*4,
                         field_delim=';'))
                 .batch(batch_size)     
        )
    )

    return dataset.make_initializable_iterator()


iterator = input_pipeline(['/home/sku/data/a.csv', 
                           '/home/sku/data/b.csv'], 
                           batch_size=5)

next_element = iterator.get_next()


# Build the autoencoder
x = tf.placeholder(tf.float32, shape=[None, 4], name='in')

z = tf.contrib.layers.fully_connected(x, 2, activation_fn=tf.nn.relu)

x_hat = tf.contrib.layers.fully_connected(z, 4)

# loss function with epsilon for numeric stability
epsilon = 1e-10
loss = -tf.reduce_sum(
    x * tf.log(epsilon + x_hat) + (1 - x) * tf.log(epsilon + 1 - x_hat))

train_op = tf.train.AdamOptimizer(learning_rate=1e-3).minimize(loss)

with tf.Session() as sess:
    sess.run(iterator.initializer)
    sess.run(tf.global_variables_initializer())

for i in range(50):
    batch = sess.run(next_element)
    sess.run(train_op, feed_dict={x: batch, x_hat: batch})

ПРОБЛЕМА

При попытке передать данные в модель выдается ошибка:

ValueError: Cannot feed value of shape (4, 5) for Tensor 'in:0', which has shape '(?, 4)'

При распечатке форм пакетных данных, я получаю это, например:

(array([ 4.1,  5.9,  5.5,  6.7, 10. ], dtype=float32), array([0.4, 7.7, 0. , 3.4, 8.7], dtype=float32), array([3.5, 4.9, 8.3, 7.2, 6.4], dtype=float32), array([-1. , -1. ,  9.6, -1. , -1. ], dtype=float32))

Это имеет смысл, но где и как мне это изменить? Кроме того, эта дополнительная информация dtype появляется только при дозировании.

Я также считал, что неправильно делал кормление. Мне нужен input_fn или что-то в этом роде? Я помню, что кормление диктов способ замедлить. Если бы кто-нибудь мог дать мне эффективный способ подготовки и подачи данных, я был бы очень благодарен.

С уважением,

1 Ответ

0 голосов
/ 18 мая 2018

Я нашел решение, которое требует второй функции отображения. Вы должны добавить следующую строку в функцию ввода:

def input_pipeline(filenames, batch_size):
    dataset = tf.data.Dataset.from_tensor_slices(filenames)

    dataset = dataset.flat_map(
        lambda filename: (
                tf.data.TextLineDataset(filename)
                 .skip(1)
                 .shuffle(10)
                 .map(lambda csv_row: tf.decode_csv(
                         csv_row, 
                         record_defaults=[[-1.0]]*4,
                         field_delim=';'))
                 .map(lambda *inputs: tf.stack(inputs))  # <-- mapping required
                 .batch(batch_size)     
        )
    )

    return dataset.make_initializable_iterator()

Похоже, это преобразует вывод в виде массива в матрицу, которую можно подавать в сеть.

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

...