Tensorflow 作为深度学习最流行的框架之一,对于初学者来说,其数据处理的 API 其实并不算友好,从早期的 feed dic, 到后来的 tf-record, 再到现在的 dataset, 这个框架的高度封装造成了其很多 API 的高度抽象, 今天介绍 TensorFlow 里,比较快速便捷的一种数据处理 API, dataset API。
使用 Dataset 一般包含以下几个方面:
载入数据:为数据创建一个Dataset实例
创建一个迭代器:使用创建的数据集来构造一个Iterator实例以遍历数据集
使用数据:使用创建的迭代器,我们可以从数据集中获取数据元素,从而输入到模型中去。
load data
首先我们看 load data,
最直观的就是从 numpy 载入,我们可以利用 numpy 定义好一个数组,然后将定义好的数组载入 dataset
# create a random vector of shape (100,2)
x = np.random.sample((100,2))
# make a dataset from a numpy array
dataset = tf.data.Dataset.from_tensor_slices(x)
或者可以同时传递 feature 和 label,
features, labels = (np.random.sample((100,2)), np.random.sample((100,1)))
dataset = tf.data.Dataset.from_tensor_slices((features,labels))
另外一种比较常见的载入方式是利用 placeholder,有的时候,我们需要从外部载入数据,可以利用 placeholder 来实现:
x = tf.placeholder(tf.float32, shape=[None,2])
dataset = tf.data.Dataset.from_tensor_slices(x)
create iterator
数据载入之后,接下来,需要创建迭代器,iterator
1: 最简单的就是 make_one_shot_iterator
x = np.random.sample((100,2))
# make a dataset from a numpy array
dataset = tf.data.Dataset.from_tensor_slices(x)
# 创建迭代器
iter = dataset.make_one_shot_iterator()
# 调用 get_next 来进行访问
el = iter.get_next()
# 利用 session 运行查看结果:
with tf.Session() as sess:
print(sess.run(el))
2:第二种迭代器的创建方式,就是 make_initializable_iterator()
# using a placeholder
x = tf.placeholder(tf.float32, shape=[None,2])
dataset = tf.data.Dataset.from_tensor_slices(x)
data = np.random.sample((100,2))
# 创建迭代器
iter = dataset.make_initializable_iterator()
el = iter.get_next()
with tf.Session() as sess:
# feed the placeholder with data
sess.run(iter.initializer, feed_dict={ x: data })
print(sess.run(el))
这种创建迭代器的好处就是可以重复使用,如下所示:
# initializable iterator to switch between dataset
EPOCHS = 10
x, y = tf.placeholder(tf.float32, shape=[None,2]), tf.placeholder(tf.float32, shape=[None,1])
dataset = tf.data.Dataset.from_tensor_slices((x, y))
train_data = (np.random.sample((100,2)), np.random.sample((100,1)))
test_data = (np.array([[1,2]]), np.array([[0]]))
iter = dataset.make_initializable_iterator()
features, labels = iter.get_next()
with tf.Session() as sess:
# initialise iterator with train data
sess.run(iter.initializer, feed_dict={ x: train_data[0], y: train_data[1]})
for _ in range(EPOCHS):
sess.run([features, labels])
# switch to test data
sess.run(iter.initializer, feed_dict={ x: test_data[0], y: test_data[1]})
print(sess.run([features, labels]))
3:第三种创建方式是利用: data.Iterator.from_structure
# Reinitializable iterator to switch between Datasets
EPOCHS = 10
# making fake data using numpy
train_data = (np.random.sample((100,2)), np.random.sample((100,1)))
test_data = (np.random.sample((10,2)), np.random.sample((10,1)))
# create two datasets, one for training and one for test
train_dataset = tf.data.Dataset.from_tensor_slices(train_data)
test_dataset = tf.data.Dataset.from_tensor_slices(test_data)
# 创建迭代器
iter = tf.data.Iterator.from_structure(train_dataset.output_types,
train_dataset.output_shapes)
features, labels = iter.get_next()
# 利用迭代器进行不同的初始化
train_init_op = iter.make_initializer(train_dataset)
test_init_op = iter.make_initializer(test_dataset)
with tf.Session() as sess:
sess.run(train_init_op) # switch to train dataset
for _ in range(EPOCHS):
sess.run([features, labels])
sess.run(test_init_op) # switch to val dataset
print(sess.run([features, labels]))
dataset 的使用
载入数据,创建迭代器之后,我们一般都会利用 dataset 进行训练,
EPOCHS = 10
BATCH_SIZE = 16
# using two numpy arrays
features, labels = (np.array([np.random.sample((100,2))]),
np.array([np.random.sample((100,1))]))
dataset = tf.data.Dataset.from_tensor_slices((features,labels)).repeat().batch(BATCH_SIZE)
iter = dataset.make_one_shot_iterator()
x, y = iter.get_next()
# make a simple model
net = tf.layers.dense(x, 8, activation=tf.tanh) # pass the first value from iter.get_next() as input
net = tf.layers.dense(net, 8, activation=tf.tanh)
prediction = tf.layers.dense(net, 1, activation=tf.tanh)
loss = tf.losses.mean_squared_error(prediction, y) # pass the second value from iter.get_net() as label
train_op = tf.train.AdamOptimizer().minimize(loss)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(EPOCHS):
_, loss_value = sess.run([train_op, loss])
print("Iter: {}, Loss: {:.4f}".format(i, loss_value))
常用函数
batch
dataset API 里,还有几个比较常用的函数,一个是 batch,可以非常方便的将载入的数据自动封装成一个个的 batch,
# BATCHING
BATCH_SIZE = 4
x = np.random.sample((100,2))
# make a dataset from a numpy array
dataset = tf.data.Dataset.from_tensor_slices(x).batch(BATCH_SIZE)
iter = dataset.make_one_shot_iterator()
el = iter.get_next()
with tf.Session() as sess:
print(sess.run(el))
repeat
使用.repeat()我们可以指定数据集迭代的次数。如果没有设置参数,则迭代会一直循环。通常来说,一直循环并直接用标准循环控制epoch的次数能取得较好的效果。
shuffle
shuffle 可以将载入的数据随机打乱,因为一般来说,我们载入的数据可能会出现属于某个类的数据扎堆出现,利用 shuffle 可以将数据打乱,提升训练的效率,避免过拟合
# BATCHING
BATCH_SIZE = 4
x = np.array([[1],[2],[3],[4]])
# make a dataset from a numpy array
dataset = tf.data.Dataset.from_tensor_slices(x)
dataset = dataset.shuffle(buffer_size=100)
dataset = dataset.batch(BATCH_SIZE)
iter = dataset.make_one_shot_iterator()
el = iter.get_next()
with tf.Session() as sess:
print(sess.run(el))
map
map 也是常用的一个函数,map 可以通过自定义的函数,改变原始的输入,这个在处理图像的时候非常有用:
trainA = tf.data.Dataset.from_tensor_slices(trainA_dataset)
def image_processing(filename):
x = tf.read_file(filename) # file read
x_decode = tf.image.decode_jpeg(x, channels=3) # for RGB
# DO NOT USE decode_image
# will be error
img = tf.image.resize_images(x_decode, [256, 256])
img = tf.cast(img, tf.float32) / 127.5 - 1
return img
trainA = trainA.map(image_processing, num_parallel_calls=8)
参考来源:
https://github.com/FrancescoSaverioZuppichini/Tensorflow-Dataset-Tutorial/blob/master/dataset_tutorial.ipynb
https://blog.csdn.net/dqcfkyqdxym3f8rb0/article/details/79342369