【Tensorflow】数据读取——队列管理器与线程协调器

1、队列和线程

2、文件读取

3、图片处理

在训练模型的过程中,如果数据量特别大将会消耗很多的IO读取时间。考虑到这点,Tensorflow有自己的多线程进行并发运行、队列机制和自带的文件格式(tfrecords)。

我们可以通过Tensorflow开启一个主线程和一个子线程。子线程用来读取数据,处理好后放入队列(队列可以实现数据共享、传递),然后主线程拿数据用来训练模型,这两个线程互不干扰。

队列和线程

队列与队列管理器

Tensorflow队列:

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

tf.FIFOQueue 先进先出队列,按顺序出队列

tf.RandomShuffleQueue 随机出队列

 

1、tf.FIFOQueue

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)

同步

我们先了解一下同步的过程,从上到下执行。

代码展示

#! /usr/bin/env python 
# -*- coding:utf-8 -*-
import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'   # 设置告警级别

"""
模拟同步:先处理数据,然后才能取数据训练
1、首先定义队列
2、定义读取数据,处理数据,入数据的过程    (取数据, +1 , 入队列)

Tensorflow中,运行操作op有依赖性
"""

# 1、首先定义队列
Q = tf.FIFOQueue(3, tf.float32)
# 2、放入一些数据,参数vals是一个张量
enq_many = Q.enqueue_many([[0.1, 0.2, 0.3], ])
# 3、定义读取数据,处理数据,入数据的过程   (取数据, +1 , 入队列)
out_q = Q.dequeue()
data = out_q + 1
en_q = Q.enqueue(data)


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()))

代码运行后如下所示:

线程和协调器

队列管理器和线程协调器实现异步读取训练

当数据量很大时,入队操作从硬盘中读取数据,放入内存中。主线程需要的等待入队操作完成,才能进行训练。会话里可以运行多线程,实现异步读取。

队列管理器

  • tf.train.QueueRunner(queue, enqueue_ops=None)  创建一个QueueRunner队列管理器

queue:一个队列

enqueue_ops:添加线程的队列操作列表。[]*2表示指定两个线程,[]中是要处理的操作(指定子线程要做的事)

  • create_threads(sess, coord=None, start=False)  创建线程来运行给定会话的入队操作(开启线程)

start:布尔值,如果为True启动线程;如果为False,调用者必须调用start()启动线程

coord:线程协调器。线程管理器需要用到。

return:线程的实例

线程协调器

  • tf.train.Coordinator()

线程协调员,实现一个简单的机制来协调一组线程的终止

request_stop() 请求停止

should_stop() 检查是否要求停止

join(threads=None, stop_grace_period_secs=120) 等待线程终止

return 线程协调员实例

代码展示

#! /usr/bin/env python 
# -*- coding:utf-8 -*-
import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'   # 设置告警级别

"""
模拟异步:子线程存入样本,主线程读取样本
1、首先定义队列1000
2、定义要做的事情  循环 值+1 放入队列当中
3、定义队列管理器op,指定多少个子线程,子线程干什么事情
"""
# 1、首先定义队列1000
Q = tf.FIFOQueue(1000, tf.float32)
# 2、定义要做的事情  循环 值+1 放入队列当中
var = tf.Variable(0.0)
# 实现自增   tf.assign_add把变量的值改变
data = tf.assign_add(var, tf.constant(1.0))
en_q = Q.enqueue(data)
# 3、定义队列管理器op,指定多少个子线程,子线程干什么事情
qr = tf.train.QueueRunner(Q, enqueue_ops=[en_q]*2)

# 初始化变量的OP
init_op = tf.global_variables_initializer()


with tf.Session() as sess:
    # 初始化变量
    sess.run(init_op)

    # 开启线程协调器
    coord = tf.train.Coordinator()

    # 真正的开启子线程
    threads = qr.create_threads(sess, coord=coord, start=True)

    # 主线程,不断读取数据训练
    for i in range(300):
        print(sess.run(Q.dequeue()))

    # 回收子线程
    coord.request_stop()
    coord.join(threads)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值