Reading data

基础知识

https://zhuanlan.zhihu.com/p/27238630

很好的讲解文章,了解了文件名队列

https://hk.saowen.com/a/ba8b012d8c6505b401c36a12c9cbd6d63db4d2a7d3d97abda4ca18133a6bf72b

讲解了decode_raw和FixedLengthRecordReader搭配使用

所有方式

第二和第三种的区别方式在于前一种需要自己每次循环中设置数据,第三种无需指定。

而第一种方式是最新的方法,代码中使用的则是第三种方式。

There are four methods of getting data into a TensorFlow program:

  • tf.data API: Easily construct a complex input pipeline. (preferred method)

  • Feeding: Python code provides the data when running each step.

  • QueueRunner: a queue-based input pipeline reads the data from files at the beginning of a TensorFlow graph.

  • Preloaded data: a constant or variable in the TensorFlow graph holds all the data (for small data sets).

生成tfrecords-bert中最新的生成方式:

数据写入 .tfrecords 文件,需要将每一个样本数据封装为tf.train.Example格式,再将Example逐个写入文件。Example格式中的数据基础类型是tf.train.Feature。

基础数据格式

三种基础数据类型:bytes,float,int64

对应tf.train中三种类型:BytesList (字符串列表), FloatList (浮点数列表), Int64List (64位整数列表),构造它们三个依照下面的方式传入相对应的value。

example 协议格式

要将我们的数据写入 .tfrecords 文件,需要将每一个样本数据封装为tf.train.Example格式,再将Example逐个写入文件。Example格式中的数据基础类型是tf.train.Feature

tf.train.Feature(): 它的参数是BytesList, FloatList, Int64List三种

tf.train.Features: 它的参数是一个字典,k-v对中 v 的类型是Feature,对应每一个字段。

tf.train.FeatureList: 它的参数是一个Feature的list, [Feature1, Feature2,...]

tf.train.FeatureLists: 它的参数是一个字典,k-v对中 v 的类型是FeatureList。

我们需要根据我们的数据,找到每一个字段应该映射为 Feature或FeatureList, 多个Feature组成Features,多个FeatureList组成FeatureLists, 然后我们就定义了我们的一个训练数据对应的 Features,FeatureLists, 再将其封装为 tf.train.Example 就可以写入 tfrecords二进制文件了。

这样就需要选择使用Example还是SequenceExample, SequenceExample多了一个featurelists, 也就是说如果数据中存在字段,我们把它映射为了FeatureList而不是Feature, 那么就要用SequenceExample, 否则用Example。

那么什么样的数据需要映射为FeatureList或Feature?

我的理解是对于长度固定的字段类型,映射为Feature, 比如分类问题中的类别这个字段一般用一个数字表示,二分类就是0或1,那么就class=0映射为tf.train.Feature(tf.train.Int64List(value=[0])), 只要这个字段包含的数据维度是固定的,就可以封装为 Feature。

对于长度不固定的字段类型,映射为FeatureList。比如NLP样本有一个特征是一句话,那么一句话的长度是不固定的,NLP中一般是先分词,然后把每个词对应为该词在字典中的索引,一句话就用一个一维整形数组来表示 [2, 3, 5, 20, ...],这个数组的长度是不固定的,我们就映射为

读取tfrecords-bert中最新的读取方式:

  • 读入所有的tfrecord文件,组成列表传入dataset = tf.data.TFRecordDataset(filename)

  • 利用函数的方式进行处理dataset = dataset.map(decode),对其中每一个图片文件名进行处理,返回的也只是一个样本。注意这里虽然没有对所有样本循环,我猜测是流式隐循环;

    然后设置shuffle(不用考虑min_after_dequeue和num_threads),repeat和batch或apply(tf.contrib.data.batch_and_drop_remainder(batch_size))

  • 定义解析函数:

  • parse_single_example将之前的A scalar string Tensor, a single serialized Example转变成张量。返回:A dict mapping feature keys to Tensor and SparseTensor values.

  • 其中FixedLenFeature表示Configuration for parsing a fixed-length input feature,J理解为怎么从protocol buffer中以怎样的格式结束数据。

QueueRunner

J总结一下该方式的整体思路:

查看具体数据的演示代码

如果需要查看具体的数据可使用下列代码

Warning: This section discusses implementing input pipelines using the queue-based APIs which can be cleanly replaced by the tf.data API.

A typical queue-based pipeline for reading records from files has the following stages:

  1. The list of filenames

  2. Optional filename shuffling

  3. Optional epoch limit

  4. Filename queue

  5. A Reader for the file format

  6. A decoder for a record read by the reader

  7. Optional preprocessing

  8. Example queue

Filenames, shuffling, and epoch limits

For the list of filenames, use either a constant string Tensor (like ["file0", "file1"] or [("file%d" % i) for i in range(2)]).

Pass the list of filenames to the tf.train.string_input_producer function.string_input_producer creates a FIFO queue for holding the filenames until the reader needs them.

Reader

Select the reader that matches your input file format and pass the filename queue to the reader's read method. The read method outputs a key identifying the file and record (useful for debugging if you have some weird records), and a scalar string value. Use one (or more) of the decoder and conversion ops to decode this string into the tensors that make up an example.

J即返回(key, value),其中value就是serialized_example,因为是scalar string(字符串),所以需要进一步解析成为tensor。

Standard TensorFlow format

J对于tfrecord格式,单独一个则用tf.data.TFRecordDataset,多个文件的话,使用队列,则用tf.TFRecordReader。J我认为这里我搞错了,其实tfrecorddataset也可以,而且输入的也不是多文件(不是多个tfrecord文件)。

Another approach is to convert whatever data you have into a supported format. This approach makes it easier to mix and match data sets and network architectures. The recommended format for TensorFlow is a TFRecords file containing tf.train.Example protocol buffers (which containFeatures as a field). You write a little program that gets your data, stuffs it in an Example protocol buffer, serializes the protocol buffer to a string, and then writes the string to a TFRecords file using the tf.python_io.TFRecordWriter. For example,tensorflow/examples/how_tos/reading_data/convert_to_records.py converts MNIST data to this format.

The recommended way to read a TFRecord file is with a tf.data.TFRecordDataset, as in this example:

To accomplish the same task with a queue based input pipeline requires the following code (using the same decode function from the above example):

其中的reader方法:Returns the next record (key, value) pair produced by a reader.

Will dequeue a work unit from queue if necessary (e.g. when the Reader needs to start reading from a new file since it has finished with the previous file).

J也就是意思说read每次产生一个新的样本,而非新的tfrecord file文件。见原文The read method outputs a key identifying the file and record (useful for debugging if you have some weird records), and a scalar string value.

这里最大的误会可能就在于没有循环,因而以为是读取了整个tfrecord的file文件,J实际上是隐循环,因为下面的decode肯定是对每一个图像进行解析的,因而读取的是样本级,而非文件级。

Decode

Jparse_single_example将之前的A scalar string Tensor, a single serialized Example转变成张量。返回:A dict mapping feature keys to Tensor and SparseTensor values.

其中FixedLenFeature表示Configuration for parsing a fixed-length input feature,J理解为怎么从protocol buffer中以怎样的格式结束数据。

而decode_raw表示Reinterpret the bytes of a string as a vector of numbers,就是将字符串解析为数值,J猜测上一步只是按照什么格式去读,但是读出来还是字符串,需要转换。

To read a file of TFRecords, use tf.TFRecordReader with the tf.parse_single_example decoder. The parse_single_example op decodes the example protocol buffers into tensors.

Preprocessing

tf.image.per_image_standardization:Linearly scales image to have zero mean and unit norm.

Batching

At the end of the pipeline we use another queue to batch together examples for training, evaluation, or inference. For this we use a queue that randomizes the order of examples, using thetf.train.shuffle_batch.

J这里有等待前面样本凑够了一批的含义。之前read是每个样本读出来后操作,虽然这里batch传入的参数还是单个样本的符号,比如下面的[example, label],但是这个函数会负责后面生成batch的操作,所以不用担心。

tf.train.shuffle_batch是将队列中数据打乱后,再读取出来,因此队列中剩下的数据也是乱序的,队头也是一直在补充(我猜也是按顺序补充),比如batch_size=5,capacity=10,min_after_dequeue=5,

初始是有序的0,1,..,9(10条记录),

然后打乱8,2,6,4,3,7,9,2,0,1(10条记录),

队尾取出5条,剩下7,9,2,0,1(5条记录),

然后又按顺序补充进来,变成7,9,2,0,1,10,11,12,13,14(10条记录),

再打乱13,10,2,7,0,12...1(10条记录),

再出队...

capacity可以看成是局部数据的范围,读取的数据是基于这个范围的,

在这个范围内,min_after_dequeue越大,数据越乱。

这样按batch读取的话,最后会自动在前面添加一个维度,比如数据的维度是[1],batch_size是10,那么读取出来的shape就是[10,1] 。J就是第一个是batch_size的维度。

Creating threads to prefetch using QueueRunner objects

上面的tf.train的函数都会产生QueueRunner对象,其存储了对于队列的相关操作。Holds a list of enqueue operations for a queue, each to be run in a thread.需要调用start_queue_runners启动这些QueueRunner对象才能操作。而QueueRunner需要配合Coordinator处理其队列可能出现的error。

示例代码为:

实例代码为:

tf.data

查看具体数据的演示代码

可以考虑像上一个一样,设置较小的batch,然后sess.run就可以打印出。

代码

数据增强

基本代码

基础知识

对比度,饱和度,色相,亮度

J因而根据分析,一般色相不去动(颜色就变了),明度和饱和度去动(因为可能环境会有灯光影响),对比度就不动了(默认最亮颜色和最暗间的阶层是不变的)。

对比度,则表示指图像的最亮部分与最暗部分亮度的比值。

色相:色彩的相貌。我们常说的 红色黄色橙色绿色蓝色。。这些就是对色相的一个描述。

明度:色彩的明亮程度。我们可以通俗的理解成,这个颜色加了多少白颜料,加了多少黑颜料。

纯度:色彩的饱和度。从左至右,纯度由高变低。纯度越高,颜色越正,越容易分辨。所以我们在日常生活中看到的那些 一眼看不出是什么颜色的颜色大致就是纯度低的颜色。

参数设置

测试代码

Reference

Last updated

Was this helpful?