TensorFlow Dataset

简介 Brief

作为新手, 你可能还在使用feed_dict来给你的tensorflow Graph提供数据. 但是, Tensorflow已经在tf.data中提供了更高层的API, 用于提供数据.

As green hand, you can use feed_dict to feed data to your tensorflow graph. However, Tensorflow has provided high-level API for feeding data in tf.data.

基础概念 Basics

两个基本概念, tf.data.Dataset 用来表征数据. tf.data.Iterator 用来消费数据.

Dataset

如果通过内存中的某些张量构建Dataset, 则需要通过tf.data.Dataset.from_tensors()tf.data.Dataset.from_tensor_slices()两个方法来进行构建.

如果是通过硬盘上的文件进行构建, 则可以构建tf.data.TFRecordDataset.
类似的还有tf.data.TextLineDatasettf.data.FixedLengthRecordDataset. 后面会给出对应的初始化和消费代码.

Iterator

构建Iterator的方式是通过Dataset中的make_one_shot_iteratormake_initializable_iterator两个方法进行构建, 返回的对象是tf.data.Iterator.

Dataset.make_one_shot_iterator() 不需要显性的初始化.

Dataset创建的Iterator需要执行initializer().
Iterator实例化的对象需要通过make_initializer()来指定迭代的Dataset.

根据Iterator的定义,
Acccording to the definition of Iterator,

注意 : 大部分用户并不会直接调用, 而是用Dataset.make_initializable_iterator() or Dataset.make_one_shot_iterator()来间接生成.

Note: Most users will not call this initializer directly, and will instead use Dataset.make_initializable_iterator() or Dataset.make_one_shot_iterator().

但是, 如果你知道dataset的数据类型和结构, 可以通过调用staticmethod方法 from_structure 来实例化一个Iterator.

However, if you know the specific type and structure of dataset, you can generate one Iterator instance by calling the static method from_structure


Differences between from_tensors and from_tensor_slices

它的作用是切分传入Tensor的第一个维度,生成相应的dataset。
例1:
dataset = tf.data.Dataset.from_tensor_slices(np.random.uniform(size=(5, 2)))
传入的数值是一个矩阵,它的形状为(5, 2),tf.data.Dataset.from_tensor_slices就会切分它形状上的第一个维度,最后生成的dataset中一个含有5个元素,每个元素的形状是(2, ),即每个元素是矩阵的一行。
例2:
对于更复杂的情形,比如元素是一个python中的元组或者字典:在图像识别中一个元素可以是{”image”:image_tensor,”label”:label_tensor}的形式。
dataset = tf.data.Dataset.from_tensor_slices ( { “a”:np.array([1.0,2.0,3.0,4.0,5.0]), “b”:np.random.uniform(size=(5,2) ) } )
这时,函数会分别切分”a”中的数值以及”b”中的数值,最后总dataset中的一个元素就是类似于{ “a”:1.0, “b”:[0.9,0.1] }的形式。
2

Dataset.from_tensors()
Dataset.from_tensor_slices()

Dataset使用中的一些问题

tf.data.Dataset.shuffle(buffer_size)中的buffer_size是什么意思?

先看下官方给出的Dataset.shullfe操作的定义:

api_docs/python/tf/data/Dataset#shuffle

python
shuffle(
buffer_size,
seed=None,
reshuffle_each_iteration=None
)

Randomly shuffles the elements of this dataset.
随机重新排序dataset中的元素.

This dataset fills a buffer with buffer_size elements, then randomly samples elements from this buffer, replacing the selected elements with new elements. For perfect shuffling, a buffer size greater than or equal to the full size of the dataset is required.
dataset使用buffer_size个元素填满一个缓冲区(buffer), 然后从该缓冲区内随机抽样元素. 对于被抽中的元素, 使用新的元素进行填充. 为了获得完美的随机排序效果, 应该将缓冲区的大小设置为大于或等于dataset的大小.

这里引入了两个问题:
1. 用于填充的new_elements指的是从除去buffer_size之后剩余的数据里抽取吗?
2. 为什么要将缓冲区的大小设置为大于或等于dataset的大小?

为了便于理解, tf.data.Dataset.shuffle(buffer_size)中buffer_size的理解中给出了很好的图解.

  1. Dataset会取所有数据的前buffer_size数据项, 填充 buffer.
    dataset.shuffle.01

  2. 然后, 从buffer中随机选择一条数据输出, 比如这里随机选中了item 7, 那么buffer中item 7对应的位置就空出来了.
    dataset.shuffle.02

  3. 然后, 从Dataset中顺序选择最新的一条数据填充到buffer中, 这里是item 10.
    dataset.shuffle.03

  4. 然后在从Buffer中随机选择下一条数据输出, 也就是返回步骤2.

需要说明的是,这里的数据项item, 并不只是单单一条真实数据, 如果有batch size, 则一条数据项item包含了batch size条真实数据.

shuffle是防止数据过拟合的重要手段,然而不当的buffer size,会导致shuffle无意义.

References

TensorFlow – Guide – High Level Guide – Importing Data
tf.data.Dataset.shuffle(buffer_size)中buffer_size的理解
Meaning of buffer_size in Dataset.map , Dataset.prefetch and Dataset.shuffle

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据