目录
1.dataset from tensor(dataset.from_)
(1)from_tensors
(2)from_tensor_slices
(3)from_generator
2.dataset apply function(dataset.apply(func)/map)
3.dataset as numpy iterator(dataset.as_numpy_iterator())
4.dataset.filter(func)
5.batch
6.flat_map
7.enumerate
8.reduce
9.repeat
10.shard
11.shuffle
12.skip
13.take
14.unbatch
创建Dataset的三个关键步骤或用法:
1. Create a source dataset from your input data. 根据输入数据创建源dataset 2. Apply dataset transformations to preprocess the data. 应用transformations处理数据 3. Iterate over the dataset and process the elements. 迭代处理dataset与elements
Iteration happens in a streaming fashion, so the full dataset does not need to fit into memory.
迭代以流方式进行,因此整个数据集不需要放入内存中。
从这里可以看出差别:
from_tensors:组合输入并将数据集与单个元素一起返回
from_tensor_slices:为输入张量的每一行创建一个带有单独元素的数据集
而我们一般用第二种——from_tensor_slices
from_generator( generator, output_types, output_shapes=None, args=None)
def tensor_generator(): tensor = tf.constant([[1,2,3,4],[2,3,4,5]]) for i in tensor: yield i dataset_generator = tf.data.Dataset.from_generator(tensor_generator,(tf.uint8)) list(dataset_generator) """ [<tf.Tensor: shape=(4,), dtype=uint8, numpy=array([1, 2, 3, 4], dtype=uint8)>, <tf.Tensor: shape=(4,), dtype=uint8, numpy=array([2, 3, 4, 5], dtype=uint8)>] """结果好像与直接iter一样:但from_generator可以指定type与shape
tensor = tf.constant([[1,2,3,4],[2,3,4,5]]) tensor_iter = iter(tensor) list(tensor_iter) """ [<tf.Tensor: shape=(4,), dtype=int32, numpy=array([1, 2, 3, 4], dtype=int32)>, <tf.Tensor: shape=(4,), dtype=int32, numpy=array([2, 3, 4, 5], dtype=int32)>] """也可以直接map
dataset = tf.data.Dataset.from_tensor_slices([[1,2,3,4],[2,3,4,5]]) for i in dataset_tensor_slices: print(i) """ tf.Tensor([1 2 3 4], shape=(4,), dtype=int32) tf.Tensor([2 3 4 5], shape=(4,), dtype=int32) """ dataset = map(lambda x:x**2,dataset) for i in dataset: print(i) """ tf.Tensor([ 1 4 9 16], shape=(4,), dtype=int32) tf.Tensor([ 4 9 16 25], shape=(4,), dtype=int32) """ dataset = tf.data.Dataset.from_tensor_slices([[1,2,3,4],[2,3,4,5]]) dataset = dataset.map(lambda x:x**2) list(dataset) """ [<tf.Tensor: shape=(4,), dtype=int32, numpy=array([ 1, 4, 9, 16], dtype=int32)>, <tf.Tensor: shape=(4,), dtype=int32, numpy=array([ 4, 9, 16, 25], dtype=int32)>] """下面是官网的代码:
dataset = tf.data.Dataset.from_tensor_slices([1, 2, 3]) dataset = dataset.filter(lambda x: x < 3) list(dataset.as_numpy_iterator()) # `tf.math.equal(x, y)` is required for equality comparison def filter_fn(x): return tf.math.equal(x, 1) dataset = dataset.filter(filter_fn) list(dataset.as_numpy_iterator()) """ [1] """注意到,这里只是进行了一维的判断,当我试着进行二维判断的时候,出现了许许多多错误,简直要抓狂了,发现dataset与tensor还不是那么一回事,有许许多多的问题,现在还不是很了解,以后如果有见解的话在这里继续补充(反正面对各种报错,简直是要疯了!!)。
但事是必须要去完成的。
回头来再度filter的使用要求,重新审视了一下Return:
The Dataset containing the elements of this dataset for which predicate is True.
返回dataset中elements符合predicate的元素!
是elements中符合的元素!
当dataset是一维的时候,elements为tensor,当二维时,elements 同样是tensor:
一维:
x = tf.data.Dataset.from_tensor_slices([1,2,3,4]) for i in x: print(i) print(i==1) print(tf.math.equal(i,1)) """ tf.Tensor(1, shape=(), dtype=int32) tf.Tensor(True, shape=(), dtype=bool) tf.Tensor(True, shape=(), dtype=bool) tf.Tensor(2, shape=(), dtype=int32) tf.Tensor(False, shape=(), dtype=bool) tf.Tensor(False, shape=(), dtype=bool) tf.Tensor(3, shape=(), dtype=int32) tf.Tensor(False, shape=(), dtype=bool) tf.Tensor(False, shape=(), dtype=bool) tf.Tensor(4, shape=(), dtype=int32) tf.Tensor(False, shape=(), dtype=bool) tf.Tensor(False, shape=(), dtype=bool) """二维:
x = tf.data.Dataset.from_tensor_slices([[1,2,3,4],[1,2,3,4]]) for i in x: print(i) print(i==1) print(tf.math.equal(i,1)) """ tf.Tensor([1 2 3 4], shape=(4,), dtype=int32) tf.Tensor([ True False False False], shape=(4,), dtype=bool) tf.Tensor([ True False False False], shape=(4,), dtype=bool) tf.Tensor([1 2 3 4], shape=(4,), dtype=int32) tf.Tensor([ True False False False], shape=(4,), dtype=bool) tf.Tensor([ True False False False], shape=(4,), dtype=bool) """这里面单独测试都没问题,但是直接将能够返回多维的predicate传入到filter中,就会出错。
也就是说,filter每次只接收关于单独element的bool逻辑谓词。
在return内部无法做for循环,只能在外面先将dataset分解,逐个element传入filter:
x = tf.data.Dataset.from_tensor_slices([[1,2,3,4],[1,2,3,4]]) def func(x): return tf.math.equal(x,1) l = [] for i in x: i = tf.data.Dataset.from_tensor_slices(i) a = i.filter(func) b = a.as_numpy_iterator() l.append(list(b)) """ l:[[1], [1]] """主要是自己对tensor与dataset的分别不是太清楚,tensor可以直接返回多维的bool,这里不行,只能逐个进行,预计关于filter的其他逻辑函数也是如此,这里暂且记下,如果后续有更多的了解,再进行补全,如果你有更好的做法,告诉我一下也行!
将数据进行分割,每部分有batch个数据,是否抛弃最后不足的部分由
drop_remainder=True/False 决定
这个很简单,但是在使用过程中,发现了一个问题:
([1,2,3],[2,3,4])与[[1,2,3],[2,3,4]]在创建dataset中是不一样的,但是在创建tensor中是一样的。
dataset认为([1,2,3],[2,3,4])是两个张量,[[1,2,3],[2,3,4]]是一个张量
tensor认为二者都是一个张量
dataset = tf.data.Dataset.from_tensor_slices([[1,2,3,4],[2,3,4,5],[2,3,4,5]]) dataset = dataset.batch(2,drop_remainder=False) list(dataset.as_numpy_iterator()) """ [array([[1, 2, 3, 4], [2, 3, 4, 5]], dtype=int32), array([[2, 3, 4, 5]], dtype=int32)] """ dataset = tf.data.Dataset.from_tensor_slices(([1,2,3,4],[2,3,4,5],[2,3,4,5])) dataset = dataset.batch(2,drop_remainder=False) list(dataset.as_numpy_iterator()) """ 结果是多通道的batch(如本例的3维,3通道,取3通道的Batch数据) [(array([1, 2], dtype=int32), array([2, 3], dtype=int32), array([2, 3], dtype=int32)), (array([3, 4], dtype=int32), array([4, 5], dtype=int32), array([4, 5], dtype=int32))] """所以,tensorflow就很烦~
映射展平
dataset = tf.data.Dataset.from_tensor_slices( [[1, 2, 3], [4, 5, 6], [7, 8, 9]]) dataset = dataset.flat_map(lambda x: Dataset.from_tensor_slices(x)) list(dataset.as_numpy_iterator())Creates a Dataset that includes only 1/num_shards of this dataset.
A = tf.data.Dataset.range(10) B = A.shard(num_shards=3, index=0) list(B.as_numpy_iterator()) """ [0,3,6,9] """ C = A.shard(num_shards=3, index=1) list(C.as_numpy_iterator()) """ [1,4,7] """ D = A.shard(num_shards=3, index=2) list(D.as_numpy_iterator()) """ [2,5,8] """Randomly shuffles the elements of this dataset.
dataset = tf.data.Dataset.range(3) dataset = dataset.shuffle(3, reshuffle_each_iteration=True) dataset = dataset.repeat(2) # doctest: +SKIP """ 不指定种子,每次不同 [1,0,2,1,2,0] """ dataset = tf.data.Dataset.range(3) dataset = dataset.shuffle(3, reshuffle_each_iteration=False) dataset = dataset.repeat(2) # doctest: +SKIP """ 不指定种子,每次相同 [1,0,2,1,0,2] """Creates a Dataset that skips count elements from this dataset.
dataset = tf.data.Dataset.range(10) dataset = dataset.skip(7) list(dataset.as_numpy_iterator()) """ [7,8,9] """Creates a Dataset with at most count elements from this dataset.
我看起来像是从头开始算count
dataset = tf.data.Dataset.range(10) dataset = dataset.take(3) list(dataset.as_numpy_iterator()) """ [0,1,2] """Splits elements of a dataset into multiple elements.
类似于展平,flatten?
elements = [ [1, 2, 3], [1, 2], [1, 2, 3, 4] ] dataset = tf.data.Dataset.from_generator(lambda: elements, tf.int64) dataset = dataset.unbatch() list(dataset.as_numpy_iterator()) """ [1,2,3,1,2,1,2,3,4] """