这篇文章写数据读取,包含了线程以及batch的概念


1、准备数据,构造三个文件,A.csv,B.csv,C.csv

$ echo -e "Alpha1,A1\nAlpha2,A2\nAlpha3,A3" > A.csv  
$ echo -e "Bee1,B1\nBee2,B2\nBee3,B3" > B.csv  
$ echo -e "Sea1,C1\nSea2,C2\nSea3,C3" > C.csv

2、从数据里生成样本和标签

2.1、单个Reader,每次生成一个样本

#-*- coding:utf-8 -*-  
import tensorflow as tf  
# 生成一个先入先出队列和一个QueueRunner,生成文件名队列  
filenames = ['A.csv', 'B.csv', 'C.csv']  
filename_queue = tf.train.string_input_producer(filenames, shuffle=False)  
# 定义Reader  
reader = tf.TextLineReader()  
key, value = reader.read(filename_queue)  
# 定义Decoder  
example, label = tf.decode_csv(value, record_defaults=[['null'], ['null']])  
#example_batch, label_batch = tf.train.shuffle_batch([example,label], batch_size=1, capacity=200, min_after_dequeue=100, num_threads=2)  
# 运行Graph  
with tf.Session() as sess:  
    coord = tf.train.Coordinator()  #创建一个协调器,管理线程  
    threads = tf.train.start_queue_runners(coord=coord)  #启动QueueRunner, 此时文件名队列已经进队。  
    for i in range(10):  
        print example.eval(),label.eval()  
    coord.request_stop()  
    coord.join(threads)

结果:这里生成的样本和label之间对应不上,乱序了。生成结果如下:
Alpha1 A2
Alpha3 B1
Bee2 B3
Sea1 C2
Sea3 A1
Alpha2 A3
Bee1 B2
Bee3 C1
Sea2 C3
Alpha1 A2


2.2、用tf.train.shuffle_batch,生成的结果就能够对应上

#-*- coding:utf-8 -*-  
import tensorflow as tf  
# 生成一个先入先出队列和一个QueueRunner,生成文件名队列  
filenames = ['A.csv', 'B.csv', 'C.csv']  
filename_queue = tf.train.string_input_producer(filenames, shuffle=False)  
# 定义Reader  
reader = tf.TextLineReader()  
key, value = reader.read(filename_queue)  
# 定义Decoder  
example, label = tf.decode_csv(value, record_defaults=[['null'], ['null']])  
example_batch, label_batch = tf.train.shuffle_batch([example,label], batch_size=1, capacity=200, min_after_dequeue=100, num_threads=2)  
# 运行Graph  
with tf.Session() as sess:  
    coord = tf.train.Coordinator()  #创建一个协调器,管理线程  
    threads = tf.train.start_queue_runners(coord=coord)  #启动QueueRunner, 此时文件名队列已经进队。  
    for i in range(10):  
        e_val,l_val = sess.run([example_batch, label_batch])  
        print e_val,l_val  
    coord.request_stop()  
    coord.join(threads)

运行结果

BCE tensorflow 怎么调用_文件名


2.3、单个Reader,每次生成一个batch,主要也是通过tf.train.shuffle_batch来实现

#-*- coding:utf-8 -*-  
import tensorflow as tf  
filenames = ['A.csv', 'B.csv', 'C.csv']  
filename_queue = tf.train.string_input_producer(filenames, shuffle=False)  
reader = tf.TextLineReader()  
key, value = reader.read(filename_queue)  
example, label = tf.decode_csv(value, record_defaults=[['null'], ['null']])  
# 使用tf.train.batch()会多加了一个样本队列和一个QueueRunner。  
#Decoder解后数据会进入这个队列,再批量出队。  
# 虽然这里只有一个Reader,但可以设置多线程,相应增加线程数会提高读取速度,但并不是线程越多越好。  
example_batch, label_batch = tf.train.batch(  
      [example, label], batch_size=5)  
with tf.Session() as sess:  
    coord = tf.train.Coordinator()  
    threads = tf.train.start_queue_runners(coord=coord)  
    for i in range(10):  
        e_val,l_val = sess.run([example_batch,label_batch])  
        print e_val,l_val  
    coord.request_stop()  
    coord.join(threads)

运行结果

BCE tensorflow 怎么调用_ci_02


2.4、下面这种写法,提取batch_size个样本,特征和label之间也是不同步的

#-*- coding:utf-8 -*-  
import tensorflow as tf  
filenames = ['A.csv', 'B.csv', 'C.csv']  
filename_queue = tf.train.string_input_producer(filenames, shuffle=False)  
reader = tf.TextLineReader()  
key, value = reader.read(filename_queue)  
example, label = tf.decode_csv(value, record_defaults=[['null'], ['null']])  
# 使用tf.train.batch()会多加了一个样本队列和一个QueueRunner。  
#Decoder解后数据会进入这个队列,再批量出队。  
# 虽然这里只有一个Reader,但可以设置多线程,相应增加线程数会提高读取速度,但并不是线程越多越好。  
example_batch, label_batch = tf.train.batch(  
      [example, label], batch_size=5)  
with tf.Session() as sess:  
    coord = tf.train.Coordinator()  
    threads = tf.train.start_queue_runners(coord=coord)  
    for i in range(10):  
        print example_batch.eval(), label_batch.eval()  
    coord.request_stop()  
    coord.join(threads)

运行结果

BCE tensorflow 怎么调用_文件名_03


2.5、多个reader,生成batch。通过调用batch_join函数

#-*- coding:utf-8 -*-  
import tensorflow as tf  
filenames = ['A.csv', 'B.csv', 'C.csv']  
filename_queue = tf.train.string_input_producer(filenames, shuffle=False)  
reader = tf.TextLineReader()  
key, value = reader.read(filename_queue)  
record_defaults = [['null'], ['null']]  
#定义了多种解码器,每个解码器跟一个reader相连  
example_list = [tf.decode_csv(value, record_defaults=record_defaults)  
                  for _ in range(2)]  # Reader设置为2  
# 使用tf.train.batch_join(),可以使用多个reader,并行读取数据。每个Reader使用一个线程。  
example_batch, label_batch = tf.train.batch_join(  
      example_list, batch_size=5)  
with tf.Session() as sess:  
    coord = tf.train.Coordinator()  
    threads = tf.train.start_queue_runners(coord=coord)  
    for i in range(10):  
        e_val,l_val = sess.run([example_batch,label_batch])  
        print e_val,l_val  
    coord.request_stop()  
    coord.join(threads)

运行结果:

BCE tensorflow 怎么调用_ci_04


3、总结
tf.train.batch与tf.train.shuffle_batch函数使用单个Reader读取文件,但是可以使用多个线程(num_thread>1),这些线程同时读取同一个文件里的不同example。这种方法的优点:

  1. 如果读的线程比文件数多,这种方法可以避免两个线程同时读取同一个文件里的同一个example
  2. tf.train.batch_join方法所使用的同时读硬盘里的N个不同文件会花费多余的disk seek 时间

tf.train.batch_join与tf.train.shuffle_batch_join可设置多Reader读取,每个Reader使用一个线程、且每个reader读取各自的文件,直到这次epoch里的文件全部读取完。

至于两种方法的效率,单Reader时,2个线程就达到了速度的极限。多Reader时,2个Reader就达到了极限。所以并不是线程越多越快,甚至更多的线程反而会使效率下降。