TensorFlow导入数据详解

本文详细介绍了如何使用TensorFlow的tf.data API构建复杂的输入管道,包括数据源的创建、数据预处理、批处理以及训练工作流。从Numpy数组、TFRecord到文本数据的读取,再到Dataset.map()的使用,提供了丰富的示例。
摘要由CSDN通过智能技术生成

原文地址:https://www.tensorflow.org/programmers_guide/datasets

tf.data API 可以让人从简单可复用的piece中建立复杂的输入管道。例如,一个对于图像模型的管道,可能要从分布式文件系统中整合数据,对每个图片产生随机干扰,并且合并这些随机选择的图片到batch中用于训练;一个对于文字模型的管道可能涉及到从原始文本数据中提取符合, 利用查询表将它们转化成embedding identifier,并且整合不同长度的序列。

tf.data API 简化了大量数据、不同数据格式以及复杂转化的处理。

tf.data API带来了TensorFlow的两种新抽象:

  • tf.data.Dataset : 表示元素的序列,其中每个元素包含了一个或多个Tensor对象。例如,一个图像数据管道中,一个元素可能是一个具有一对张量表示其图像数据和标签的训练样本 。有两个不同的方法创建dataset :
    • 创造source (例如Dataset.from_tensor_slices()) 从一个或多个tf.Tensor对象中构建dataset
    • 使用transformation(例如Dataset.batch()) 从一个或多个tf.data.Dataset对象中构建dataset
  • tf.data.Iterator : 是从dataset中提取元素的主要方式。该操作通过 Iterator.get_next() yield出 Dataset的下一个元素,一般作为输入管道和模型之间的接口。最简单的迭代器是 “one-shot iterator” ,用来迭代一次某个特定的Dataset。更复杂的使用中,Iterator.initializer操作可以用不同的dataset重新初始并且参数化一个迭代器,可以以此在一个程序中训练和验证数据多次。

基础机制

启动一个输入管道,需要首先定义source 。 为了从内存的张量中构建Dataset,可以使用 tf.data.Dataset.from_tensors() 或者
tf.data.Dataset.from_tensor_slices(),再或者,如果数据在硬盘上以推荐的TFRecord格式存储,可以构建一个tf.data.TFRecordDataset

拥有了Dataset对象以后,可以将它们转化为新的Dataset。例如Dataset.map()Dataset.batch()

最常用于使用Dataset的方式是使用一个迭代器(例如 Dataset.make_one_shot_iterator())。

tf.data.Iterator提供两种操作:

  • Iterator.initializer (重新)初始化迭代器
  • Iterator.get_next() 返回下一个元素的tf.Tensor对象

Dataset构建

dataset包括了含有相同结构的元素。一个元素包含一个或多个tf.Tensor对象,称作组件。每个组件有一个tf.DType 表示元素的类型;还有一个tf.TensorShape表示元素的形状。可以用Dataset.output_typesDataset.output_shapes来检查:

dataset1 = tf.data.Dataset.from_tensor_slices(tf.random_uniform([4, 10]))
print(dataset1.output_types)  # ==> "tf.float32"
print(dataset1.output_shapes)  # ==> "(10,)"

dataset2 = tf.data.Dataset.from_tensor_slices(
   (tf.random_uniform([4]),
    tf.random_uniform([4, 100], maxval=100, dtype=tf.int32)))
print(dataset2.output_types)  # ==> "(tf.float32, tf.int32)"
print(dataset2.output_shapes)  # ==> "((), (100,))"

dataset3 = tf.data.Dataset.zip((dataset1, dataset2))
print(dataset3.output_types)  # ==> (tf.float32, (tf.float32, tf.int32))
print(dataset3.output_shapes)  # ==> "(10, ((), (100,)))"

给元素中的组件命名也很方便 :

dataset = tf.data.Dataset.from_tensor_slices(
   {
  "a": tf.random_uniform([4]),
    "b": tf.random_uniform([4, 100], maxval=100, dtype=tf.int32)})
print(dataset.output_types)  # ==> "{'a': tf.float32, 'b': tf.int32}"
print(dataset.output_shapes)  # ==> "{'a': (), 'b': (100,)}"  

以及转变操作 :

dataset1 = dataset1.map(lambda x: ...)

dataset2 = dataset2.flat_map(lambda x, y: ...)

# Note: Argument destructuring is not available in Python 3.
dataset3 = dataset3.filter(lambda x, (y, z): ...)

创建迭代器

有了表示输入数据的Dataset后,下一步是创建可以得到其中元素的迭代器,随着复杂程度的提高,tf.data API 提供以下迭代器:

  • one-shot
  • initializable
  • reinitializable
  • feedable

one-shot是最简单的迭代器,不需要明确的初始化,迭代一次,但不支持参数化:

dataset = tf.data.Dataset.range(100)
iterator = dataset.make_one_shot_iterator()
next_element = iterator.get_next()

for i in range(100):
  value = sess.run(next_element)
  assert i == value

目前,one-shot迭代器是唯一易于在 Estimator上使用的类型

initializable迭代器需要在使用前进行iterator.initializer的操作,虽然不方便,但支持参数化,可以使用一个或多个 tf.placeholder() 在初始化迭代器时占位:

max_value = tf.placeholder(tf.int64, shape=[])
dataset = tf.data.Dataset.range(max_value)
iterator = dataset.make_initializable_iterator()
next_element = iterator.get_next()

# Initialize an iterator over a dataset with 10 elements.
sess.run(iterator.initializer, feed_dict={max_value: 10})
for i in range(10):
  value = sess.run(next_element)
  assert i == value

# Initialize the same iterator over a dataset with 100 elements.
sess.run(iterator.initializer, feed_dict={max_value: 100})
for i in range(100):
  value = sess.run(next_element)
  assert i == value

reinitializable迭代器可以从多个不同的Dataset对象中初始化。例如,一个使用随机干扰以提升泛化能力的训练输入管道,和一个评估未修改数据上的预测的验证输入管道。这些管道一般使用不同的Dataset对象,但是这些对象有相同的结构:

# Define training and validation datasets with the same structure.
training_dataset = tf.data.Dataset.range(<
  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值