Оценщик тензорного потока оценивает намного медленнее, чем обучение

У меня есть настраиваемый оценщик, и я пытаюсь использовать некоторые настраиваемые показатели во время оценки. Однако всякий раз, когда я добавляю эти метрики к оценке, через 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()

person Annie    schedule 29.05.2018    source источник
comment
Думаю, вы тем временем решили свою проблему, но я отредактировал свой ответ для всех, у кого похожие симптомы   -  person Ciprian Tomoiagă    schedule 30.07.2018


Ответы (1)


В рамках Оценщика все происходит в model_fn, а именно в вашем crnn_model(features, labels, mode, params). Вот почему эта функция имеет такую ​​сложную сигнатуру.

Параметр mode указывает, вызывается ли он для обучения, оценки или прогнозирования. Итак, если вы хотите записывать дополнительные сводки на тензорную плату во время оценки, вы должны добавить их в раздел if mode == tf.estimator.ModeKeys.EVAL или за пределами любого if в model_fn.

Я полагаю, ваш eval работает намного медленнее, потому что у вас разные размеры пакетов для train / eval, и размер пакета eval может быть меньше. Вы указали, что это не так.

После внимательного изучения вашего кода и опыта работы с подобной моделью я считаю, что оценка с метриками занимает больше времени, потому что одна из метрик edit_distance(), которая последовательно реализуется на ЦП. Во время обучения это op не требуется, поэтому он не запускается.

Я предлагаю вам запускать свои train() и evaluate() в разных программах с одинаковыми model_fn() и model_dir. Таким образом, train не нужно ждать evaluate. И evaluate будет запускаться только при необходимости, т.е. когда в model_dir появятся новые контрольные точки. Если у вас нет двух графических процессоров для этого, вы можете либо разделить память графического процессора между двумя процессами (используя настраиваемую конфигурацию запуска с gpu_memory_fraction=0.75 для поезда), либо скрыть графический процессор от evaluate() с помощью переменной среды CUDA_VISIBLE_DEVICES=''.

person Ciprian Tomoiagă    schedule 05.06.2018
comment
Код для метрик, переданных в eval_metrics_ops, находится чуть выше него metrics = {'precision': tf.metrics.mean (precision), 'edit_dist': tf.metrics.mean (edit_dist),} При использовании метрик оценка занимает больше времени, чем обучение даже при одинаковом размере партии как для обучения, так и для оценки. - person Annie; 06.06.2018
comment
Распространяется ли поддержка по оценке? например, используя несколько узлов для оценки - person crafet; 26.09.2018
comment
@crafet Не знаю. Подумайте о том, чтобы задать новый вопрос, так как ваш не имеет отношения к этому - person Ciprian Tomoiagă; 27.09.2018