tensorflow import data

importing data:

  tf.data接口允许建立复杂的数据输入管道,距离在,图像模型的管道也许需要聚合分布在不同文件系统的图片,给每个图片随机干扰,并聚合,随机选取一批图像用于训练,对于文本模型,安德森,这个接口简化了处理大量数据,不同的数据格式,和复杂的转化。

   接口引入了两个新的抽象给tensorflow

tf.data.dataset表示一系列的元素,每个元素包含一个或者多个tensor类,例子:一个图像管道,一个元素可能是一个单独的训练样本,用一对儿tensor道标图像的数据和标签

创建dataset的两个不同的方法:要么从tensor里切片切出来,要么从别的dataset分块分出来

创建一个source:Dataset.from_tensor_slices(),从一个或者多个tensor类构建    

用transformation:Dataset.batch()构建一个数据集从一个或者多个 tf.data,Dataset类

Tf.data.iterator提供一个从dataset提取元素的主要方法,这种操作通过iterator.get_next()返回dataset中的下一元素,通常作为输入管道代码和模型的接口,这个简单的迭代器叫做one-shot iterator,循环访问一次dataset。

基本machanics

Guide的这个部分表述了建立dataset和iterator类的基本方法,以及如何从他们中提取数据。

为了开始一个输入管道,必须建立一个source.比如,从内存中建立DATASET的方法:tf.data.Dataset.from_tensors() or tf.data.Dataset.from_tensor_slices().

或者,如果你的输入数据实在硬盘上(并且是一种被推荐的TFRecord format格式),就可以构建一个

tf.data.TFRecordDataset

一旦有了Dataset类,就可以公国tf.data.Dataset类把他们转化成新的Dataset,例子:可以对每个element操作: Dataset.map(),或者多个element操作,Dataset.batch()。  Tf.data.Dataset,查看完整操作https://tensorflow.google.cn/api_docs/python/tf/data/Dataset

最常见的使用Dataset中数据的方法是用iterator类,迭代。可以一次提取dataset中的一个元素,(Dataset.make_one_shot_iterator())tf.data.Iterator提供两种操作:Iterator.initializer,让你能够初始化,重新初始化迭代器的情况。Iterator.get_next(),返回下一个元素,

Dataset 结构:

一个dataset中的数据由相同的结构,一个元素包含一个或者多个tensor类叫做components。每个组件(每个element中的tensor)都有tf.Dtype查看类型,tf.TensorShape将每个元素的静态形状输出,Dataset.output_types  Dataset.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,)))"
或者给每个component起个名(一个element里的component名字一样,因为他们的shape一样,type一样),用字典传给tensor_slices,这样在查看信息的时候就可以直接看到了

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,)}"
解释:dataset2中有两个element,一个是tf.random_uniform([4]),包含4个component,另一个是(【4,100】),每个component有100维。

Dataset类支持任何结构的datasets,Dataset.map(), Dataset.flat_map(), and Dataset.filter()转换去给每一个element转换,元素的结构决定函数的参数

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

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

# Note: Argument destructuring is notavailable in Python 3.
dataset3
=dataset3.filter(lambda x,(y, z):...)
创建一个iterator

一旦有了Dataset去代表你要输入的数据,下一就是创建一个迭代器去使用dataset中的elements.      tf.data结构现在支持以下iterators,越来月复杂:

One-shot, initializable , reinitializable , feedable

One-shot,迭代器是iterator中最简单的一种形式,只可以从dataset中迭代一次,不用初始化,可以支持几乎所有基于队列的输入管道,但是不支持参数化,

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
Note:Currently, one-shot iterators are the only type that is easily usable with an Estimator.

Initializable,用这种模式之前需要先初始化(初始化的时候不取值),通常使用方法是:获取数据集合dataset,在dataset里建立迭代器,创建next_element = iterator.get_next()

在运行session的时候先初始化迭代器,然后就可以用next_element了。

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 adataset 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 adataset 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

使用iterator中的值

Iterator.get_next()方法返回一个或者多个张量,对应于迭代器中的下一个元素,注意:这个方法并不直接更新迭代器,必须将其作为返回值传递给tf.Session.run()来使用下一个元素。如果迭代器到达了dataset的结尾,继续运行就会生成错误,跳出迭代,如果想用,需要重新初始化。通常是:

dataset = tf.data.Dataset.range(5)
iterator
=dataset.make_initializable_iterator()
next_element =iterator.get_next()

# Typically `result` will be theoutput of a model, or an optimizer's
# training operation.
result
= tf.add(next_element,next_element)

sess.run(iterator.initializer)
print(sess.run(result)) # ==> "0"
print(sess.run(result)) # ==> "2"
print(sess.run(result)) # ==> "4"
print(sess.run(result)) # ==> "6"
print(sess.run(result)) # ==> "8"
try:
  sess
.run(result)
except tf.errors.OutOfRangeError:
 
print("Endof dataset")  #==> "End of dataset"
放在try except

sess.run(iterator.initializer)
whileTrue:
 
try:
    sess
.run(result)
  except tf.errors.OutOfRangeError:
   
break
注意:一次迭代,迭代器里所有组建都会迭代。

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])))
dataset3
= tf.data.Dataset.zip((dataset1, dataset2))

iterator
=dataset3.make_initializable_iterator()

sess.run(iterator.initializer)
next1, (next2, next3) = iterator.get_next()
读取输入数据:

利用NumPy arrays

如果所有的数据都在内存里,创建dataset的最简单的办法就是把他们变为tensor类,然后用Dataset.from_tensor_slices().

: # Load the training data into two NumPy arrays, for example using`np.load()`.
with np.load("/var/data/training_data.npy")as data:
  features
=data["features"]
  labels
=data["labels"]

# Assume that each row of `features` ‎对应‎ tothe same row as `labels`.
assert features.shape[0]== labels.shape[0]

dataset
= tf.data.Dataset.from_tensor_slices((features,labels))
(载入数据,放入内存data,assert(程序你帮我确认啊,错了要告诉我啊!!)特征和标签个数相同,然后切片)对于小数据集比较好,但是消耗内存因为array的内容会copy很多次,最大容量2GB

这样的话可以用占位符代替变量,然后先不传入值,整个session设计好,初始化的时候再传入值。

# Load the training data intotwo NumPy arrays, for example using `np.load()`.
with np.load("/var/data/training_data.npy")as data:
  features
=data["features"]
  labels
=data["labels"]

# Assume that each row of `features`corresponds to the same row as `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))
# [Other transformations on`dataset`...]
dataset
= ...
iterator =dataset.make_initializable_iterator()

sess.run(iterator.initializer, feed_dict={features_placeholder: features,
                                        labels_placeholder: labels})

利用TFRecord data:

tf.data接口支持很多种文件格式,可以处理不适合放在内存里的数据,比如,TFRecord文件可是是一个简单的二进制格式,很多tensorflow都用它训练数据。Tf.data.TFRecordDataset类能帮你从一个或者多个TFRecord文件里读取数据。

# Creates a dataset that readsall of the examples from two files.
filenames
= ["/var/data/file1.tfrecord","/var/data/file2.tfrecord"]
dataset
= tf.data.TFRecordDataset(filenames)
这样的话可以直接从硬盘读取测试集和验证集,分别run就行了。

filenames = tf.placeholder(tf.string,shape=[None])
dataset
= tf.data.TFRecordDataset(filenames)
dataset
= dataset.map(...)  #Parse the record into tensors.
dataset
= dataset.repeat()  #Repeat the input indefinitely.
dataset
= dataset.batch(32)
iterator
=dataset.make_initializable_iterator()

# You can feed the initializer withthe appropriate filenames for the current
# phase of execution, e.g. trainingvs. validation.

# Initialize `iterator` with trainingdata.
training_filenames
= ["/var/data/file1.tfrecord","/var/data/file2.tfrecord"]
sess
.run(iterator.initializer, feed_dict={filenames: training_filenames})

# Initialize `iterator` withvalidation data.
validation_filenames
= ["/var/data/validation1.tfrecord",...]
sess
.run(iterator.initializer, feed_dict={filenames: validation_filenames})
读取文本数据,许多的数据集使用多个文本文件存储,tf.data.TextLineDataset会一行一行输出文件里的文版,可以用tf.placeholder(tf.string)输入数据。

filenames =["/var/data/file1.txt","/var/data/file2.txt"]
dataset
= tf.data.TextLineDataset(filenames)
可以使用filter函数过滤不需要的信息。

filenames =["/var/data/file1.txt","/var/data/file2.txt"]

dataset
= tf.data.Dataset.from_tensor_slices(filenames)

# Use `Dataset.flat_map()` totransform each file as a separate nested dataset,
# and then concatenate their contentssequentially into a single "flat" dataset.
# * Skip the first line (header row).
# * Filter out lines beginning with"#" (comments).
dataset
= dataset.flat_map(
    lambda filename:(
        tf
.data.TextLineDataset(filename)
       
.skip(1)
       
.filter(lambda line: tf.not_equal(tf.substr(line,0,1),"#"))))
用Dataset.map()处理数据。去处理dataset中的每一个element。

给出几个应用dataset.map的例子

分析协议缓冲区的messages

解码图像数据并改变大小。应用现实生活的图片处理图像数据的时候,把图像大小改成同样的大小是必要的。

# Reads an image from a file,decodes it into a dense tensor, and resizes it
# to a fixed shape.
def _‎分析‎_function(filename, label):
  image_string
= tf.read_file(filename)
  image_decoded = tf.image.decode_image(image_string)
  image_resized = tf.image.resize_images(image_decoded, [28,28])
 
return image_resized, label

# A vector of filenames.
filenames
= tf.constant(["/var/data/image1.jpg","/var/data/image2.jpg",...])

# `labels[i]` is the label for theimage in `filenames[i].
labels
= tf.constant([0,37,...])

dataset
= tf.data.Dataset.from_tensor_slices((filenames,labels))
dataset
= dataset.map(_parse_function)
利用tf.py_func()调用任意python逻辑

通常我们希望尽可能的用tensorflow的方式处理数据,但是有时候不可避免的需要调用额外的python第三方库。

import cv2

# Use a custom OpenCV function to readthe image, instead of the standard
# TensorFlow `tf.read_file()`operation.
def _read_py_function(filename, label):
  image_decoded
= cv2.imread(filename.decode(), cv2.IMREAD_GRAYSCALE)
  return image_decoded, label

# Use standard TensorFlow operationsto resize the image to a fixed shape.
def _resize_function(image_decoded, label):
  image_decoded
.set_shape([None,None,None])
  image_resized
= tf.image.resize_images(image_decoded, [28,28])
 
return image_resized, label

filenames
= ["/var/data/image1.jpg","/var/data/image2.jpg",...]
labels
= [0,37,29,1,...]

dataset
= tf.data.Dataset.from_tensor_slices((filenames,labels))
dataset
= dataset.map(
    lambda filename, label: tuple(tf.py_func(
        _read_py_function
, [filename, label], [tf.uint8, label.dtype])))
dataset = dataset.map(_resize_function)
批处理数据集元素

简单的batching:把连续n个elements合成一个:Dataset.batch()

inc_dataset = tf.data.Dataset.range(100)
dec_dataset
= tf.data.Dataset.range(0,-100,-1)
dataset
= tf.data.Dataset.zip((inc_dataset, dec_dataset))
batched_dataset
=dataset.batch(4)

iterator
=batched_dataset.make_one_shot_iterator()
next_element =iterator.get_next()

print(sess.run(next_element)) # ==> ([0, 1, 2,   3],  [ 0, -1,  -2,  -3])
print(sess.run(next_element)) # ==> ([4, 5, 6,   7],  [-4, -5,  -6,  -7])
print(sess.run(next_element)) # ==> ([8, 9, 10, 11],  [-8, -9, -10, -11])
分析:inc:[0,1,…,99] dec:[0,-1,-2,….,-99] dataset = (inc,dec)

batched_dataset=把dataset中element中的组件每4个组成一个batch

Batchingtensors with ‎填充,如果element的长度不同,需要用Dataset.padded_batch()

可以设置参数,把不同长度的输入数据合起来,短的就补全。

训练工作流/

 

处理多个epochs循环

最简单的方法就是用Dataset.repeat()。如果不传入参数就无限期循环

filenames =["/var/data/file1.tfrecord","/var/data/file2.tfrecord"]
dataset
= tf.data.TFRecordDataset(filenames)
dataset
= dataset.map(...)
dataset = dataset.repeat(10)
dataset
= dataset.batch(32)
如果想要在每次结束后看统计信息的话写一个训练循环

filenames =["/var/data/file1.tfrecord","/var/data/file2.tfrecord"]
dataset
= tf.data.TFRecordDataset(filenames)
dataset
= dataset.map(...)
dataset = dataset.batch(32)
iterator
=dataset.make_initializable_iterator()
next_element =iterator.get_next()

# Compute for 100 epochs.
for _ in range(100):
  sess
.run(iterator.initializer)
  whileTrue:
   
try:
      sess
.run(next_element)
    except tf.errors.OutOfRangeError:
     
break

 
#[Perform end-of-epoch calculations here.]
随机打乱数据:dataset.shuffle()参数buffer_size等于需要从dataset随机选的数量

filenames =["/var/data/file1.tfrecord","/var/data/file2.tfrecord"]
dataset
= tf.data.TFRecordDataset(filenames)
dataset
= dataset.map(...)
dataset = dataset.shuffle(buffer_size=10000)
dataset
= dataset.batch(32)
dataset
= dataset.repeat()
Using high-level APIs

 

 

总结:importingdata的方法:具体代码自己回头再找吧

数据载入需要考虑两个步骤,一建立dataset(原始数据存储的位置)二,iterator(迭代dataset中的数据)

Dataset包含N个element(一个特征,),每个element包含M个component(一个样本的一个特征,每个element中的数据类型需要相同)

Dataset获取的形式有两种:source,从内存或者硬盘中来;transformation,从原有dataset转变而来,

iterator是用来迭代数据的,也就是dataset放着所有的数据,具体操作的时候由iterator取来,送给模型。分4中,one-shot   initializable 还有其他两种。未完

数据读入流程:硬盘、内存、dataset、map\shuffle\batch\repeat、iterator(ont-shot不需要初始化,initializable,需要初始化)

filenames =["/var/data/file1.tfrecord","/var/data/file2.tfrecord"]
dataset
= tf.data.TFRecordDataset(filenames)
dataset
= dataset.map(...)
dataset = dataset.shuffle(buffer_size=10000)
dataset
= dataset.batch(32)
dataset
= dataset.repeat()


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值