2.Tensorflow Dataset
1. from_tensor_slices 从tensor中切片建立数据集
1.x版本示例, 示例为1.2.0:
dataset = tf.data.Dataset.from_tensor_slices([1, 2, 3, 4, 5, 6, 7, 8, 9])
iterator = dataset.make_one_shot_iterator()
element = iterator.get_next()
with tf.Session() as sess:
for i in range(9):
print(sess.run(element), end='\t')
===============================================
1 2 3 4 5 6 7 8 9
dataset = tf.data.Dataset.from_tensor_slices(np.random.randint(0, 12, size=[3, 4]))
print(dataset.output_shapes, dataset.output_types)
iterator = dataset.make_one_shot_iterator()
element = iterator.get_next()
with tf.Session() as sess:
for i in range(3):
print(sess.run(element), end='\t')
====================================================
(4,) <dtype: 'int32'>
[5 8 5 6] [ 7 1 3 11] [0 7 2 0]
2.x版本示例, 示例为2.5.0:
dataset = tf.data.Dataset.from_tensor_slices([1, 2, 3, 4, 5, 6, 7, 8, 9])
for element in dataset:
print(element)
==========================================================================
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)
tf.Tensor(8, shape=(), dtype=int32)
tf.Tensor(9, shape=(), dtype=int32)
dataset = tf.data.Dataset.from_tensor_slices(np.random.randint(0, 12, size=[3, 4]))
for e in dataset:
print(e)
=======================================================================================
tf.Tensor([ 6 10 3 10], shape=(4,), dtype=int64)
tf.Tensor([4 5 4 0], shape=(4,), dtype=int64)
tf.Tensor([8 5 2 5], shape=(4,), dtype=int64)
从上面看出,
- 在1.x版本
from_tensor_slices 取元素是以第一个维度来从数据中取的,而且有 output_shapes 属性,是去掉第一维后的size。 - 在2.x版本
from_tensor_slices 使用更简单,跟1.x一样取元素,没有 output_shapes 属性。
注: 因为本人没有共用tf 1.x和2.x gpu版本的环境,这是不同环境测试的。
2. from_tensors 从tensor建立数据集
1.x 使用from_tensors ,这是将tensor作为一个整体来使用,这是 与from_tensor_slices 最大区别
dataset = tf.data.Dataset.from_tensors([1, 2, 3, 4, 5, 6, 7, 8, 9])
print(dataset.output_shapes, dataset.output_types)
iterator = dataset.make_one_shot_iterator()
element = iterator.get_next()
with tf.Session() as sess:
print(sess.run(element))
=============================================================================================
(9,) <dtype: 'int32'>
[1 2 3 4 5 6 7 8 9]
在2.x 中,使用更加简单:
dataset1 = tf.data.Dataset.from_tensors([1, 2, 3, 4, 5, 6, 7, 8, 9])
for e in dataset1:
print(e)
=======================================================================
tf.Tensor([1 2 3 4 5 6 7 8 9], shape=(9,), dtype=int32)
3. tf.data.Dataset.from_generator()
def from_generator(
generator,
output_types,
output_shapes=None,
args=None
)
该方法中,
generator :要求一个带yield关键字的迭代方法output_types : 输出types,一般最好指定,避免后续出错output_shapes : 输出shape,会自适应,一般默认,也可以指定args : 是generator 函数的参数
详细使用在后续使用中看到。
在1.2.0中,一般有两种使用方法,如下:
一是使用make_one_shot_iterator() ,逐步遗弃,2.x版本使用不了。
import tensorflow as tf
import numpy as np
def generator_func():
for i in range(100):
x = np.random.rand(28, 28)
y = np.random.randint(1, 10, size=1)
yield x, y
dataset = tf.data.Dataset.from_generator(generator_func, (tf.float32, tf.int32))
iterator = dataset.make_one_shot_iterator()
x, y = iterator.get_next()
with tf.Session() as sess:
print(sess.run(x), sess.run(y))
=====================================================
[[0.5423386 0.65143526 0.3766116 ]
[0.9540024 0.45769814 0.24270163]
[0.435695 0.7821666 0.07473102]] [8]
二是使用循环, 一般在2.x版本中使用。
import tensorflow as tf
import numpy as np
def generator_func():
for i in range(100):
x = np.random.rand(3, 3)
y = np.random.randint(1, 10, size=1)
yield x, y
dataset = tf.data.Dataset.from_generator(generator_func, (tf.float32, tf.int32))
for batch, (x, y) in enumerate(dataset):
print(batch)
print(x, y)
print(x.shape, y.shape)
break
==========================================================================
0
tf.Tensor(
[[0.16074419 0.2210305 0.45905504]
[0.2771892 0.22691838 0.47918117]
[0.8086647 0.30347258 0.7489832 ]], shape=(3, 3), dtype=float32) tf.Tensor([9], shape=(1,), dtype=int32)
(3, 3) (1,)
4. batch
def batch(self,
batch_size,
drop_remainder=False,
num_parallel_calls=None,
deterministic=None)
batch_size :从数据集中迭代获取batch的大小drop_remainder : 丢掉数据尾部,默认False。- 返回
dataset
2.5.0 版本官方例子:
dataset = tf.data.Dataset.range(8)
dataset = dataset.batch(3)
list(dataset.as_numpy_iterator())
==========================================================
[array([0, 1, 2]), array([3, 4, 5]), array([6, 7])]
dataset = tf.data.Dataset.range(8)
dataset = dataset.batch(3, drop_remainder=True)
list(dataset.as_numpy_iterator())
===========================================================
[array([0, 1, 2]), array([3, 4, 5])]
5.repeat
def repeat(self, count=None)
count :重复次数。
2.5.0 版本例子:
dataset = tf.data.Dataset.from_tensor_slices(np.random.randint(0, 6, size=[2, 3]))
dataset = dataset.repeat(3)
for i in list(dataset):
print(i)
====================================================================================
tf.Tensor([2 3 4], shape=(3,), dtype=int64)
tf.Tensor([3 0 0], shape=(3,), dtype=int64)
tf.Tensor([2 3 4], shape=(3,), dtype=int64)
tf.Tensor([3 0 0], shape=(3,), dtype=int64)
tf.Tensor([2 3 4], shape=(3,), dtype=int64)
tf.Tensor([3 0 0], shape=(3,), dtype=int64)
6. shuffle
def shuffle(self, buffer_size, seed=None, reshuffle_each_iteration=None) 其中:
buffer_size : 该方法会用数据集取填满buffer,再随机采样,所以最好是buffer_size >= data_size .reshuffle_each_iteration :每次迭代是否打乱,默认False打乱
dataset1 = tf.data.Dataset.from_tensor_slices(np.random.randn(2, 3))
dataset1 = dataset1.repeat(3)
dataset1 = dataset1.shuffle(buffer_size=10, reshuffle_each_iteration=False)
for i in list(dataset1):
print(i)
=======================================================================================
tf.Tensor([ 1.16431126 -0.66935843 0.3605916 ], shape=(3,), dtype=float64)
tf.Tensor([-0.5781084 -0.30355537 -0.07175025], shape=(3,), dtype=float64)
tf.Tensor([-0.5781084 -0.30355537 -0.07175025], shape=(3,), dtype=float64)
tf.Tensor([ 1.16431126 -0.66935843 0.3605916 ], shape=(3,), dtype=float64)
tf.Tensor([ 1.16431126 -0.66935843 0.3605916 ], shape=(3,), dtype=float64)
tf.Tensor([-0.5781084 -0.30355537 -0.07175025], shape=(3,), dtype=float64)
dataset1 = tf.data.Dataset.from_tensor_slices(np.random.randn(2, 3))
dataset1 = dataset1.repeat(3)
dataset1 = dataset1.shuffle(buffer_size=10, reshuffle_each_iteration=True)
for i in list(dataset1):
print(i)
=========================================================================================
tf.Tensor([ 0.06522093 -0.07025763 -0.17388337], shape=(3,), dtype=float64)
tf.Tensor([ 0.06522093 -0.07025763 -0.17388337], shape=(3,), dtype=float64)
tf.Tensor([ 0.80405422 -0.456626 -0.82905241], shape=(3,), dtype=float64)
tf.Tensor([ 0.80405422 -0.456626 -0.82905241], shape=(3,), dtype=float64)
tf.Tensor([ 0.80405422 -0.456626 -0.82905241], shape=(3,), dtype=float64)
tf.Tensor([ 0.06522093 -0.07025763 -0.17388337], shape=(3,), dtype=float64)
7. padded_batch
def padded_batch(self,
batch_size,
padded_shapes=None,
padding_values=None,
drop_remainder=False)
其中:
batch_size :每个batch从数据集中取的数据数目padded_shapes :pad后的shapepadding_values :拿什么值去pad,默认是0drop_remainder : 实际处理中N % batch_size 是否能整除代表最后一个batch数据是否足够,如果最后一个batch不够,不丢掉就设置False,默认不丢掉。
2.5.0 版本实例如下,假设有数据集A:
A = tf.data.Dataset.range(1, 6, output_type=tf.int32).map(lambda x: tf.fill([x], x))
for item in A.as_numpy_iterator():
print(item)
=====================================================================================
[1]
[2 2]
[3 3 3]
[4 4 4 4]
[5 5 5 5 5]
那么,padded_shapes 不设置或者置为[-1]都是按最大的size去pad:如下
B = A.padded_batch(2, padded_shapes = [-1])
for item in B.as_numpy_iterator():
print("#" * 20)
print(item)
====================================================================================
[[1 0]
[2 2]]
[[3 3 3 0]
[4 4 4 4]]
[[5 5 5 5 5]]
如果, padded_shapes 设置固定值,那么就都会拿pad_value来pad到固定长度
C = A.padded_batch(2, padded_shapes = [6])
for item in C.as_numpy_iterator():
print("*" * 20)
print(item)
============================================================================
********************
[[1 0 0 0 0 0]
[2 2 0 0 0 0]]
********************
[[3 3 3 0 0 0]
[4 4 4 4 0 0]]
********************
[[5 5 5 5 5 0]]
两个都设置如下, 来自:
D = A.padded_batch(2, padded_shapes=5, padding_values=-1)
for item in D.as_numpy_iterator():
print("*" * 20)
print(item)
================================
********************
[[ 1 -1 -1 -1 -1]
[ 2 2 -1 -1 -1]]
********************
[[ 3 3 3 -1 -1]
[ 4 4 4 4 -1]]
********************
[[5 5 5 5 5]]
实际使用过程中,我们需要自定义padded_shapes, padding_values ,例子如下:
elements = [([1, 2, 3], [10]),
([4, 5], [11, 12])]
datasets = tf.data.Dataset.from_generator(
lambda: iter(elements), (tf.int32, tf.int32))
datasets = datasets.padded_batch(2,
padded_shapes=([4], [None]),
padding_values=(-1, 100))
print(list(datasets.as_numpy_iterator()))
===================================================================
[(array([[ 1, 2, 3, -1],
[ 4, 5, -1, -1]], dtype=int32), array([[ 10, 100],
[ 11, 12]], dtype=int32))]
Inference
[1] tf2 Dataset
[1] TensorFlow2.0-dataset 这个只适用2.0 alpha版本
[2] tf.padded_batch
|