【问题标题】:tensorflow estimator evaluate much slower than training张量流估计器评估比训练慢得多
【发布时间】:2018-11-07 13:32:51
【问题描述】:

我有一个自定义估算器,并尝试在评估期间使用一些自定义指标。但是,每当我将这些指标添加到评估中时,通过 eval_metric_ops 评估变得非常慢(比实际计算相同指标的训练慢得多)。如果我不在那里添加指标,那么我只能在 Tensorboard 中看到用于训练的指标,而不能用于评估。

为自定义估算器添加自定义指标以便在评估期间保存的正确方法是什么。

这就是我所拥有的:

def compute_accuracy(preds, labels):
    total = tf.shape(labels.values)[0]
    preds = tf.sparse_to_dense(preds.indices, preds.dense_shape, preds.values, default_value=-1)
    labels = tf.sparse_to_dense(labels.indices, labels.dense_shape, labels.values, default_value=-2)

    r = tf.shape(labels)[0]
    c = tf.minimum(tf.shape(labels)[1], tf.shape(preds)[1])
    preds = tf.slice(preds, [0,0], [r,c])
    labels = tf.slice(labels, [0,0], [r,c])

    preds = tf.cast(preds, tf.int32)
    labels = tf.cast(labels, tf.int32)

    correct = tf.reduce_sum(tf.cast(tf.equal(preds, labels), tf.int32))
    accuracy = tf.divide(correct, total)
    return accuracy

In model_fn
    edit_dist = tf.reduce_mean(tf.edit_distance(tf.cast(predicted_label[0], tf.int32), labels))
    accuracy = compute_accuracy(predicted_label[0], labels)
    tf.summary.scalar('edit_dist', edit_dist)
    tf.summary.scalar('accuracy', accuracy)

    metrics = {
        'accuracy': tf.metrics.mean(accuracy),
        'edit_dist':tf.metrics.mean(edit_dist),
    }

   if mode == tf.estimator.ModeKeys.EVAL:
        return tf.estimator.EstimatorSpec(mode, loss=loss, eval_metric_ops=metrics)

根据要求,这里是完整的模型和 TfRecord Writer 代码:

def crnn_model(features, labels, mode, params):

    inputs = features['image']
    print("INPUTS SHAPE", inputs.shape)

    if mode == tf.estimator.ModeKeys.TRAIN:
        batch_size = params['batch_size']
        lr_initial = params['lr']
        lr = tf.train.exponential_decay(lr_initial, global_step=tf.train.get_global_step(),
                                        decay_steps=params['lr_decay_steps'], decay_rate=params['lr_decay_rate'],
                                        staircase=True)
        tf.summary.scalar('lr', lr)
    else:
        batch_size = params['test_batch_size']

    with tf.variable_scope('crnn', reuse=False):
        rnn_output, predicted_label, logits = CRNN(inputs, hidden_size=params['hidden_size'], batch_size=batch_size)

    if mode == tf.estimator.ModeKeys.PREDICT:
        predictions = {
            'predicted_label': predicted_label,
            'logits': logits,
        }
        return tf.estimator.EstimatorSpec(mode, predictions=predictions)


    loss = tf.reduce_mean(tf.nn.ctc_loss(labels=labels, inputs=rnn_output,
                                         sequence_length=23 * np.ones(batch_size),
                                         ignore_longer_outputs_than_inputs=True))
    edit_dist = tf.reduce_mean(tf.edit_distance(tf.cast(predicted_label[0], tf.int32), labels))
    accuracy = compute_accuracy(predicted_label[0], labels)

    metrics = {
        'accuracy': tf.metrics.mean(accuracy),
        'edit_dist':tf.metrics.mean(edit_dist),
    }

    tf.summary.scalar('loss', loss)
    tf.summary.scalar('edit_dist', edit_dist)
    tf.summary.scalar('accuracy', accuracy)

    if mode == tf.estimator.ModeKeys.EVAL:
        return tf.estimator.EstimatorSpec(mode, loss=loss, eval_metric_ops=metrics)

    assert mode == tf.estimator.ModeKeys.TRAIN

    update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
    with tf.control_dependencies(update_ops):
        optimizer = tf.train.AdadeltaOptimizer(learning_rate=lr)
        train_op = optimizer.minimize(loss=loss, global_step=tf.train.get_global_step())
        return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)

Tf Record Writer 代码

def _write_fn(self, out_file, image_list, label_list, mode):
    writer = tf.python_io.TFRecordWriter(out_file)
    N = len(image_list)
    for i in range(N):
        if (i % 1000) == 0:
            print('%s Data: %d/%d records saved' % (mode, i,N))
            sys.stdout.flush()

        try:
            #print('Try image: ', image_list[i])
            image = load_image(image_list[i])
        except (ValueError, AttributeError):
            print('Ignoring image: ', image_list[i])
            continue
        label = label_list[i]
        feature = {
            'label': _int64_feature(label),
            'image': _byte_feature(tf.compat.as_bytes(image.tostring()))
        }

        example = tf.train.Example(features=tf.train.Features(feature=feature))

        writer.write(example.SerializeToString())
    writer.close()

【问题讨论】:

  • 我猜你同时解决了你的问题,但我为任何有类似症状的人编辑了我的答案

标签: tensorflow evaluate


【解决方案1】:

在 Estimator 框架中,一切都发生在model_fn,即你的crnn_model(features, labels, mode, params)。这就是为什么这个函数有如此复杂的签名。

mode 参数表示是否调用它进行训练、评估或预测。因此,如果您想在评估期间将其他摘要记录到 tensorboard,您可以将它们添加到 if mode == tf.estimator.ModeKeys.EVAL 部分下,或在 model_fn 中的任何 if 之外。

我想你的评估要慢得多,因为你有不同的训练/评估批量大小,评估批量大小可能更小。 你表示不是这样的。

在仔细查看您的代码并体验过类似模型后,我认为使用指标进行评估需要更长的时间,因为其中一个指标是 edit_distance(),它是在 CPU 上按顺序实现的。在训练期间,此op 不是必需的,因此不会运行。

我建议你在不同的程序中运行train()evaluate(),使用相同的model_fn()model_dir。这样train就不需要等待evaluate了。而evaluate 只会在必要时运行,即当model_dir 中有新的检查点时。如果您没有 2 个 GPU,您可以在两个进程之间拆分 GPU 内存(使用带有 gpu_memory_fraction=0.75 的自定义运行配置进行训练)或通过使用 CUDA_VISIBLE_DEVICES='' 环境从 evaluate() 隐藏 GPU变量

【讨论】:

  • 传递给 eval_metrics_ops 的指标代码就在它上面 metrics = { 'accuracy': tf.metrics.mean(accuracy), 'edit_dist':tf.metrics.mean(edit_dist), }即使在训练和评估的批量大小相同的情况下,使用度量标准时,评估所需的时间也比训练要长。
  • 评估支持是否自行分发?例如使用多个节点进行评估
  • @crafet 我不知道。考虑提出一个新问题,因为您的问题与这个问题无关
猜你喜欢
  • 2019-08-02
  • 1970-01-01
  • 1970-01-01
  • 2018-04-09
  • 2019-04-13
  • 1970-01-01
  • 2019-02-04
  • 1970-01-01
  • 2019-10-31
相关资源
最近更新 更多