performance - TensorFlow:使用队列提供数据与使用 feed_dict 直接提供数据

标签 performance tensorflow

我一直在使用 feed_dict 来直接输入 placeholder在像 MNIST 这样的小问题中练习编码。 TensorFlow 还支持使用 queue 馈送数据和 queue runner ,它需要一些努力来学习。

有没有人对这两种方法进行比较并衡量性能?是否值得花时间学习使用队列来馈送数据?

我想使用队列不仅是为了性能,也是为了更清晰的代码,这意味着什么。也许一个数据集的代码可以很容易地用于另一个数据集(一旦我将数据转换为 TFRecord)?

然而,this post似乎说队列可能比 feed_dict 方法慢。现在还是这样吗?如果代码更慢且更难编码,我为什么要使用队列?

感谢您的投入。

最佳答案

我的 NMT 模型有 2 层,512 个隐藏单元。我用最大句子长度 = 50,批量大小 = 32 进行训练,看到 feed_dict 和队列之间的速度相似,大约每秒 2400-2500 个目标词(我使用这个指标来衡量基于此 paper 的速度)。

我发现 feed_dict 非常直观且易于使用。排队很难。使用队列,您必须:

1/将您的数据转换为 tfrecords。我实际上需要谷歌一下以了解如何将我的 seq2seq 数据转换为 tfrecords,因为文档不是很有帮助。

2/从 tfrecords 解码您的数据。您会发现用于生成 tfrecords 和解码的函数并不直观匹配。例如,如果我的每个训练示例都有 3 个序列(只有 3 个整数列表)src_input, trg_input, trg_target我想记录src_input的长度也是(它的一些元素可能是 PADDING,所以不要计算),这里是如何从每个示例生成 tfrecord:

def _make_example(src_input, src_seq_length, trg_input, trg_seq_length, trg_target, target_weight):
    context = tf.train.Features(
        feature={
            'src_seq_length': int64_feature(src_seq_length)
        })
    feature_lists = tf.train.FeatureLists(
        feature_list={
            'src_input': int64_featurelist(src_input),
            'trg_input': int64_featurelist(trg_input),
            'trg_target': int64_featurelist(trg_target)
        })

    return tf.train.SequenceExample(context=context, feature_lists=feature_lists)  

这是解码它的方法:
def _read_and_decode(filename_queue):
    reader = tf.TFRecordReader(options=self.tfrecord_option)
    _, serialized_ex = reader.read(filename_queue)

    context_features = {
        'src_seq_length': tf.FixedLenFeature([], dtype=tf.int64)
    }
    sequence_features = {
        'src_input': tf.FixedLenSequenceFeature([], dtype=tf.int64),
        'trg_input': tf.FixedLenSequenceFeature([], dtype=tf.int64),
        'trg_target': tf.FixedLenSequenceFeature([], dtype=tf.int64)
    }
    context, sequences = tf.parse_single_sequence_example(
        serialized_ex, 
        context_features=context_features, 
        sequence_features=sequence_features)

    src_seq_length = tf.cast(context['src_seq_length'], tf.int32)
    src_input = tf.cast(sequences['src_input'], tf.int32)
    trg_input = tf.cast(sequences['trg_input'], tf.int32)
    trg_target = tf.cast(sequences['trg_target'], tf.int32)

    return src_input, src_seq_length, trg_input, trg_target

并生成每个 tfrecord 功能/功能列表:
def int64_feature(value):
    return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))

def int64_featurelist(l):
    feature = [tf.train.Feature(int64_list=tf.train.Int64List(value=[x])) for x in l]
    return tf.train.FeatureList(feature=feature)  

http://gph.is/2cg7iKP

3/训练/开发设置。我相信定期训练模型一段时间,然后在开发集上评估,然后重复是一种常见的做法。我不知道如何用队列来做到这一点。使用 feed_dict,您只需在同一 session 下构建两个具有共享参数的图形,一个用于训练,另一个用于开发。当您对开发集进行评估时,只需将开发数据提供给开发图,就是这样。但是对于队列,队列的输出是图本身的一部分。要运行队列,你必须启动队列运行器,创建一个协调器,使用这个协调器来管理队列。完成后,队列已关闭!!!。目前,我不知道如何最好地编写我的代码以使火车/开发设置与队列一致,除了打开新 session ,每次评估时为开发构建新图。提出了同样的问题 here ,你可以在 Stackoverflow 上谷歌搜索类似的问题。

但是,很多人说 queue 比 feed_dict 更快。我的猜测是,如果您以分布式方式训练,队列是有益的。但对我来说,我经常只在 1 个 GPU 上训练,到目前为止,我对队列根本没有印象。嗯,只是我的猜测。

关于performance - TensorFlow:使用队列提供数据与使用 feed_dict 直接提供数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38416824/

相关文章:

javascript - 创建 DOM 元素 : createElement, 添加属性等与创建它们的字符串然后追加之间的区别

python - Tensorflow ValueError : All shapes must be fully defined: [TensorShape([Dimension(None), 维度(无),维度(3)]),TensorShape([])

python - tf.nn.sigmoid_cross_entropy_with_logits 公司关于文档中的参数

java - int vs long 的迭代速度

c# - Entity Framework 使用大量内存

python - 在 Tensorflow 中使用 py_func - ValueError : callback pyfunc_0 is not found

tensorflow - 获取 Tensorflow Serving 中暴露模型的信息

tensorflow - Tensorflow 2.0.0-alpha 0 版本中已弃用函数的问题

c - C循环中2个数组之间的加速复制

java - 解析具有空值属性的 xml