TensorFlow学习笔记(10) - 队列与多线程及输入数据框架
队列
在 Tensorflow 中,队列和变量类似,都是计算图上的节点.
对于变量节点, 其操作为赋值操作, 修改其取值.
对于队列节点, 其操作为修改操作, 修改其状态. 主要方法有:
- Enqueue
- EnqueueMany
- Dequeue
TensorFlow 提供的队列有两种, FIFOQueue
和 RandomShuffleQueue
.
FIFOQueue
创建普通FIFO队列, RandomShuffleQueue
创建一个随机队列, 每次出队都是随机的选择.
以下是一个出队/入队的程序:
1 | # 创建容量为2的队列, 类型为 int32 |
多线程
TensorFlow 提供tf.Coordinator
和 tf.QueueRunner
两个类来完成多线程协同的功能.
tf.Coordinator
提供以下三个函数:
should_stop
:启动线程需要一直查询此函数, 返回为 True 时, 当前线程需要退出request_stop
: 每个线程都可以通过此函数来通知其他线程退出join
: 线程数组加入到协调器中,并等待其全部结束
1 | def threadFunc(coord, work_id): |
tf.QueueRunner
主要用于启动多个线程来操作同一个队列.
1 | # 创建队列 |
输入文件队列
tf.train.match_filenames_once
: 获取符合正则表达式的所有文件tf.train.string_input_producer
: 可管理上个函数生成文件. 是用初始化时提供的文件列表创建一个输入队列, 通过设置shuffle
参数来打乱顺序, 打乱顺序会运行在一个单独的线程上, 不影响读取文件的速度.
string_input_producer
读取流程: 调用文件读取函数->判断是否有打开的文件可读->有则读,没有或已读完则出队一个文件并读取.
当队列所有数据都读完后会重新初始化, 即全部文件重新加入队列, num_epochs
限制了重复使用次数
string_input_producer
中的输入队列可以被多个线程读取, 且其中文件会被均匀分给不同的线程.
模拟生成数据文件
1 | def convert_to_feature(values: list): |
使用文件生成器来加载文件
1 | def inputProducerDemo(): |
组合训练数据
上个 Demo 一次读取一个样例数据, 使用 tf.train.batch
和 tf.train.shuffle_batch
一次读取一个 batch 的数据, 后者随机读取.
设置num_threads
参数,可以指定多个线程同时执行入队操作. >1 时,多线程会同时读取一个文件中的不同样例并行进行处理.
tf.train.shuffle_batch_join
, 会从输入文件队列中获取不同文件分配给不同线程. 其中, 如果线程过多会导致过多硬盘寻址,从而降低效率.
主要体现逻辑的伪代码如下:
1 | example, label = features['values'], features['label'] |
另外,自己目前使用的 pandas
和numpy
也可以作为输入数据框架.