【问题标题】:TensorFlow Seq2Seq Training Time per Minibatch Monotonically Increases每个 Minibatch 的 TensorFlow Seq2Seq 训练时间单调增加
【发布时间】:2017-06-23 05:39:45
【问题描述】:

我正在训练一个tensorflow.contrib.seq2seq 编码器-解码器模型,每个小批量的训练时间是单调递增的。

Step Number: 10 Elapsed time: 52.89215302467346 Loss: 1.0420862436294556 Metrics: {'accuracy': 0.22499999} Step Number: 20 Elapsed time: 60.28505992889404 Loss: 0.8007364869117737 Metrics: {'accuracy': 0.28} Step Number: 30 Elapsed time: 73.98479580879211 Loss: 0.7292348742485046 Metrics: {'accuracy': 0.34} Step Number: 40 Elapsed time: 82.99069213867188 Loss: 0.6843382120132446 Metrics: {'accuracy': 0.345} Step Number: 50 Elapsed time: 86.97363901138306 Loss: 0.6808319687843323 Metrics: {'accuracy': 0.38999999} Step Number: 60 Elapsed time: 106.96697807312012 Loss: 0.601255476474762 Metrics: {'accuracy': 0.44} Step Number: 70 Elapsed time: 124.17725801467896 Loss: 0.5971778035163879 Metrics: {'accuracy': 0.405} Step Number: 80 Elapsed time: 137.91252613067627 Loss: 0.596596896648407 Metrics: {'accuracy': 0.43000001} Step Number: 90 Elapsed time: 146.6834409236908 Loss: 0.5921837687492371 Metrics: {'accuracy': 0.42500001}

我的所有数据都是人工生成的并且是随机抽样的,这意味着(通常)训练早期的小批量和训练后期的小批量之间应该没有区别。此外,我所有的数据都具有相同的输入序列长度和相同的输出序列长度。为什么我的模型可能需要更长的时间来训练以后的小批量?

我发现了这个相关的 post,但我没有在训练循环期间更改我的计算图。

为了展示一些代码,让我们从main开始:

def main(_):
    x_minibatch, y_minibatch, y_lengths_minibatch = construct_data_pipeline()

    model = import_model()

    train(model=model, x_minibatch=x_minibatch, y_minibatch=y_minibatch, y_lengths_minibatch=y_lengths_minibatch)

```

我的数据存储为SequenceExamples,每个TFRecord 文件一个。我的construct_data_pipeline()函数定义如下:

def construct_data_pipeline():
    # extract TFRecord filenames located in data directory
    tfrecord_filenames = []
    for dirpath, dirnames, filenames in os.walk(tf.app.flags.FLAGS.data_dir):
        for filename in filenames:
            if filename.endswith('.tfrecord'):
                tfrecord_filenames.append(os.path.join(dirpath, filename))

    # read and parse data from TFRecords into tensors
    x, y, x_len, y_len = construct_examples_queue(tfrecord_filenames)

    # group tensors into minibatches
    x_minibatch, y_minibatch, y_lengths_minibatch = construct_minibatches(x=x, y=y,
                                                                      y_len=y_len,
                                                                      x_len=x_len)

    return x_minibatch, y_minibatch, y_lengths_minibatch

步入construct_examples_queue()

def construct_examples_queue(tfrecords_filenames):
    number_of_readers = tf.flags.FLAGS.number_of_readers

    with tf.name_scope('examples_queue'):
        key, example_serialized = tf.contrib.slim.parallel_reader.parallel_read(tfrecords_filenames,
                                                                            tf.TFRecordReader,
                                                                            num_readers=number_of_readers)

        x, y, x_len, y_len = parse_example(example_serialized)

        return x, y, x_len, y_len

我不认为我可以显示parse_example,因为数据不是我自己的。主要部分是我指定我期望 SequenceExample 包含的内容,然后调用

    context_parsed, sequence_parsed = tf.parse_single_sequence_example(example_serialized,
                                                                   context_features=context_features,
                                                                   sequence_features=sequence_features)

跳到我如何构建小批量,我使用

def construct_minibatches(x, y, y_len, x_len,
                      bucket_boundaries=list(range(400, tf.app.flags.FLAGS.max_x_len, 100))):

    batch_size = tf.app.flags.FLAGS.batch_size

    with tf.name_scope('batch_examples_using_buckets'):
        _, outputs = tf.contrib.training.bucket_by_sequence_length(input_length=len_x,
                                                               tensors=[x, y, y_len],
                                                               batch_size=batch_size,
                                                               bucket_boundaries=bucket_boundaries,
                                                               dynamic_pad=True,
                                                               capacity=2 * batch_size,
                                                               allow_smaller_final_batch=True)

        x_minibatch = outputs[0]
        y_minibatch = outputs[1]
        y_lengths_minibatch = outputs[2]
        return x_minibatch, y_minibatch, y_lengths_minibatch

注意:出于隐私问题,我不得不更改一些变量名称。希望我没有犯任何错误。

【问题讨论】:

  • 愚蠢的问题,但你确定不是训练开始后的时间吗?什么会产生“经过的时间”?
  • 损失也在稳步下降。
  • 经过时间初始化为start_time = time.time()。然后,在 10 个 minibatch 训练后,我调用print(time.time() - start_time),然后调用start_time = time.time()
  • 更准确地说,我其实是打电话给print('Step Number: {}\tElapsed time: {}\tLoss: {}\tMetrics: {}'.format(step_number + 1, time.time() - start_time, loss, metrics))
  • 如果没有更多详细信息,包括您输入数据和调用 session.run 的代码部分,就不可能回答这个问题。

标签: tensorflow


【解决方案1】:

感谢faddy-w 同时解决了我的两个问题!

事实证明,我在不知情的情况下更改了我的计算图。

我在打电话

sess.run([model.optimizer.minimize(model.loss), model.y_predicted_logits],
                                 feed_dict={model.x: x_values,
                                            model.y_actual: y_values,
                                            model.y_actual_lengths: y_lengths_values})

从一个循环中,其中

model.loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=self.y_actual,
                                                                      logits=self.y_predicted_logits))

model.optimizer = tf.train.GradientDescentOptimizer(learning_rate=initial_learning_rate)

不知道optimizer.minimize() 向我的图表添加了额外的操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-21
    • 1970-01-01
    • 1970-01-01
    • 2017-09-13
    • 2019-12-31
    • 2018-11-12
    相关资源
    最近更新 更多