目录
前言
关于python深度学习(tensorflow 1.x版本)学习笔记01——线程队列与io操作(壹)
一、tensorflow与io操作
- io操作相对于CPU操作计算来说速度稍慢。
当读取海量样本时,一次性读取消耗内存;只能一次性进行训练、速度慢。
- tensorflow:
①多线程机制:能够并行地执行任务。②队列。③文件的改善:tfrecords 。
二、tensorflow队列
1、参数 方法
1)tf.FIFOQueue 先进先出队列,按顺序出队列(在训练样本时,希望读入的训练样本是有序的。)
- tf.FIFOQueue(capacity, dtypes, name='fifo_queue')
#capacity:整数。可能存储在此队列中的元素数量的上限。
#DType对象列表。长度dtypes必须等于每个队列元素中的张量数,dtype的类型形状,决定后面进队列元素形状。
方法:
q.dequeue() #获取队列的数据
q.enqueue(值) #将一个数据添加进队列
q.enqueue_many(列表或者元组) #将多个数据添加进队列
q.size() #返回队列的大小
2)tf.RandomShuffleQueue 随机出队列
2、案例实现
import tensorflow as tf
# 模拟一下同步先处理数据,然后才能取数据训练
# tensorflow当中,运行操作(有操作计算)具有依赖性
# 1、首先定义队列
Q = tf.FIFOQueue(3, tf.float32)
# 放入一些数据
enq_many = Q.enqueue_many([[1, 0.1, 0.01], ])
# 2、定义一些读取数据、取数据的过程。# 以下案例模拟定义处理数据的过程:取数据 、*2、 入队列
out_q = Q.dequeue()
data = out_q * 2
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()))
例子:同步操作一个(出队列、*2、入队列)以此进行100 次循环的过程,结果如下:
分析:当数据量很大时,入队操作从硬盘中读取数据,放入内存中,主线程需要等待入队操作完成,才能进行训练。会话里可以运行多个线程,实现异步读取。
三、队列管理器与线程协调器实现异步读取训练
1、队列管理器
- tf.train.QueueRunner(queue, enqueue_ops=None)
# queue:A Queue
# enqueue_ops:添加线程的队列操作列表,[]*2,指定两个线程
# create_threads(sess, coord=None,start=False) 创建线程来运行给定会话的入队操作
# start:布尔值,如果True启动线程;如果为False调用者 必须调用start()启动线程
# coord:线程协调器 用于线程的管理
2、异步操作
- 通过队列管理器来实现变量加1,入队,主线程出队列的操作,观察效果
# 模拟异步子线程 存入样本,主线程 读取样本
import tensorflow as tf
Q = tf.FIFOQueue(3, tf.float32)# 定义队列
# 1、定义一个队列 容量1000, 类型tf.float32
queue = tf.FIFOQueue(1000, tf.float32)
# 2、定义要做的事情 循环 值,+1 并且入列的操作
var = tf.Variable(0.0)
# assign_add操作 和 enq_op 不是同步执行, assign_add操作有可能执行很多次才会执行enq_op操作
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)
# 真正开启子线程
threads = qr.create_threads(sess, start=True)
# 主线程不断读取数据训练
for i in range(300):
print(sess.run(Q.dequeue()))
报错分析:主线程结束,意味着session关闭,资源释放。这时候有一个问题就是,入队自顾自地去执行,在需要的出队操作完成之后,程序无法结束。需要一个实现线程间的同步,终止其他线程--线程协调器。
3、线程协调器
- tf.train.Coordinator() 线程协调员,实现一个简单的机制来协调一组线程的终止
方法: 返回的是线程协调实例
request_stop() 请求停止
should_stop() 检查是否要求停止(一般不用)
join(threads=None, stop_grace_period_secs=120) 等待线程终止
- 线程协调员实例
# 模拟异步子线程 存入样本,主线程 读取样本
# 1、定义一个队列 容量1000, 类型tf.float32
queue = tf.FIFOQueue(1000, tf.float32)
# 2、定义要做的事情 循环 值,+1 并且入列的操作
var = tf.Variable(0.0)
# assign_add操作 和 enq_op 不是同步执行, assign_add操作有可能执行很多次才会执行enq_op操作
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上下文创建的会话会自动关闭, 主线程已经执行完毕了
with tf.Session() as sess:
# 初始化变量
sess.run(init_op)
# 开启线程管理器
coord = tf.train.Coordinator()
# 真正开启子线程
threads = qr.create_threads(sess=sess, coord=coord, start=True)
# 主线程不断读取数据训练
for i in range(300):
# 主线程deq 出列
print(sess.run(Q.dequeue()))
# 进行回收
coord.request_stop()
coord.join(threads=threads)
总结
以上是通过学习视频《Python深度学习(tensorflow)》整理学习笔记(附:视频学习地址https://www.bilibili.com/video/BV1Wt411C75s/),本篇主要记录了tensorflow解决读取数据、实现同步模拟、队列管理器和线程协调器实现异步读取训练。