在前面的内容中我们介绍了使用Tensorflow提供的一些函数来处理图像数据,比如旋转、增亮、锐化等等。尽管使用这些图像数据预处理方法可以在一定程度上减少无关因素对图像识别模型效果的影响,这些复杂的预处理过程仍会影响整个训练过程。 为了对大而多的图像数据做预处理,Tensorflow提供了队列加多线程处理输入数据的解决方案。在这之前我们先来学习一下Tensorflow中的队列。
数据队列
大家所熟悉的是队列(Queue)是一种先进先出的线性表数据结构,队列只允许在前端(Front)进行删除操作,在后端(Rear)进行插入操作。插入操作的一端称为队尾,删除操作的一端称为队头,如果里面不存在元素的话就称之为空队列。
Tensorflow提供了FIFOQueue和RandomShuffleQueue两种队列,其中前者就是实现一个先进先出的队列,后者实现的是一个随机队列,顺序是打乱的。
对于Tensorflow提供的队列,主要有三个函数:enqueue_many()、dequeue()和enqueue()可以修改,分别是初始化队列元素、把队首的第一个元素出队、把一个元素加入到队尾。
下面是实际操作的代码:
输出的结果是:
上面的程序展示了FIFOQueue函数的用法,下面我们再来讲一下RandomShuffleQueue函数。RandomShuffleQueue队列不是一个先进先出的队列,它会随机把队列中的函数打乱,每次出队列操作得到的都是从当前队列所有元素中随机选择出来的一个。如果我们需要随机抽取数据集中的数据来做训练时,RandomShuffleQueue就满足了我们的需求。RandomShuffleQueue入队列的方法与FIFOQueue一样,都是从队尾入队。RandomShuffleQueue函数的使用跟FIFOQueue一样,也是定义了enqueue_many()、dequeue()两个函数。实际上Tensorflow中的队列不仅仅是一种数据结构,我们可以创建多个线程,并实现这些线程同时向一个队列或多个队列中写入元素,接下来我们会讲一下如何把文件编制成队列。对于TFReord格式的文件而言,当数据量较大的时候可以把数据分成多个文件存储来提高处理效率。 一般会将同一个数据集的不同文件赋予相同的名称,并在名称的后面添加具有区分作用的数字后缀。以 MNIST 数据集的测试集图片数据为例, 我们使用封装TFRecord文件的方式将该文件封装成两个TFRecord文件—data_tfrecords-0-of-2和data_tfrecords-1-of-2,操作代码如下:
将文件组织成队列需要先使用 TensorFlow 的 train.match_filenames_once()函数来获取符合一个正则表达式的所有文件 。这个函数会返回一个文件列表,得到的文件列表可以通过 train.string_input__producer()函数进行有效的管理。train.string_input__producer()函数会使用初始化时提供的文件列表创建一个输入文件队列,函数创建的输入文件队列中的元素就是文件列表中的所有文件,这个队列可作为文件读取函数(如 TFRecorrdReader 类的 read()函数)的参数。
每次调用文件读取函数时,train.string_input__producer()函数会先判断当前是否己有打开的文件可读,如果没有己打开的文件或者打开的文件己经读完,这个函数会从输入队列中出队一个文件并从这个文件开始读取数据。
总结:本节的内容就到此结束了,主要是学习了Tensorflow中的队列。我们会在下一节的内容中讲一讲使用多线程处理数据。
关注小鲸融创,一起深度学习金融科技!