参考链接:
Dataset官方链接 <https://tensorflow.google.cn/api_docs/python/tf/data/Dataset>
TensorFlow全新的数据读取方式:Dataset API入门教程
<https://blog.csdn.net/qq_40027052/article/details/78528898>

TensorFlow数据读取方式:

* 利用placeholder读取内存数据
* 利用queue读取硬盘中的数据
参考链接:https://zhuanlan.zhihu.com/p/27238630
<https://zhuanlan.zhihu.com/p/27238630>
* Dataset API同时支持从内存和硬盘的读取,相比之前的两种方法在语法上更加简洁易懂
Dataset创建和读取数据集

Google官方给出的Dataset API中的类图如下所示:

Dataset可以看作是相同类型元素的有序列表。在实际使用时,单个元素可以是向量,也可以是字符串、图片,元组tuple或者字典dict

简单的创建和读取

以单个元素为数字为例创建Dataset,创建的数据集包含1~5 5个元素
dataset = tf.data.Dataset.from_tensor_slices(np.array([1.0, 2.0, 3.0, 4.0, 5.0
]))
使用类iterator读取数据集中的值如下所示:
#实例化make_one_shot_iterator对象,该对象只能读取一次 iterator =
dataset.make_one_shot_iterator()# 从iterator里取出一个元素 one_element =
iterator.get_next()with tf.Session() as sess: for i in range(5):
print(sess.run(one_element))

如果一个dataset中元素被读取完了,再尝试sess.run(one_element)的话,就会抛出tf.errors.OutOfRangeError异常,这个行为与使用队列方式读取数据的行为是一致的。在实际程序中,可以在外界捕捉这个异常以判断数据是否读取完,请参考下面的代码:
iterator = dataset.make_one_shot_iterator() one_element = iterator.get_next()
with tf.Session() as sess: try: while True: print(sess.run(one_element)) except
tf.errors.OutOfRangeError: print("end!")
创建较为复杂的Dataset

tf.data.Dataset.from_tensor_slices会切分传入Tensor的第0个维度,生成相应的dataset。
dataset = tf.data.Dataset.from_tensor_slices(np.random.uniform(size=(5, 2)))
传入的数值是一个矩阵,它的形状为(5, 2),tf.data.Dataset.from_tensor_slices
就会切分它形状上的第0个维度,最后生成的dataset中一个含有5个元素,每个元素的形状是(2, ),即每个元素是矩阵的一行,相当于一个一维的array。
实际使用中,Dataset中的元素可能是元组或者字典。在图像识别问题中,一个元素可以是{“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': 1.0, 'b': array([0.26454147, 0.78977893])} {'a': 2.0, 'b': array([
0.19478178, 0.37884041])} {'a': 3.0, 'b': array([0.45655924, 0.46979661])} {'a':
4.0, 'b': array([0.08724776, 0.26343558])} {'a': 5.0, 'b': array([0.63206763,
0.02796295])}
例如(元组):
dataset = tf.data.Dataset.from_tensor_slices( (np.array([1.0, 2.0, 3.0, 4.0,
5.0]), np.random.uniform(size=(5, 2))) )
输出:
(1.0, array([0.48643253, 0.69208099])) (2.0, array([0.96668577, 0.39036077])) (
3.0, array([0.54854508, 0.54833064])) (4.0, array([0.30970788, 0.29545166])) (
5.0, array([0.0290356 , 0.75689468]))
对Dataset中的数据进行转换transformation


一个Dataset通过Transformation变成一个新的Dataset。通常我们可以通过Transformation完成数据变换,打乱,组成batch,生成epoch等一系列操作
常用的Transformation有:

* map
* batch
* shuffle
*
repeat

(1)map

map接收一个函数对象,Dataset中的每个元素都会被当作这个函数的输入,并将函数返回值作为新的Dataset,如我们可以对dataset中每个元素的值加1:
dataset = tf.data.Dataset.from_tensor_slices(np.array([1.0, 2.0, 3.0, 4.0, 5.0
])) dataset = dataset.map(lambda x: x + 1) # 2.0, 3.0, 4.0, 5.0, 6.0
(2)batch
根据接收的整数值将该数个元素组合成batch,如下面的程序将dataset中的元素组成了大小为32的batch
dataset = dataset.batch(32)
(3)shuffle
打乱dataset中的元素,它有一个参数buffersize,表示打乱时使用的buffer的大小
dataset = dataset.shuffle(buffer_size=10000)
(4)repeat
整个序列重复多次,主要用来处理机器学习中的epoch,假设原先的数据是一个epoch,使用repeat(5)就可以将之变成5个epoch:
dataset = dataset.repeat(5)
实例:读入磁盘图片和label创建Dataset

读入磁盘中的图片和图片相应的label,并将其打乱,组成batch_size=32的训练样本。在训练时重复10个epoch。
# 将filename对应的图片文件读入,并缩放到统一的大小 def _parse_function(filename, label): #
读取图像文件内容编码为字符串 image_contents = tf.read_file(filename) #
根据图像编码后的字符串解码为uint8的tensor image_decoded = tf.image.decode_image(image_contents)
# 修改图像尺寸 image_resized = tf.image.resize_images(image_decoded, [28, 28]) return
image_resized, label# 图片文件的列表 filenames = tf.constant(["/var/data/image1.jpg",
"/var/data/image2.jpg", ...]) # label[i]就是图片filenames[i]的label labels =
tf.constant([0, 37, ...]) # 此时dataset中的一个元素是(filename, label) dataset =
tf.data.Dataset.from_tensor_slices((filenames, labels))#
此时dataset中的一个元素是(image_resized, label) dataset = dataset.map(_parse_function) #
此时dataset中的一个元素是(image_resized_batch, label_batch) #
dataset中的元素是(image_resized_batch, label_batch),image_resized_batch的形状为(32, 28,
28, 3),而label_batch的形状为(32, ) dataset = dataset.shuffle(buffersize=1000).batch(
32).repeat(10)
Dataset其他创建方法

Dataset API还提供了另外三种创建Dataset的方式:

*
tf.data.TextLineDataset():这个函数的输入是一个文件的列表,输出是一个dataset。dataset中的每一个元素就对应了文件中的一行。可以使用这个函数来读入CSV文件。
*
tf.data.FixedLengthRecordDataset():这个函数的输入是一个文件的列表和一个record_bytes,之后dataset的每一个元素就是文件中固定字节数record_bytes的内容。通常用来读取以二进制形式保存的文件,如CIFAR10数据集就是这种形式。
*
tf.data.TFRecordDataset():顾名思义,这个函数是用来读TFRecord文件的,dataset中的每一个元素就是一个TFExample。
其他的Iterator

除了这种one shot iterator外,还有三个更复杂的Iterator,即:
- initializable iterator
- reinitializable iterator
- feedable iterator

initializable iterator

initializable iterator必须要在使用前通过sess.run()来初始化。使用initializable
iterator,可以将placeholder代入Iterator中,这可以方便我们通过参数快速定义新的Iterator。一个简单的initializable
iterator使用示例:
limit = tf.placeholder(dtype=tf.int32, shape=[]) dataset = tf.data.Dataset.from
_tensor_slices(tf.range(start=0, limit=limit)) iterator = dataset.make
_initializable_iterator() next_element = iterator.get_next() with tf.Session()
as sess: sess.run(iterator.initializer, feed_dict={limit: 10}) for i in range(10
): value = sess.run(next_element)
使用initializable
iterator读入大规模数据时更为方便。在使用tf.data.Dataset.from_tensor_slices(array)时,实际上发生的事情是将array作为一个tf.constants保存到了计算图中。当array很大时,会导致计算图变得很大,给传输、保存带来不便。这时,我们可以用一个placeholder取代这里的array,并使用initializable
iterator,只在需要时将array传进去,这样就可以避免把大数组保存在图里,示例代码为(来自官方例程):
with np.load("/var/data/training_data.npy") as data: features = data["features"
] labels = data["labels"] features_placeholder = tf.placeholder(features.dtype,
features.shape) labels_placeholder = tf.placeholder(labels.dtype, labels.shape)
dataset = tf.data.Dataset.from_tensor_slices((features_placeholder,
labels_placeholder)) iterator = dataset.make_initializable_iterator() sess.run
(iterator.initializer, feed_dict={features_placeholder: features,
labels_placeholder: labels})
reinitializable iterator

此iterator可以被不同的数据集重用
# Creates a new, uninitialized Iterator with the given structure iterator =
tf.data.Iterator.from_structure(tf.int64, tf.TensorShape([])) # The returned
iterator is not bound to a particular dataset, # and it has no initializer. To
initialize theiterator, run the # operation returned by Iterator
.make_initializer(dataset). dataset_range = tf.data.Dataset.range(2)
range_initializer =iterator.make_initializer(dataset_range) dataset_evens =
tf.data.Dataset.range(3) evens_initializer = iterator
.make_initializer(dataset_evens) next_batch =iterator.get_next() sess =
tf.Session() # Initialize theiterator to `dataset_range`
sess.run(range_initializer)while True: try: val = sess.run(next_batch)
print(val)except tf.errors.OutOfRangeError: break print('-------------------')
# Initialize theiterator to `dataset_evens` sess.run(evens_initializer) while
True: try: val1 = sess.run(next_batch) print(val1) except
tf.errors.OutOfRangeError:break
输出:
0 1 ------------------- 0 1 2

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信