TensorFlow数据读取⽅式:DatasetAPI,以及如何查看dataset:Dat。。。
TensorFlow数据读取⽅式:Dataset API
Datasets:⼀种为TensorFlow 模型创建输⼊管道的新⽅式。把数组、元组、张量等转换成DatasetV1Adapter格式
Dataset api有⽅法加载和操作数据,并将其输⼊到您的模型中。Dataset api与Estimators api很匹配。
下图是tensorflow API的完整架构图:
Datasets API是由以下图中所⽰的类组成:
其中:
**Dataset:**基类,包含创建和转换数据集的⽅法。还允许您从内存中的数据或Python中初始化数据集
⽣产者。
TextLineDataset: 从⽂本⽂件中读取⾏ (txt,csv…)。
TFRecordDataset: 从TFRecord⽂件 读取记录。
FixedLengthRecordDataset: 从⼆进制⽂件中读取固定⼤⼩的记录 。
Iterator: 提供⼀次访问⼀个数据集元素的⽅法
总之,Datasets API实现了从内存或者硬盘⽂件中加载数据组成数据集,同时对数据集进⾏⼀系列变换操作,最终将数据集提供给其他API 使⽤的⼀系列功能。下⾯,本⽂就将从这三个⽅⾯对Datasets API进⾏介绍。
加载数据形成数据集
dataset = tf.data.Dataset.from_tensor_slices(data #数据
)#按第⼀维度进⾏切分,返回dataset形式数据
#shapes:切分后的维度
#tf.float64:最⼩元素的类型
从内存或迭代器中加载数据:
数据集的单个元素包含⼀个或多个tf.Tensor对象,叫做分量。可能是单个张量,
张量的元组,或张量的嵌套元组。除了元组,您还可以使⽤collections.namedtuple或dictionary
将字符串映射到张量以表⽰数据集的单个元素。
# ⼀个张量 :
dataset1 = tf.data.Dataset.from_tensor_slices(tf.random_uniform([4, 10]))
# 张量的元组:
dataset2 =    tf.data.Dataset.from_tensor_slices((tf.random_uniform([4]),tf.random_uniform([4,100])))
# 张量的元组, mnist_data是⼀个objection
images = shape([-1, 28, 28, 1])
labels = ain.labels
dataset = tf.contrib.data.Dataset.from_tensor_slices((images, labels))
# 张量的嵌套元组:
dataset3 = tf.data.Dataset.zip((dataset1, dataset2))
# ⼀个集合.可命名元组或者⼀个字典映射字符串成张量
dataset = tf.data.Dataset.from_tensor_slices(
{"a": tf.random_uniform([4]),"b": tf.random_uniform([4, 100], maxval=100, dtype=tf.int32)})
读取数组
import tensorflow as tf
import numpy as np
# 创建dataset
dataset = tf.data.Dataset.from_tensor_slices(
np.array([1.0, 2.0, 3.0, 4.0, 5.0])
)#<DatasetV1Adapter shapes: (), types: tf.float64>
# 实例化了⼀个Iterator
iterator = dataset.make_one_shot_iterator()#<tensorflow.python.data.ops.iterator_ops.Iterator object at 0x000002016B501CC0> # 从iterator⾥取出⼀个元素
one_element = _next()# <tf.Tensor 'IteratorGetNext:0' shape=() dtype=float64>
with tf.Session() as sess:
for i in range(5):
print(sess.run(one_element))# 1.0
# 2.0
# 3.0
# 4.0
# 5.0
读取矩阵
ib.eager as tfe
import tensorflow as tf
import numpy as np
dataset = tf.data.Dataset.from_tensor_slices(
np.array([
[[1, 2, 3,],
[4, 5, 6]],
[[7, 8, 9,],
[10,11,12]]
])
)
print("dataset:",dataset)#<DatasetV1Adapter shapes: (2, 3), types: tf.int32>
for one_element in tfe.Iterator(dataset):
print(one_element)#tf.Tensor([1 2 3 4 5], shape=(5,), dtype=int32)
#tf.Tensor([6  7  8  9 10], shape=(5,), dtype=int32)
#tf.Tensor([11 12 13 14 15], shape=(5,), dtype=int32)
读取字典
ib.eager as tfe
import tensorflow as tf
import numpy as np
dataset = tf.data.Dataset.from_tensor_slices(
{
"a": np.array([[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]
]),  # 维度3x5
"b": np.array([1.0, 2.0, 3.0])  # 维度3x0,注意:第⼀维度3要与上⾯相同
}
)
print("dataset:",dataset)#<DatasetV1Adapter shapes: {a: (5,), b: ()}, types: {a: tf.int32, b: tf.float64}>
for one_element in tfe.Iterator(dataset):
print(one_element)#{'a': <tf.Tensor: id=9, shape=(5,), dtype=int32, numpy=array([1, 2, 3, 4, 5])>, 'b': <tf.Tensor: id=10, shape=(), dtype=float64, numpy= 1.0>}
# {'a': <tf.Tensor: id=13, shape=(5,), dtype=int32, numpy=array([ 6,  7,  8,  9, 10])>, 'b': <tf.Tensor: id=14, shape=(), dtype=float64, numpy=2.
0>}
# {'a': <tf.Tensor: id=17, shape=(5,), dtype=int32, numpy=array([11, 12, 13, 14, 15])>, 'b': <tf.Tensor: id=18, shape=(), dtype=float64, numpy= 3.0>}
⽂本⽂件:
filepaths = ["/var/", "/var/"]
dataset = tf.data.TextLineDataset(filepaths)
读取图⽚image
import tensorflow as tf
import glob
import os
# 函数的功能时将filename对应的图⽚⽂件读进来,并缩放到统⼀的⼤⼩
def _parse_function(filename,
):
image_string = tf.read_file(filename
)
image_decoded = tf.image.decode_bmp(image_string,
)
# 根据图⽚类型,选择以下函数
# image_decoded = tf.image.decode_png(image_string)
# image_decoded = tf.image.decode_jepg(image_string)
# image_decoded = tf.image.decode_git(image_string)
image_resized = size_images(image_decoded,
[64, 64]#图像维度变化
)
return image_resized
def walk_type(path, file_type):
paths = glob.glob(os.path.join(path,#存放图⽚的⽂件夹路径
file_type # ⽂件类型
)
)# path下所有file_type类型的⽂件的路径列表
return paths
paths = walk_type('dataset/*/','*.bmp')#图⽚路径列表
filenames = tf.constant(paths
)
dataset = tf.data.Dataset.from_tensor_slices((filenames))
dataset = dataset.map(_parse_function)
dataset = dataset.shuffle(buffer_size=1000).batch(1).repeat(10)
tfrecords⽂件:
filepaths = ["/data/file1.tfrecord", "/data/file2.tfrecord"]
dataset = tf.data.TFRecordDataset(filepaths)
⼆进制⽂件:
filepaths = [os.path.join(data_dir, 'data_batch_%d.bin' % i) for i in range(1, 6)]
image_bytes = image.height * image.width * image.depth
record_bytes = label_bytes + image_bytes
dataset = tf.data.FixedLengthRecordDataset(filepaths,record_bytes)
Datasets API⽀持⼀系列的变换操作
Datasets API⽀持 repeat、map、shuffle、batch等变换。
(1)repeat是将整个数据集重复多次,相当于⼀个或多个epoch,接受的参数数字代表repeat次数,若为空则⽆限重复
# Repeat infinitely.
dataset = tf.data.TFRecordDataset(filenames).repeat()
(2)map接收⼀个函数,Dataset中的每个元素都会被当作这个函数的输⼊,并将函数返回值作为新的Dataset。通常⽤于数据变换或者解析与编码⽂件数据。
def parser(self, serialized_example):
"""解析单个tf.Example变成图⽚和标签张量."""
features = tf.parse_single_example(
serialized_example,
features={
'image': tf.FixedLenFeature([], tf.string),
'label': tf.FixedLenFeature([], tf.int64),
})
image = tf.decode_raw(features['image'], tf.uint8)
image.set_shape([DEPTH * HEIGHT * WIDTH])
# 从[depth * height * width]变换维度到[depth, height, width].
image = tf.cast(
tf.float32)
label = tf.cast(features['label'], tf.int32)
# ⾃定义预处理
image = self.preprocess(image)
return image, label
dataset = dataset.map(self.parser, num_threads=batch_size, output_buffer_size=2 * batch_size)
def decode_csv(line):
parsed_line = tf.decode_csv(line, [[0.], [0.], [0.], [0.], [0]])
label = parsed_line[-1:] # 最后⼀个元素是label
del parsed_line[-1] # 删除最后⼀个元素
features = parsed_line # 所有的(除了最后⼀个元素)都是特性
d = dict(zip(feature_names, features)), label
return d
dataset = (tf.data.TextLineDataset(file_path) # 读⽂本⽂件
.skip(1) # 跳过标题⾏
.map(decode_csv)) # 通过应⽤decode_csv fn转换每个元素
(3)shuffle的功能为打乱dataset中的元素,它有⼀个参数buffersize,表⽰打乱时使⽤的buffer的⼤⼩。单位是以图⽚(张量)为单位,⽽不是byte;
# 可能的洗牌记录
if subset == 'train' or shuffle:
min_queue_examples = int(
Cifar10DataSet.num_examples_per_epoch(subset) * 0.4)
# 确保容量⾜够⼤,以提供良好的随机洗牌。
dataset = dataset.shuffle(buffer_size=min_queue_examples + 3 * batch_size)
(4)batch就是将多个元素组合成batch,接受⼀个batch_size的参数。
# Batch 组合
dataset = dataset.batch(batch_size)
迭代器
构建了表⽰输⼊数据的数据集之后,下⼀步是创建⼀个迭代器来访问来⾃该数据集的元素。Dataset API⽬前⽀持以下迭代器,以提⾼复杂程度:
one-shot :
⼀次性迭代器是迭代器的最简单形式,它只⽀持遍历数据集⼀次,不需要显式初始化。⼀次性迭代器 处理现有基于队列的输⼊管道⽀持的⼏乎所有情况 ,但是它们不⽀持参数化。
iterator = dataset.make_one_shot_iterator()
image_batch, label_batch = _next()
python怎么读取dat文件#返回image_batch label_batch
dataset = tf.data.Dataset.range(100)
iterator = dataset.make_one_shot_iterator()
next_element = _next()
for i in range(100):
value = sess.run(next_element)
assert i == value
initializable
可初始化迭代器要求您运⾏显式迭代器。在使⽤它之前的初始化操作。作为对这种不便的交换,它允许您使⽤⼀个或多个tf.placeholder()张量对数据集的定义进⾏参数化,当您初始化迭代器时可以提供这些张量。
max_value = tf.placeholder(tf.int64, shape=[])
dataset = tf.data.Dataset.range(max_value)
iterator = dataset.make_initializable_iterator()
next_element = _next()
# 在具有10个元素的数据集上初始化⼀个迭代器。
sess.run(iterator.initializer, feed_dict={max_value: 10})
for i in range(10):
value = sess.run(next_element)
assert i == value
# 在具有100个元素的数据集上初始化相同的迭代器。
sess.run(iterator.initializer, feed_dict={max_value: 100})
for i in range(100):
value = sess.run(next_element)
assert i == value
# 将训练数据加载到两个NumPy数组中
features = data["features"]
labels = data["labels"]
# 假设“features”的每⼀⾏都与“labels”对应
assert features.shape[0] == labels.shape[0]
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))
# ['dataset'上的其他转换…...]
dataset = ...
iterator = dataset.make_initializable_iterator()
sess.run(iterator.initializer, feed_dict={features_placeholder: features,
labels_placeholder: labels})
reinitializable