Reputation: 111
The setting: I want to predict a value by training a CNN on input batches in a regression setting. I also want to evaluate and calculate the loss after every epoch, so I need to switch between datasets at runtime.
Input: [num_examples, height, width, channels] -> [num_examples, y]
I want to use the new Dataset API because I want to avoid feeding batches myself during the training.
I also don't want to store my dataset in the computation graph because the Dataset is bigger than 2GB, but small enough to be stored in memory.
This is my current setup:
def initialize_datasets(x, y,...):
dataset_train = tf.data.Dataset.from_tensor_slices((x, y))
dataset_train = dataset_train.apply(tf.contrib.data.shuffle_and_repeat(buffer_size=examples_train, count=epochs))
dataset_train = dataset_train.batch(batch_size)
dataset_test = tf.data.Dataset.from_tensor_slices((x, y))
dataset_test = dataset_test.apply(tf.contrib.data.shuffle_and_repeat(buffer_size=examples_test, count=-1))
dataset_test = dataset_test.batch(batch_size)
# Iterator
iterator_train = dataset_train.make_initializable_iterator()
iterator_test = dataset_test.make_initializable_iterator()
return iterator_train, iterator_test
def get_input_batch_data(testing, iterator_train, iterator_test):
features, labels = tf.cond(testing, lambda: iterator_test.get_next(), lambda: iterator_train.get_next())
return features, labels
Then in my model()
function:
#1
iterator_train, iterator_test = initialize_datasets(x, y, ...)
#2
features, labels = get_input_batch_data(testing, iterator_train,
iterator_test)
# forward pass, loss, etc
...
with tf.Session as sess:
#initialize with train data, trainX[num_examples, height, width, channels]
sess.run(iterator_train.initializer, feed_dict={x: trainX, y: trainY,
batch_size: batchsize})
#initialize with test data
sess.run(iterator_test.initializer, feed_dict={x: testX, y: testY,
batch_size: NUM_EXAMPLES_TEST})
for i in range(EPOCHS)
for j in range(NUM_BATCHES)
_, batch_loss = sess.run([train_step, loss], feed_dict={testing:
False, i: iters_total, pkeep: p_keep})
# after 1 epoch, calculate loss and whole test data set
epoch_test_loss = sess.run(loss, feed_dict={testing: True, i:
iters_total, pkeep: 1})
This is the output:
Iter: 44, Epoch: 0 (8.46s), Train-Loss: 103011.18, Test-Loss: 100162.34
Iter: 89, Epoch: 1 (4.17s), Train-Loss: 93699.51, Test-Loss: 92130.21
Iter: 134, Epoch: 2 (4.13s), Train-Loss: 90217.82, Test-Loss: 88978.74
Iter: 179, Epoch: 3 (4.14s), Train-Loss: 88503.13, Test-Loss: 87515.81
Iter: 224, Epoch: 4 (4.18s), Train-Loss: 87336.62, Test-Loss: 86486.40
Iter: 269, Epoch: 5 (4.10s), Train-Loss: 86388.38, Test-Loss: 85637.64
Iter: 314, Epoch: 6 (4.14s), Train-Loss: 85534.52, Test-Loss: 84858.43
Iter: 359, Epoch: 7 (4.29s), Train-Loss: 84693.19, Test-Loss: 84074.78
Iter: 404, Epoch: 8 (4.20s), Train-Loss: 83973.64, Test-Loss: 83314.47
Iter: 449, Epoch: 9 (4.40s), Train-Loss: 83149.73, Test-Loss: 82541.73
Problems:
I also uploaded the whole model here: https://github.com/toemm/TF-CNN-regression/blob/master/BA-CNN_so.ipynb
Upvotes: 1
Views: 1842
Reputation: 4460
The obvious answer is: You do not want to do this within the same graph as the evaluation graph is different from the training graph.
So the solution is really to build two different things like
import numpy as np
import tensorflow as tf
X_train = tf.constant(np.ones((100, 2)), 'float32')
X_val = tf.constant(np.zeros((10, 2)), 'float32')
iter_train = tf.data.Dataset.from_tensor_slices(
X_train).make_initializable_iterator()
iter_val = tf.data.Dataset.from_tensor_slices(
X_val).make_initializable_iterator()
def graph(x, is_train=True):
return x
output_train = graph(iter_train.get_next(), is_train=True)
output_val = graph(iter_val.get_next(), is_train=False)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
sess.run(iter_train.initializer)
sess.run(iter_val.initializer)
for train_iter in range(100):
print(sess.run(output_train))
for train_iter in range(10):
print(sess.run(output_val))
Upvotes: 4