【问题标题】:Tensorflow shuffle_batch speedTensorFlow shuffle_batch 速度
【发布时间】:2017-06-11 12:40:07
【问题描述】:

我注意到,如果我将训练数据加载到内存中并将其作为 numpy 数组输入到图形中,与使用相同大小的随机批次相比,我的数据有大约 1000 个实例,那么速度会有很大差异。

使用内存 1000 次迭代只需不到几秒钟,但使用 shuffle batch 几乎需要 10 分钟。我得到洗牌批次应该会慢一点,但这似乎太慢了。这是为什么呢?

增加了赏金。关于如何更快地制作随机小批量的任何建议?

这是训练数据:Link to bounty_training.csv (pastebin)

这是我的代码:

shuffle_batch

import numpy as np
import tensorflow as tf

data = np.loadtxt('bounty_training.csv',
    delimiter=',',skiprows=1,usecols = (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14))

filename = "test.tfrecords"

with tf.python_io.TFRecordWriter(filename) as writer:
    for row in data:
        features, label = row[:-1], row[-1]
        example = tf.train.Example()
        example.features.feature['features'].float_list.value.extend(features)
        example.features.feature['label'].float_list.value.append(label)
        writer.write(example.SerializeToString())

def read_and_decode_single_example(filename):
    filename_queue = tf.train.string_input_producer([filename],
                                                   num_epochs=None)
    reader = tf.TFRecordReader()
    _, serialized_example = reader.read(filename_queue)

    features = tf.parse_single_example(
        serialized_example,
        features={
            'label': tf.FixedLenFeature([], np.float32),
            'features': tf.FixedLenFeature([14], np.float32)})

    pdiff = features['label']
    avgs = features['features']

    return avgs, pdiff

avgs, pdiff = read_and_decode_single_example(filename)


n_features = 14
batch_size = 1000
hidden_units = 7
lr = .001

avgs_batch, pdiff_batch = tf.train.shuffle_batch(
    [avgs, pdiff], batch_size=batch_size,
    capacity=5000,
    min_after_dequeue=2000)

X = tf.placeholder(tf.float32,[None,n_features])
Y = tf.placeholder(tf.float32,[None,1])

W = tf.Variable(tf.truncated_normal([n_features,hidden_units]))
b = tf.Variable(tf.zeros([hidden_units]))

Wout = tf.Variable(tf.truncated_normal([hidden_units,1]))
bout = tf.Variable(tf.zeros([1]))

hidden1 = tf.matmul(X,W) + b
pred = tf.matmul(hidden1,Wout) + bout

loss = tf.reduce_mean(tf.squared_difference(pred,Y))

optimizer = tf.train.AdamOptimizer(lr).minimize(loss)

with tf.Session() as sess:
    init = tf.global_variables_initializer()
    sess.run(init)
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)

    for step in range(1000):
        x_, y_ = sess.run([avgs_batch,pdiff_batch])

        _, loss_val = sess.run([optimizer,loss],
              feed_dict={X: x_, Y: y_.reshape(batch_size,1)} )

        if step % 100 == 0:
            print(loss_val)


    coord.request_stop()
    coord.join(threads)

通过 numpy 数组进行全批处理

"""
avgs and pdiff loaded into numpy arrays first...
Same model as above
"""
   with tf.Session() as sess:
        init = tf.global_variables_initializer()
        sess.run(init)

        for step in range(1000):
            _, loss_value = sess.run([optimizer,loss],
                    feed_dict={X: avgs,Y: pdiff.reshape(n_instances,1)} )

【问题讨论】:

    标签: tensorflow


    【解决方案1】:

    在这种情况下,您每步运行 3 次会话 - 一次在 avgs_batch.eval,一次用于 pdiff_batch.eval,一次用于实际的 sess.run 调用。这并不能解释减速的幅度,但这绝对是你应该记住的事情。至少前两个 eval 调用应该合并为一个 sess.run 调用。

    我怀疑大部分减速来自使用TFRecordReader。我不会假装理解 tensorflow 的内部工作原理,但您可能会发现我的回答 here 很有帮助。

    总结

    • 创建与每个示例相关的最少数据,即图像文件名、ID 而不是整个图像;
    • 使用tensorflow.python.framework.ops.convert_to_tensor 转换为张量流操作;
    • 使用tf.train.slice_input_producer 获取单个示例的张量;
    • 对个别示例进行一些预处理 - 例如从文件名加载图像;
    • 使用tf.train.batch 将它们分组在一起。

    【讨论】:

    • 我在某处读到 eval() 只需要几微秒。我在想这与阅读器处理 i/o 的方式有关。训练循环的一次迭代所花费的时间似乎与我给它的批量大小成线性关系。
    【解决方案2】:

    诀窍不是将单个示例输入到 shuffle_batch 中,而是使用 enqueue_many=True 输入一个 n+1 维张量示例。我发现这个帖子很有帮助:

    TFRecordReader seems extremely slow , and multi-threads reading not working

    def get_batch(batch_size):
        reader = tf.TFRecordReader()
        _, serialized_example = reader.read(filename_queue)
    
        batch_list = []
        for i in range(batch_size):
            batch_list.append(serialized_example)
    
        return [batch_list]
    
    batch_serialized_example = tf.train.shuffle_batch(
     get_batch(batch_size), batch_size=batch_size,
        capacity=100*batch_size,
        min_after_dequeue=batch_size*10,
        num_threads=1, 
        enqueue_many=True)
    
    features = tf.parse_example(
        batch_serialized_example,
        features={
            'label': tf.FixedLenFeature([], np.float32),
            'features': tf.FixedLenFeature([14], np.float32)})
    
    batch_pdiff = features['label']
    batch_avgs = features['features']
    
    ...
    

    【讨论】:

      【解决方案3】:

      使用队列获取数据时,不应使用 feed_dict。相反,让您的图表直接依赖于输入数据,即:

      • 移除 X 和 Y 占位符
      • 直接使用您的功能批次

        hidden1 = tf.matmul(avgs_batch,W) + b
        
      • 类似地,在计算损失时使用标签批次 (pdiff_batch) 而不是 Y

      • 最后,只保留第二个 session.run 直接计算损失,而不使用 feed_dict

        # x_, y_ = sess.run([avgs_batch,pdiff_batch])
        # _, loss_val = sess.run([optimizer,loss],
              feed_dict={X: x_, Y: y_.reshape(batch_size,1)} )
        
        _, loss_val = sess.run([optimizer,loss])
        

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-15
        • 1970-01-01
        相关资源
        最近更新 更多