在学习tensorflow的过程中,读取数据这一块很难理解。确实这一块官方的教程比较简略,网上也找不到什么合适的学习材料。今天这篇文章就以图片的形式,用最简单的语言,为大家详细解释一下tensorflow的数据读取机制,文章的最后还会给出实战代码以供参考。

一、tensorflow读取机制图解

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

假设我们的硬盘中有一个图片数据集0001.jpg,0002.jpg,0003.jpg……我们只需要把它们读取到内存中,然后提供给GPU或是CPU进行计算就可以了。这听起来很容易,但事实远没有那么简单。

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

读取线程源源不断地将文件系统中的图片读入到一个内存的队列中,而负责计算的是另一个线程,计算需要数据时,直接从内存队列中取就可以了。这样就可以解决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文件夹中。

对应的代码如下:

  1. # 导入tensorflow
  2. import tensorflow as tf
  3. # 新建一个Session
  4. with tf.Session() as sess:
  5. # 我们要读三幅图片A.jpg, B.jpg, C.jpg
  6. filename = ['A.jpg', 'B.jpg', 'C.jpg']
  7. # string_input_producer会产生一个文件名队列
  8. filename_queue = tf.train.string_input_producer(filename, shuffle=False, num_epochs=5)
  9. # reader从文件名队列中读数据。对应的方法是reader.read
  10. reader = tf.WholeFileReader()
  11. key, value = reader.read(filename_queue)
  12. # tf.train.string_input_producer定义了一个epoch变量,要对它进行初始化
  13. tf.local_variables_initializer().run()
  14. # 使用start_queue_runners之后,才会开始填充队列
  15. threads = tf.train.start_queue_runners(sess=sess)
  16. i = 0
  17. while True:
  18. i += 1
  19. # 获取图片数据并保存
  20. image_data = sess.run(value)
  21. with open('read/test_%d.jpg' % i, 'wb') as f:
  22. 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内图像就会被打乱,如图所示:

  1. # 导入tensorflow
  2. import tensorflow as tf
  3. # 新建一个Session
  4. with tf.Session() as sess:
  5. # 我们要读三幅图片A.jpg, B.jpg, C.jpg
  6. filename = ['./data/A.png', './data/B.png', './data/C.png']
  7. # string_input_producer会产生一个文件名队列
  8. filename_queue = tf.train.string_input_producer(filename, shuffle=True, num_epochs=5)
  9. # reader从文件名队列中读数据。对应的方法是reader.read
  10. reader = tf.WholeFileReader()
  11. key, value = reader.read(filename_queue)
  12. # tf.train.string_input_producer定义了一个epoch变量,要对它进行初始化
  13. tf.local_variables_initializer().run()
  14. # 使用start_queue_runners之后,才会开始填充队列
  15. threads = tf.train.start_queue_runners(sess=sess)
  16. i = 0
  17. while True:
  18. i += 1
  19. # 获取图片数据并保存
  20. image_data = sess.run(value)
  21. with open('data/test_%d.jpg' % i, 'wb') as f:
  22. f.write(image_data)

四、TensorFLow的几种图片读取方法

1.使用gfile读图片,decode输出是Tensor,eval后是ndarray

  1. import matplotlib.pyplot as plt
  2. import tensorflow as tf
  3. import numpy as np
  4. print(tf.__version__)
  5. image_raw = tf.gfile.FastGFile('test/a.jpg','rb').read() #bytes
  6. img = tf.image.decode_jpeg(image_raw) #Tensor
  7. #img2 = tf.image.convert_image_dtype(img, dtype = tf.uint8)
  8. with tf.Session() as sess:
  9. print(type(image_raw)) # bytes
  10. print(type(img)) # Tensor
  11. #print(type(img2))
  12. print(type(img.eval())) # ndarray !!!
  13. print(img.eval().shape)
  14. print(img.eval().dtype)
  15. # print(type(img2.eval()))
  16. # print(img2.eval().shape)
  17. # print(img2.eval().dtype)
  18. plt.figure(1)
  19. plt.imshow(img.eval())
  20. plt.show()

2.使用WholeFileReader输入queue,decode输出是Tensor,eval后是ndarray

  1. import tensorflow as tf
  2. import os
  3. import matplotlib.pyplot as plt
  4. def file_name(file_dir): #来自http://blog.csdn.net/lsq2902101015/article/details/51305825
  5. for root, dirs, files in os.walk(file_dir): #模块os中的walk()函数遍历文件夹下所有的文件
  6. print(root) #当前目录路径
  7. print(dirs) #当前路径下所有子目录
  8. print(files) #当前路径下所有非目录子文件
  9. def file_name2(file_dir): #特定类型的文件
  10. L=[]
  11. for root, dirs, files in os.walk(file_dir):
  12. for file in files:
  13. if os.path.splitext(file)[1] == '.jpg':
  14. L.append(os.path.join(root, file))
  15. return L
  16. path = file_name2('test')
  1. #path2 = tf.train.match_filenames_once(path)
  2. file_queue = tf.train.string_input_producer(path, shuffle=True, num_epochs=2) #创建输入队列
  3. image_reader = tf.WholeFileReader()
  4. key, image = image_reader.read(file_queue)
  5. image = tf.image.decode_jpeg(image)
  6. with tf.Session() as sess:
  7. # coord = tf.train.Coordinator() #协同启动的线程
  8. # threads = tf.train.start_queue_runners(sess=sess, coord=coord) #启动线程运行队列
  9. # coord.request_stop() #停止所有的线程
  10. # coord.join(threads)
  11. tf.local_variables_initializer().run()
  12. threads = tf.train.start_queue_runners(sess=sess)
  13. #print (type(image))
  14. #print (type(image.eval()))
  15. #print(image.eval().shape)
  16. for _ in path+path:
  17. plt.figure
  18. plt.imshow(image.eval())
  19. plt.show()

3.使用read_file,decode输出是Tensor,eval后是ndarray

  1. import matplotlib.pyplot as plt
  2. import tensorflow as tf
  3. import numpy as np
  4. print(tf.__version__)
  5. image_value = tf.read_file('test/a.jpg')
  6. img = tf.image.decode_jpeg(image_value, channels=3)
  7. with tf.Session() as sess:
  8. print(type(image_value)) # bytes
  9. print(type(img)) # Tensor
  10. #print(type(img2))
  11. print(type(img.eval())) # ndarray !!!
  12. print(img.eval().shape)
  13. print(img.eval().dtype)
  14. # print(type(img2.eval()))
  15. # print(img2.eval().shape)
  16. # print(img2.eval().dtype)
  17. plt.figure(1)
  18. plt.imshow(img.eval())
  19. plt.show()

tensorflow图片读取相关推荐

  1. linux 读取大量图片 内存,10 张图帮你搞定 TensorFlow 数据读取机制

    导读 在学习tensorflow的过程中,有很多小伙伴反映读取数据这一块很难理解.确实这一块官方的教程比较简略,网上也找不到什么合适的学习材料.今天这篇文章就以图片的形式,用最简单的语言,为大家详细解 ...

  2. 1 图片channels_深度学习中各种图像库的图片读取方式

    深度学习中各种图像库的图片读取方式总结 在数据预处理过程中,经常需要写python代码搭建深度学习模型,不同的深度学习框架会有不同的读取数据方式(eg:Caffe的python接口默认BGR格式,Te ...

  3. TensorFlow数据读取方式:Dataset API,以及如何查看dataset:DatasetV1Adapter的方法

    TensorFlow数据读取方式:Dataset API Datasets:一种为TensorFlow 模型创建输入管道的新方式.把数组.元组.张量等转换成DatasetV1Adapter格式 Dat ...

  4. tensorflow 1.0 学习:十图详解tensorflow数据读取机制

    本文转自:https://zhuanlan.zhihu.com/p/27238630 在学习tensorflow的过程中,有很多小伙伴反映读取数据这一块很难理解.确实这一块官方的教程比较简略,网上也找 ...

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

    在学习TensorFlow的过程中,有很多小伙伴反映读取数据这一块很难理解.确实这一块官方的教程比较简略,网上也找不到什么合适的学习材料.今天这篇文章就以图片的形式,用最简单的语言,为大家详细解释一下 ...

  6. TensorFlow数据读取机制:文件队列 tf.train.slice_input_producer和 tf.data.Dataset机制

    TensorFlow数据读取机制:文件队列 tf.train.slice_input_producer和tf.data.Dataset机制 之前写了一篇博客,关于<Tensorflow生成自己的 ...

  7. python读取图像数据流_浅谈TensorFlow中读取图像数据的三种方式

    本文面对三种常常遇到的情况,总结三种读取数据的方式,分别用于处理单张图片.大量图片,和TFRecorder读取方式.并且还补充了功能相近的tf函数. 1.处理单张图片 我们训练完模型之后,常常要用图片 ...

  8. tensorflow数据读取机制

    原博客地址:https://zhuanlan.zhihu.com/p/27238630 代码地址:https://github.com/hzy46/Deep-Learning-21-Examples/ ...

  9. (转)深度学习中各种图像库的图片读取方式

    https://blog.csdn.net/u013841196/article/details/81194310 深度学习中各种图像库的图片读取方式总结 在数据预处理过程中,经常需要写python代 ...

最新文章

  1. YOLOv4 论文翻译
  2. sap服务器应用webservice加载spring的机制问题
  3. 小猫TOMCAT其实很可爱
  4. Uva(10048),最短路Floyd
  5. Python用urlib爬虫基础及格式入门
  6. 理解Spark的核心RDD
  7. 云消防大数据_消防云大数据app下载-消防云大数据下载v1.1.5 安卓版-西西软件下载...
  8. 电话圈(floyd)
  9. PaperNotes(13)-Conditional Image Generation with PixelCNN Decoders
  10. 数的划分(洛谷-P1025)
  11. 转”使用UBOOT烧写根文件系统和内核的方法
  12. ES6中的const命令【转】
  13. uniapp动态修改元素节点样式
  14. 安卓自定义Toast的原理及实现
  15. 计算机的云是什么意思_阿里巴巴计算机云是什么意思
  16. windows下的虚拟化
  17. 【Vue知识点- No8.】网易云音乐案例(vant组件库的使用)
  18. 数据结构与算法(七)—— 散列表结构及其实现和应用
  19. hydra的基本使用
  20. 傅里叶级数FS,连续时间傅里叶变换CTFT,离散时间傅里叶变换DTFT,离散傅里叶变换DFT,推导与联系(二)

热门文章

  1. html 两个idv上下居中,Django搭建个人博客:回到顶部浮动按钮、矢量图标、页脚沉底和粘性侧边栏...
  2. php导航栏代码子菜单找不到,php – 下拉导航菜单,显示每个类别的最新帖子
  3. 什么是计算机嵌套分类汇总,excel嵌套分类汇总 Excel表格中创建嵌套分类汇总和查看嵌套分类汇总明细的方法...
  4. EDA实验课课程笔记(五)——NC-verilog的介绍与使用(一)
  5. BIEE叙述图导航实例
  6. 三维点云学习(4)5-DBSCNA python 复现-3-kd-tree radius NN 三方库 scipy 与 sklearn速度比较
  7. n1 linux wifi,【教程】N1在EMMC安装LINUX和HASSIO实现智能家居中枢
  8. 系统学习 TypeScript(四)——变量声明的初步学习
  9. java虚拟机内存模型与垃圾回收知识复习总结
  10. 无意中发现的MSDN软件下载网站