9、数据读取(一)——队列操作实现同步


1、我们要处理的数据一般在文件(图片,文档等)当中,读取数据之后才能使用深度学习算法进行训练,tf提供了多种数据的读取方式。

  • CSV文件读取
  • 图片读取
  • 二进制文件读取
  • tfrecords文件读取

2、在计算需要快速进行的时候,如何提高I/O的速度?(即如何解决I/O和计算不平衡的问题)

  在训练的过程中,我们需要训练的数据往往会非常的大,不可能执行一次性读取的操作,不仅消耗内存,而且“计算”要花费更长的时间去等待“读取”的完成才能继续,tf提供了真正的多线程、队列以及文件的改善(tfrecords文件格式)机制,可以并行的去执行多个任务,

   tf让子线程去读取数据,这样主线程就可以直接进行模型的训练。子线程没读取到一定量的数据(如100个)之后,主线程进行模型的训练。

3、队列和线程

(1)队列和队列管理器

 在训练样本的时候,希望读入的训练样本时有序的

  ● tf.FlFOQueue     先进先出队列,按顺序出队列

API :  
FIFOQueue(capacity, dtypes, name='fifo_queue')  创建-一个以先进先出的顺序对元素进行排队的队列 ● capacity:整数。队列的大小,可能存储在此队列中的元素数量的上限, ● dtypes: DType对象列表。长度dtypes必须等于每个队列元素中的张量数, dtype的类型形状,决定了后面进队列元素形状 method ● dequeue(name=None) #出队列 ● enqueue(vals, name=None): #进队列 ● enqueue_many(vals, name=None); #vals列表或者元组,把很多数据数据同时放进去,返回一个进队列操作 ● size(name=None) #队列当前的元素个数,常用于判断

例:对队列进行操作,队列Q中有三个数据,每取一个数据,对数据进行+1操作,再把结果放入队列

  ① 定义一个队列 

Q = tf.FIFOQueue(3, tf.float32)

  ② 放入数据

enq_many = Q.enqueue_many(vals = [[0.1,0.2,0.3]])  #enq,enter_queue进队列

  ③出队列,加1操作,进队列

out_q = Q.dequeue()  #此时out_q是一个tensor,可以run之后取出数据
data = out_q + 1  #符号重载
en_q = Q.enqueue(data)
依赖性,下一个op和上一个op之间必须存在计算的操作关系(如加一等),才能说他们拥有依赖性,此时只需运行最后一个即可。
这里的data 和out_q存在计算的操作关系,而out_q和enq_many没有关系

④ 会话

with tf.Session() as sess:
    #初始化队列
    sess.run(enq_many)
    for i in range(100):
       sess.run(en_q)
    for i in range(Q.size().eval()):
        print(sess.run(Q.dequeue()))

 ⑤ 错误显示:

ValueError: Shape () must have rank at least 1

原因:

enq_many = Q.enqueue_many(vals = [0.1,0.2,0.3])   #vals 列表或者元组
[文档解释]该操作沿着第0维将每个组件张量分割成多个队列元素。“vals”中的所有张量必须在第0维中具有相同的大小。如果执行此操作时队列已满,则它将阻塞,直到所有元素都已排队。
这里应该是[[0.1,0.2,0.3],]才能将其的分量[0.1,0.2,0.3]切片,创建为队列元素

 ⑥ 完整代码

 1 import tensorflow as tf
 2 import os
 3 os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' #去掉警告,将警告级别提升
 4 
 5 # 模拟一下同步先处理数据,然后才能取数据训练
 6 # 每一个op需要在session中去运行
 7 # tf中,运行操作有依赖性(比如第二步)
 8 
 9 # 1. 首先定义队列
10 Q = tf.FIFOQueue(3, tf.float32)  #队列的大小
11 enq_many = Q.enqueue_many(vals = [[0.1,0.2,0.3],])   #vals 列表或者元组, 该op返回一个进队列操作
12 
13 # 2.定义一些读取数据,取数据的过程, 取数据 ,+1, 入队列
14 out_q = Q.dequeue()  #此时out_q是一个tensor,可以run之后取出数据
15 data = out_q + 1  #符号重载
16 en_q = Q.enqueue(data)
17 # 依赖性,下一个op和上一个op之间必须存在计算操作关系(如加一等),才能说他们拥有依赖性
18 # 这里的data 和out_q存在计算的操作关系,而out_q和enq_many没有关系
19 
20 with tf.Session() as sess:
21     #初始化队列
22     sess.run(enq_many)
23     # sess.graph()
24     #处理数据,从队列中取数据 (放数据)
25     for i in range(100):
26        sess.run(en_q)  #运行依赖的最后一个,这里打印是没有数据的
27 
28     #训练数据 (这里假设为取数据)
29     for i in range(Q.size().eval()):  # Q.size()是一个op,需要加eval()取值
30         print(sess.run(Q.dequeue()))

输出:

33.2
33.3
34.1

  ● tf.RandomShuffleQueue     随机出队列

 

 

 

 

(2)线程和协调器

posted on 2019-11-15 14:28  Luaser  阅读(483)  评论(0编辑  收藏  举报