Tensorflow 现在将 Dataset 作为首选的数据读取手段,而 Iterator 是 Dataset 中最重要的概念。这篇文章的目的是,以官网文档为基础,较详细的介绍 Iterator 的用法。
Dataset 和 Iterator 的关系
在文章开始之前,首先得对 Dataset 和 Iterator 有一个感性的认识。
Dataset 是数据集,Iterator 是对应的数据集迭代器。
如果 Dataset 是一个水池的话,那么它其中的数据就好比是水池中的水,Iterator 你可以把它当成是一根水管。
在 Tensorflow 的程序代码中,正是通过 Iterator 这根水管,才可以源源不断地从 Dataset 中取出数据。
但为了应付多变的环境,水管也需要变化,Iterator 也有许多种类。
下面,细细道来。
一次性水管,单次 Iterator
创建单次迭代器,非常的简单,只需要调用 Dataset 对象相应的方法。
make_one_shot_iterator()
这个方法会返回一个 Iterator 对象。
而调用 iterator 的 get_next()
就可以轻松地取出数据了。
import tensorflow as tf
dataset = tf.data.Dataset.range(5)
iterator = dataset.make_one_shot_iterator()
with tf.Session() as sess:
while True:
try:
print(sess.run(iterator.get_next()))
except tf.errors.OutOfRangeError:
break
上面的代码非常简单,首先创建了一个包含 0 到 4 的数据集。然后,创建了一个单次迭代器。
通过循环调用 get_next()
方法就可以将数据取出。
需要注意的是,通常用 try-catch
配合使用,当 Dataset 中的数据被读取完毕的时候,程序会抛出异常,获取这个异常就可以从容结束本次数据的迭代。
然后, iterator 就完成了它的历史使命。单次的迭代器,不支持动态的数据集,它比较单纯,它不支持参数化。
什么是参数化呢?你可以理解为单次的 Iterator 认死理,它需要 Dataset 在程序运行之前就确认自己的大小,但我们都知道 Tensorflow 中有一种 feeding 机制,它允许我们在程序运行时再真正决定我们需要的数据,很遗憾,单次的 Iterator 不能满足这要的要求。
可以定制的水管,可初始化的 Iterator
单次 Iterator 无法满足参数化的要求,但有其他类型的 Iterator 可以完成这个目标。
先看一段代码,问问自己,你觉得它能正常运行吗?
def