Использование наборов данных для использования массивов Numpy

Я пытаюсь использовать массивы Numpy в графе, вводя данные с помощью набора данных.

Я прочитал это, но не могу понять, как я должен передавать заполнитель массивы в наборе данных.

Если мы возьмем простой пример, я начну с:

A = np.arange(4)
B = np.arange(10, 14)

a = tf.placeholder(tf.float32, [None])
b = tf.placeholder(tf.float32, [None])
c = tf.add(a, b)

with tf.Session() as sess:
    for i in range(10):
        x = sess.run(c, feed_dict={a: A, b:B})
        print(i, x)

Затем я пытаюсь изменить его, чтобы использовать набор данных следующим образом:

A = np.arange(4)
B = np.arange(10, 14)

a = tf.placeholder(tf.int32, A.shape)
b = tf.placeholder(tf.int32, B.shape)
c = tf.add(a, b)

dataset = tf.data.Dataset.from_tensors((a, b))

iterator = dataset.make_initializable_iterator()

with tf.Session() as sess3:
    sess3.run(tf.global_variables_initializer())
    sess3.run(iterator.initializer, feed_dict={a: A, b: B})

    for i in range(10):
        x = sess3.run(c)
        print(i, x)

Если я запускаю это, я получаю «InvalidArgumentError: вы должны указать значение для тензора заполнителя ...»

Код до цикла for имитирует пример здесь, но я не понимаю, как Затем я могу использовать заполнители a и b, не предоставляя feed_dict для каждого вызова sess3.run(c) [что было бы дорого]. Я подозреваю, что мне нужно как-то использовать итератор, но я не понимаю, как это сделать.

Обновить

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

Для более разумного вопроса, как я могу использовать наборы данных для заполнения заполнителей ниже (хотя представьте, что X и Y_true намного длиннее...). Документация подводит меня к точке, где начинается цикл, и тогда я не уверен.

X = np.arange(8.).reshape(4, 2)
Y_true = np.array([0, 0, 1, 1])

x = tf.placeholder(tf.float32, [None, 2], name='x')
y_true = tf.placeholder(tf.float32, [None], name='y_true')

w = tf.Variable(np.random.randn(2, 1), name='w', dtype=tf.float32)

y = tf.squeeze(tf.matmul(x, w), name='y')

loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(
                                labels=y_true, logits=y),
                                name='x_entropy')

# set optimiser
optimiser = tf.train.AdamOptimizer().minimize(loss)

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

    for i in range(100):
        _, loss_out = sess.run([optimiser, loss], feed_dict={x: X, y_true:Y_true})
        print(i, loss_out)

Попытка сделать следующее дает мне InvalidArgumentError

X = np.arange(8.).reshape(4, 2)
Y_true = np.array([0, 0, 1, 1])

x = tf.placeholder(tf.float32, [None, 2], name='x')
y_true = tf.placeholder(tf.float32, [None], name='y_true')

dataset = tf.data.Dataset.from_tensor_slices((x, y_true))
iterator = dataset.make_initializable_iterator()

w = tf.Variable(np.random.randn(2, 1), name='w', dtype=tf.float32)

y = tf.squeeze(tf.matmul(x, w), name='y')

loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(
                                labels=y_true, logits=y),
                                name='x_entropy')

# set optimiser
optimiser = tf.train.AdamOptimizer().minimize(loss)

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

    sess.run(iterator.initializer, feed_dict={x: X,
                                              y_true: Y_true})

    for i in range(100):
        _, loss_out = sess.run([optimiser, loss])
        print(i, loss_out)

person stuart10    schedule 13.12.2017    source источник
comment
Каков, по вашему мнению, будет результат sess3.run(c)? dataset содержит только один элемент, поэтому, даже если вы использовали iterator.get_next(), цикл выполнит только одну итерацию, прежде чем сигнализировать, что элементов больше нет.   -  person mrry    schedule 13.12.2017
comment
Это, наверное, не самый яркий пример - я пытался показать самый простой пример, который мог, но, видимо, потерял смысл... Я отредактирую вопрос.   -  person stuart10    schedule 14.12.2017


Ответы (2)


Проблема в вашем более сложном примере заключается в том, что вы используете одни и те же узлы tf.placeholder() в качестве входных данных для Dataset.from_tensor_slices() (что правильно) и самой сети (что вызывает InvalidArgumentError. Вместо этого, как указывает J.E.K в их ответ, вы должны использовать iterator.get_next() в качестве входных данных для своей сети следующим образом (обратите внимание, что есть несколько других исправлений Я добавил, чтобы код работал как есть):

X = np.arange(8.).reshape(4, 2)
Y_true = np.array([0, 0, 1, 1])

x = tf.placeholder(tf.float32, [None, 2], name='x')
y_true = tf.placeholder(tf.float32, [None], name='y_true')

dataset = tf.data.Dataset.from_tensor_slices((x, y_true))

# You will need to repeat the input (which has 4 elements) to be able to take
# 100 steps.
dataset = dataset.repeat()

iterator = dataset.make_initializable_iterator()

# Use `iterator.get_next()` to create tensors that will consume values from the
# dataset.
x_next, y_true_next = iterator.get_next()

w = tf.Variable(np.random.randn(2, 1), name='w', dtype=tf.float32)

# The `x_next` tensor is a vector (i.e. a row of `X`), so you will need to
# convert it to a matrix or apply batching in the dataset to make it work with
# `tf.matmul()`
x_next = tf.expand_dims(x_next, 0)

y = tf.squeeze(tf.matmul(x_next, w), name='y')  # Use `x_next` here.

loss = tf.reduce_mean(
    tf.nn.sigmoid_cross_entropy_with_logits(
        labels=y_true_next, logits=y),  # Use `y_true_next` here.
    name='x_entropy')

# set optimiser
optimiser = tf.train.AdamOptimizer().minimize(loss)

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

    sess.run(iterator.initializer, feed_dict={x: X,
                                              y_true: Y_true})

    for i in range(100):
        _, loss_out = sess.run([optimiser, loss])
        print(i, loss_out)
person mrry    schedule 15.12.2017
comment
Отлично, я думаю, что это помогло мне преодолеть концептуальный «горб», так что теперь у меня есть некоторое представление о том, как работает набор данных, спасибо! - person stuart10; 15.12.2017

Используйте iterator.get_next() для получения элементов из Dataset, например:

next_element = iterator.get_next()

чем инициализировать итератор

sess.run(iterator.initializer, feed_dict={a:A, b:B})

и хотя бы получить значения от Dataset

value = sess.run(next_element)

ИЗМЕНИТЬ:

Приведенный выше код просто возвращает элементы из Dataset. API набора данных предназначен для обслуживания features и labels для input_fn, поэтому все дополнительные вычисления для предварительной обработки должны выполняться в API набора данных. Если вы хотите добавить элементы, вы должны определить функцию, которая применяется к элементам, например:

def add_fn(exp1, exp2):
  return tf.add(exp1, exp2)

и чем вы можете сопоставить эти функции с вашим набором данных:

dataset = dataset.map(add_fn)

Полный пример кода:

A = np.arange(4)
B = np.arange(10, 14)
a = tf.placeholder(tf.int32, A.shape)
b = tf.placeholder(tf.int32, B.shape)
#c = tf.add(a, b)
def add_fn(exp1, exp2):
  return tf.add(exp1, exp2)
dataset = tf.data.Dataset.from_tensors((a, b))
dataset = dataset.map(add_fn)
iterator = dataset.make_initializable_iterator()
next_element = iterator.get_next()
with tf.Session() as sess:
  sess.run(iterator.initializer, feed_dict={a: A, b: B})
  # just one element at dataset
  x = sess.run(next_element)
  print(x)
person J.E.K    schedule 13.12.2017