TensorFlow的数据读取机制

一、tensorflow读取机制图解

  首先需要思考的一个问题是,什么是数据读取?以图像数据为例,读取的过程可以用下图来表示  

  

  假设我们的硬盘中有一个图片数据集0001.jpg,0002.jpg,0003.jpg……我们只需要把它们读取到内存中,然后提供给GPU或是CPU进行计算就可以了。这听起来很容易,但事实远没有那么简单。事实上,我们必须要把数据先读入后才能进行计算,假设读入用时0.1s,计算用时0.9s,那么就意味着每过1s,GPU都会有0.1s无事可做,这就大大降低了运算的效率。

  如何解决这个问题?方法就是将读入数据和计算分别放在两个线程中,将数据读入内存的一个队列,如下图所示:  

  

  读取线程源源不断地将文件系统中的图片读入到一个内存的队列中,而负责计算的是另一个线程,计算需要数据时,直接从内存队列中取就可以了。这样就可以解决GPU因为IO而空闲的问题!

  而在tensorflow中,为了方便管理,在内存队列前又添加了一层所谓的“文件名队列”。

  为什么要添加这一层文件名队列?我们首先得了解机器学习中的一个概念:epoch。对于一个数据集来讲,运行一个epoch就是将这个数据集中的图片全部计算一遍。如一个数据集中有三张图片A.jpg、B.jpg、C.jpg,那么跑一个epoch就是指对A、B、C三张图片都计算了一遍。两个epoch就是指先对A、B、C各计算一遍,然后再全部计算一遍,也就是说每张图片都计算了两遍。

  tensorflow使用文件名队列+内存队列双队列的形式读入文件,可以很好地管理epoch。下面我们用图片的形式来说明这个机制的运行方式。如下图,还是以数据集A.jpg, B.jpg, C.jpg为例,假定我们要跑一个epoch,那么我们就在文件名队列中把A、B、C各放入一次,并在之后标注队列结束。

  

  程序运行后,内存队列首先读入A(此时A从文件名队列中出队):

  

  再依次读入B和C:

    

  

  此时,如果再尝试读入,系统由于检测到了“结束”,就会自动抛出一个异常(OutOfRange)。外部捕捉到这个异常后就可以结束程序了。这就是tensorflow中读取数据的基本机制。如果我们要跑2个epoch而不是1个epoch,那只要在文件名队列中将A、B、C依次放入两次再标记结束就可以了。

二、tensorflow读取数据机制的对应函数

  如何在tensorflow中创建上述的两个队列呢?

  对于文件名队列,我们使用tf.train.string_input_producer函数。这个函数需要传入一个文件名list,系统会自动将它转为一个文件名队列。

  此外tf.train.string_input_producer还有两个重要的参数,一个是num_epochs,它就是我们上文中提到的epoch数。另外一个就是shuffle,shuffle是指在一个epoch内文件的顺序是否被打乱。若设置shuffle=False,如下图,每个epoch内,数据还是按照A、B、C的顺序进入文件名队列,这个顺序不会改变:

  

  如果设置shuffle=True,那么在一个epoch内,数据的前后顺序就会被打乱,如下图所示:

  

  在tensorflow中,内存队列不需要我们自己建立,我们只需要使用reader对象从文件名队列中读取数据就可以了,具体实现可以参考下面的实战代码。

  除了tf.train.string_input_producer外,我们还要额外介绍一个函数:tf.train.start_queue_runners。初学者会经常在代码中看到这个函数,但往往很难理解它的用处,在这里,有了上面的铺垫后,我们就可以解释这个函数的作用了。

  在我们使用tf.train.string_input_producer创建文件名队列后,整个系统其实还是处于“停滞状态”的,也就是说,我们文件名并没有真正被加入到队列中(如下图所示)。此时如果我们开始计算,因为内存队列中什么也没有,计算单元就会一直等待,导致整个系统被阻塞。

  

  而使用tf.train.start_queue_runners之后,才会启动填充队列的线程,这时系统就不再“停滞”。此后计算单元就可以拿到数据并进行计算,整个程序也就跑起来了,这就是函数tf.train.start_queue_runners的用处。  

  

三、实战代码

  我们用一个具体的例子感受tensorflow中的数据读取。如图,假设我们在当前文件夹中已经有A.jpg、B.jpg、C.jpg三张图片,我们希望读取这三张图片5个epoch并且把读取的结果重新存到read文件夹中。

  

  对应的代码如下:

# 导入tensorflow
import tensorflow as tf 

# 新建一个Session
with tf.Session() as sess:
    # 我们要读三幅图片A.jpg, B.jpg, C.jpg
    filename = [‘A.jpg‘, ‘B.jpg‘, ‘C.jpg‘]
    # string_input_producer会产生一个文件名队列
    filename_queue = tf.train.string_input_producer(filename, shuffle=False, num_epochs=5)
    # reader从文件名队列中读数据。对应的方法是reader.read
    reader = tf.WholeFileReader()
    key, value = reader.read(filename_queue)
    # tf.train.string_input_producer定义了一个epoch变量,要对它进行初始化
    tf.local_variables_initializer().run()
    # 使用start_queue_runners之后,才会开始填充队列
    threads = tf.train.start_queue_runners(sess=sess)
    i = 0
    while True:
        i += 1
        # 获取图片数据并保存
        image_data = sess.run(value)
        with open(‘read/test_%d.jpg‘ % i, ‘wb‘) as f:
            f.write(image_data)

  我们这里使用filename_queue = tf.train.string_input_producer(filename, shuffle=False, num_epochs=5)建立了一个会跑5个epoch的文件名队列。并使用reader读取,reader每次读取一张图片并保存。

  运行代码后,我们得到就可以看到read文件夹中的图片,正好是按顺序的5个epoch:

   

  如果我们设置filename_queue = tf.train.string_input_producer(filename, shuffle=False, num_epochs=5)中的shuffle=True,那么在每个epoch内图像就会被打乱,如图所示:

   

  我们这里只是用三张图片举例,实际应用中一个数据集肯定不止3张图片,不过涉及到的原理都是共通的。

原文地址:https://www.cnblogs.com/xiaoyh/p/11701255.html

时间: 2024-10-07 16:21:07

TensorFlow的数据读取机制的相关文章

10 张图帮你搞定 TensorFlow 数据读取机制

导读 在学习tensorflow的过程中,有很多小伙伴反映读取数据这一块很难理解.确实这一块官方的教程比较简略,网上也找不到什么合适的学习材料.今天这篇文章就以图片的形式,用最简单的语言,为大家详细解释一下tensorflow的数据读取机制,文章的最后还会给出实战代码以供参考. 一.tensorflow读取机制图解 首先需要思考的一个问题是,什么是数据读取?以图像数据为例,读取数据的过程可以用下图来表示: 假设我们的硬盘中有一个图片数据集0001.jpg,0002.jpg,0003.jpg--我

十图详解TensorFlow数据读取机制(附代码)

http://geek.csdn.net/news/detail/201552 在学习TensorFlow的过程中,有很多小伙伴反映读取数据这一块很难理解.确实这一块官方的教程比较简略,网上也找不到什么合适的学习材料.今天这篇文章就以图片的形式,用最简单的语言,为大家详细解释一下TensorFlow的数据读取机制,文章的最后还会给出实战代码以供参考. TensorFlow读取机制图解 首先需要思考的一个问题是,什么是数据读取?以图像数据为例,读取数据的过程可以用下图来表示: 假设我们的硬盘中有一

『TensorFlow』数据读取类_data.Dataset

一.资料 参考原文: TensorFlow全新的数据读取方式:Dataset API入门教程 API接口简介: TensorFlow的数据集 二.背景 注意,在TensorFlow 1.3中,Dataset API是放在contrib包中的: tf.contrib.data.Dataset 而在TensorFlow 1.4中,Dataset API已经从contrib包中移除,变成了核心API的一员: tf.data.Dataset 此前,在TensorFlow中读取数据一般有两种方法: 使用p

TensorFlow的数据读取方法

Tensorflow一共提供了3种读取数据的方法:第一种方法个人感觉比较麻烦:在TensorFlow程序运行的每一步, 让Python代码来供给数据,比如说用PIL和numpy处理数据,然后输入给神经网络.第二种方法:从文件读取数据,在TensorFlow图的起始, 让一个输入管线从文件中读取数据:string_input_producer()和slice_input_producer(). 他们两者区别可以简单理解为:string_input_producer每次取出一个文件名.slice_i

tensorflow数据读取机制tf.train.slice_input_producer 和 tf.train.batch 函数

tensorflow中为了充分利用GPU,减少GPU等待数据的空闲时间,使用了两个线程分别执行数据读入和数据计算. 具体来说就是使用一个线程源源不断的将硬盘中的图片数据读入到一个内存队列中,另一个线程负责计算任务,所需数据直接从内存队列中获取. tf在内存队列之前,还设立了一个文件名队列,文件名队列存放的是参与训练的文件名,要训练 N个epoch,则文件名队列中就含有N个批次的所有文件名.而创建tf的文件名队列就需要使用到 tf.train.slice_input_producer 函数. tf

关于tensorflow 的数据读取线程管理QueueRunner

TensorFlow的Session对象是可以支持多线程的,因此多个线程可以很方便地使用同一个会话(Session)并且并行地执行操作.然而,在Python程序实现这样的并行运算却并不容易.所有线程都必须能被同步终止,异常必须能被正确捕获并报告,回话终止的时候, 队列必须能被正确地关闭. 所幸TensorFlow提供了两个类来帮助多线程的实现:tf.Coordinator和 tf.QueueRunner.从设计上这两个类必须被一起使用.Coordinator类可以用来同时停止多个工作线程并且向那

TensorFlow中数据读取之tfrecords

关于Tensorflow读取数据,官网给出了三种方法: 供给数据(Feeding): 在TensorFlow程序运行的每一步, 让Python代码来供给数据. 从文件读取数据: 在TensorFlow图的起始, 让一个输入管线从文件中读取数据. 预加载数据: 在TensorFlow图中定义常量或变量来保存所有数据(仅适用于数据量比较小的情况). 对于数据量较小而言,可能一般选择直接将数据加载进内存,然后再分batch输入网络进行训练(tip:使用这种方法时,结合yield 使用更为简洁,大家自己

pytorch数据读取

pytorch数据读取机制: sampler生成索引index,根据索引从DataSet中获取图片和标签 1.torch.utils.data.DataLoader 功能:构建可迭代的数据装在器 dataset:Dataset类,决定数据从哪读取及如何读取 batchsize:批大小 num_works:是否多进程读取数据,当条件允许时,多进程读取数据会加快数据读取速度. shuffle:每个epoch是否乱序 drop_last:当样本数不能被batchsize整除时,是否舍弃最后一批数据 D

Android 建立手机与手表数据同步机制总结

Android Wear 数据同步机制总结 当手机与手表建立蓝牙连接之后,数据就可以通过Google Play Service进行传输. 同步数据对象Data Item DataItem提供手机与手表数据存储的自动同步,一个DataItem对象由其创建者与路径组成的URI所确定.一个DataItem对象为手机和手表提供了一个数据通路,开发者通过改变指定的DataItem实现手机和手表的数据自动同步. 访问数据层API DataItem可以提供手机和手表数据的保存,改变该对象的操作则依赖数据层AP