Tensorflow dataset API 的使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shinian1987/article/details/81915139

Tensorflow 作为深度学习最流行的框架之一,对于初学者来说,其数据处理的 API 其实并不算友好,从早期的 feed dic, 到后来的 tf-record, 再到现在的 dataset, 这个框架的高度封装造成了其很多 API 的高度抽象, 今天介绍 TensorFlow 里,比较快速便捷的一种数据处理 API, dataset API。

使用 Dataset 一般包含以下几个方面:

  1. 载入数据:为数据创建一个Dataset实例

  2. 创建一个迭代器:使用创建的数据集来构造一个Iterator实例以遍历数据集

  3. 使用数据:使用创建的迭代器,我们可以从数据集中获取数据元素,从而输入到模型中去。

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

猜你喜欢

转载自blog.csdn.net/shinian1987/article/details/81915139