我正在尝试学习新的Tensorflow API,我在输入批量张量的处理方面有点迷失,所以我可以使用例如tf.image来操纵和扩充它们。
这是我目前的网络&管道
trainX, testX, trainY, testY = read_data()
# trainX [num_image, height, width, channels], these are numpy arrays
#...
train_dataset = tf.data.Dataset.from_tensor_slices((trainX, trainY))
test_dataset = tf.data.Dataset.from_tensor_slices((testX, testY))
#...
iterator = tf.data.Iterator.from_structure(train_dataset.output_types,
train_dataset.output_shapes)
features, labels = iterator.get_next()
train_init_op = iterator.make_initializer(train_dataset)
test_init_op = iterator.make_initializer(test_dataset)
#...defining cnn architecture...
# In the train loop
TrainLoop {
sess.run(train_init_op) # switching to train data
sess.run(train_step, ...) # running a train step
#...
sess.run(test_init_op) # switching to test data
test_loss = sess.run(loss, ...) # printing test loss after epoch
}
我正在使用数据集API创建2个数据集,以便在trainloop中我可以计算列车和测试损失并记录它们。
在这个管道中我会操纵和扭曲我输入的一批图像?
我没有为我的trainX输入批次创建任何tf.placeholders,因此我无法使用tf.image操作它们,因为例如tf.image.flip_up_down
需要3-D或4-D张量。
答案 0 :(得分:3)
最近发布的一个非常好的article和talk比我在此处的回复详细介绍了API。这是一个简短的例子:
将tensorflow导入为tf 导入numpy为np
def read_data():
n_train = 100
n_test = 50
height = 20
width = 30
channels = 3
trainX = (np.random.random(
size=(n_train, height, width, channels)) * 255).astype(np.uint8)
testX = (np.random.random(
size=(n_test, height, width, channels))*255).astype(np.uint8)
trainY = (np.random.random(size=(n_train,))*10).astype(np.int32)
testY = (np.random.random(size=(n_test,))*10).astype(np.int32)
return trainX, testX, trainY, testY
trainX, testX, trainY, testY = read_data()
# trainX [num_image, height, width, channels], these are numpy arrays
train_dataset = tf.data.Dataset.from_tensor_slices((trainX, trainY))
test_dataset = tf.data.Dataset.from_tensor_slices((testX, testY))
def map_single(x, y):
print('Map single:')
print('x shape: %s' % str(x.shape))
print('y shape: %s' % str(y.shape))
x = tf.image.per_image_standardization(x)
# Consider: x = tf.image.random_flip_left_right(x)
return x, y
def map_batch(x, y):
print('Map batch:')
print('x shape: %s' % str(x.shape))
print('y shape: %s' % str(y.shape))
# Note: this flips ALL images left to right. Not sure this is what you want
# UPDATE: looks like tf documentation is wrong and you need a 3D tensor?
# return tf.image.flip_left_right(x), y
return x, y
batch_size = 32
train_dataset = train_dataset.repeat().shuffle(100)
train_dataset = train_dataset.map(map_single, num_parallel_calls=8)
train_dataset = train_dataset.batch(batch_size)
train_dataset = train_dataset.map(map_batch)
train_dataset = train_dataset.prefetch(2)
test_dataset = test_dataset.map(
map_single, num_parallel_calls=8).batch(batch_size).map(map_batch)
test_dataset = test_dataset.prefetch(2)
iterator = tf.data.Iterator.from_structure(train_dataset.output_types,
train_dataset.output_shapes)
features, labels = iterator.get_next()
train_init_op = iterator.make_initializer(train_dataset)
test_init_op = iterator.make_initializer(test_dataset)
with tf.Session() as sess:
sess.run(train_init_op)
feat, lab = sess.run((features, labels))
print(feat.shape)
print(lab.shape)
sess.run(test_init_op)
feat, lab = sess.run((features, labels))
print(feat.shape)
print(lab.shape)
一些注意事项:
tf.data.Dataset.from_generator
。如果您的shuffle缓冲区很大,这可能会导致缓慢的随机播放时间。我首选的方法是将一些keys
张量完全加载到内存中 - 它可能只是每个示例的索引 - 然后map
使用tf.py_func
来表示数据值的键值。这比转换为tfrecords
的效率略低,但prefetching
可能不会影响效果。由于混洗是在映射之前完成的,因此您只需将shuffle_buffer
个密钥加载到内存中,而不是shuffle_buffer
示例。tf.data.Dataset.map
,具体取决于您是否要应用批处理操作(处理4D图像张量的操作)或元素操作(3D图像张量)。请注意,tf.image.flip_left_right
的文档似乎已过时,因为当我尝试使用4D张量时出现错误。如果您想随机增加数据,请使用tf.image.random_flip_left_right
而不是tf.image.flip_left_right
。tf.estimator.Estimator
(或者不介意将代码转换为使用它),那么请查看tf.estimator.train_and_evaluate
以获取在数据集之间切换的内置方式shuffle
/ repeat
方法改组/重复数据集。有关效率的说明,请参阅the article。特别是,重复 - > shuffle - >地图 - >批次 - >分批地图 - >预取似乎是大多数应用程序的最佳操作顺序。