概述
表示 一系列元素,其中每个元素包含一个或多个 Tensor 类型的对象
注意: Tensor是tensorflow内置对象
一句话解释: Dataset 相当于集合(其元素是 tensor),将读入的数据放入Dataset对象中,便于tensorflow训练、预测
官方网址:
https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/data/Dataset
优点
tf.data.Dataset,更方便的读取数据,而支持 多线程(进程) ,也在效率上获得了一定程度的提高。
使用tf.data.Dataset模块的pipline机制,可实现CPU多线程处理输入的数据,如读取图片和图片的一些的预处理,这样 GPU可以专注于训练过程,而 CPU去准备数据
注意
在使用Dataset时,由于Dataset无法获取内部数据的数量,所以模型调用fit()方法训练时,必须设置参数steps_per_epoch
如果有验证集,必须设置参数validation_steps
创建
语法:
tf.data.Dataset.from_tensor_slices(variant_tensor)
参数:
- variant_tensor :可以是list、dict、numpy
返回值
- Dataset对象
例子:通过一维list创建
dataset=tf.data.Dataset.from_tensor_slices([1,2,3,4,5,6,7])
print(dataset)
# item是tensor类型
for item in dataset:
print(item)
执行结果如下:
<TensorSliceDataset shapes: (), types: tf.int32>
tf.Tensor(1, shape=(), dtype=int32)
tf.Tensor(2, shape=(), dtype=int32)
tf.Tensor(3, shape=(), dtype=int32)
tf.Tensor(4, shape=(), dtype=int32)
tf.Tensor(5, shape=(), dtype=int32)
tf.Tensor(6, shape=(), dtype=int32)
tf.Tensor(7, shape=(), dtype=int32)
tensor类型转换成numpy类型
for item in dataset:
print(item.numpy())
执行结果如下:
1
2
3
4
5
6
7
例子:通过2个list创建
dataset=tf.data.Dataset.from_tensor_slices(([1,2,3,4,5,6,7],["赤","橙","黄","绿","青","蓝","紫"]))
for i,j in dataset:
print(i,"-",j,"-",j.numpy().decode("utf-8"))
例子:通过二维list创建
dataset=tf.data.Dataset.from_tensor_slices([[1,2],[3,4],[5,6]])
print(dataset)
执行结果如下:
<TensorSliceDataset shapes: (2,), types: tf.int32>
表示里面元素的长度是2
遍历元素,tensor类型:
for item in dataset:
print(item)
遍历元素,numpy类型:
for item in dataset:
print(item.numpy())
例子:通过dict创建
dataset=tf.data.Dataset.from_tensor_slices({
'a':[1,2,3],
'b':[4,5,6],
'c':[7,8,9]
})
print(dataset)
执行结果:
<TensorSliceDataset shapes: {a: (), b: (), c: ()}, types: {a: tf.int32, b: tf.int32, c: tf.int32}>
遍历
for item in dataset:
print(item)
执行结果如下:
{'a': <tf.Tensor: id=205, shape=(), dtype=int32, numpy=1>, 'b': <tf.Tensor: id=206, shape=(), dtype=int32, numpy=4>, 'c': <tf.Tensor: id=207, shape=(), dtype=int32, numpy=7>}
{'a': <tf.Tensor: id=211, shape=(), dtype=int32, numpy=2>, 'b': <tf.Tensor: id=212, shape=(), dtype=int32, numpy=5>, 'c': <tf.Tensor: id=213, shape=(), dtype=int32, numpy=8>}
{'a': <tf.Tensor: id=217, shape=(), dtype=int32, numpy=3>, 'b': <tf.Tensor: id=218, shape=(), dtype=int32, numpy=6>, 'c': <tf.Tensor: id=219, shape=(), dtype=int32, numpy=9>}
注意:遍历dict时,不能转换成numpy,否则报错
例子:通过numpy创建
# 通过ndarry创建
import numpy as np
database=tf.data.Dataset.from_tensor_slices(np.array([1,2,3,4,5,6,7]))
print(database)
for item in database:
print(item.numpy())
例子:复杂参数
train_ds=tf.data.Dataset.from_tensor_slices((train_names,(train_labels,train_acs,train_fms)))
例子中,参数更加复杂,传入tuple,第一个元素是 train_names,list类型;第二个元素也是tuple(称之为sec),该 sec 含有3个元素,每个元素也是list类型
详见:
https://www.malaoshi.top/show_1EF5NUEm0T3B.html
take()
根据当前dataset,创建一个dataset,新的dataset 包含 前count个元素
语法
dataset.take(count)
参数说明
- count:新的dataset包含前count个元素
返回值
- dataset对象
例子:
database=tf.data.Dataset.from_tensor_slices(np.array([1,2,3,4,5,6,7]))
for item in dataset.take(4):
print(item)
skip
根据当前dataset,创建一个dataset,新的dataset 跳过 count个元素
语法
skip(count)
参数
- count:整型
返回值
- dataset对象
shuffle()
随机重新排列此数据集的元素
语法:
shuffle(buffer_size)
参数
- buffer_size:将多少个元素打乱顺序。
一般设置为该dataset数据的个数
返回
- Dataset对象
例子
size=20
dataset=tf.data.Dataset.from_tensor_slices(list(range(size)))
dataset=dataset.shuffle(size)
for item in dataset:
print(item.numpy())
repeat()
将整个序列重复n次
一般用于训练模型时,epoch循环的次数
注意:一般在 shuffle()后面执行
语法
repeat(count=None)
参数
- count:可选,tf.int64标量tf.Tensor,表示应重复数据集的 次数。
默认为None,为None或-1表示无限重复
返回
- Dataset对象
例子
size=10
dataset=tf.data.Dataset.from_tensor_slices(list(range(size)))
dataset=dataset.repeat(2)
for item in dataset:
print(item.numpy())
batch()
将 batch_size 个元素组合成每一个batch
调用此方法返回的 dataset 类型会改变
shape会改变 ,增加1个维度,表示 数量
在读取图片时,由于图片体积较大,不可能一次将所有图片读入到内存中,而是 分批次 的读取
语法
batch(batch_size)
参数
- batch_size:每一批次 合并的元素数量。
根据机器内存大小和数据进行设置
返回值
Dataset 对象
例子
size=10
dataset=tf.data.Dataset.from_tensor_slices(list(range(size)))
print(dataset)
# 每3个元素组成一个batch
dataset2=dataset.batch(3)
print(dataset2)
for item in dataset2:
print(item.numpy())
执行结果:
<TensorSliceDataset shapes: (), types: tf.int32>
<BatchDataset shapes: (None,), types: tf.int32>
[0 1 2]
[3 4 5]
[6 7 8]
[9]
执行batch()后,dataset的类型改变了,shape改变了
map()
map接收一个函数,Dataset中的每个元素都会被当作这个函数的输入,并将函数返回值 组成 新的Dataset
该方法支持 多个CPU并行 预处理。通过参数num_parallel_calls指定并行数量
python内置函数map() 功能相同
语法
map(map_func,num_parallel_calls=None)
参数
- map_func:函数,dataset中的每一个元素传入到该函数中,并将返回结果放回到dataset中
- num_parallel_calls:整型数字。表示要并行异步处理的线程数
- 如果未指定,则将按顺序处理元素。
- 如果设置成
tf.data.experimental.AUTOTUNE,根据可用的CPU,自动设置并行的数量。
num_parallel_calls参数是为了提高map()方法的处理速度, 使用并行处理,tf.data.experimental.AUTOTUNE可以让程序自动的选择最优的线程并行个数
返回值
- Dataset对象
例子:将原始元素放大二倍
def fun(x):
return x*2
size=10
dataset=tf.data.Dataset.from_tensor_slices(list(range(size)))
dataset=dataset.map(fun)
for item in dataset:
print(item.numpy())
zip()
此功能与python内置的zip()函数一样
将2个dataset,对应元素打包成一个元祖
语法
@staticmethod
zip(datasets)
参数
- datasets:dataset对象
返回值
- Dataset对象
例子
size=10
dataset1=tf.data.Dataset.from_tensor_slices(list(range(size)))
dataset2=tf.data.Dataset.from_tensor_slices(list(range(size,20)))
dataset=tf.data.Dataset.zip((dataset1,dataset2))
for item in dataset:
print(item[0].numpy(),item[1].numpy())
prefetch()
效率问题
执行训练时,先提取、处理数据,然后在GPU(TPU)上训练模型。
当 CPU 正在准备数据时,GPU(TPU)则处于空闲状态。
当GPU(TPU)训练模型时,CPU 则处于空闲状态。
因此,训练步骤时间是 CPU 预处理时间和加速器训练时间的总和。
如下图:
Pipeline机制
prefetch()
该方法提供了 software pipelining 机制。该函数解耦了 数据产生的时间 和 数据消耗的时间。
该函数有 一个后台线程 和 一个内部缓存区,在数据被请求前,就从 dataset 中 预加载一些数据(进一步提高性能)。
注意: prefech() 一般作为 最后一个转换
语法
prefetch(buffer_size)
参数
- buffer_size:整数或tf.int64的tf.Tensor,预先提取元素的数量
如果设置成tf.data.experimental.AUTOTUNE,根据可用的CPU,自动设置最佳数量。
返回
- Dataset
感谢:
https://blog.csdn.net/guyuealian/article/details/85106012

