Как использовать метрики TensorFlow в Керасе

Кажется, уже есть несколько тем / проблем по этому вопросу, но мне не кажется, что это было решено:

Как я могу использовать метрическую функцию тензорного потока в моделях keras?

https://github.com/fchollet/keras/issues/6050

https://github.com/fchollet/keras/issues/3230

Люди, кажется, либо сталкиваются с проблемами, связанными с инициализацией переменной, либо с метрикой 0.

Мне нужно рассчитать различные показатели сегментации и я хотел бы включить tf.metric.mean_iou в мою модель Keras. Это лучшее, что мне удалось придумать:

def mean_iou(y_true, y_pred):
   score, up_opt = tf.metrics.mean_iou(y_true, y_pred, NUM_CLASSES)
   K.get_session().run(tf.local_variables_initializer())
   return score

model.compile(optimizer=adam, loss='categorical_crossentropy', metrics=[mean_iou])

Этот код не выдает никаких ошибок, но mean_iou всегда возвращает 0. Я считаю, что это потому, что up_opt не оценивается. Я видел, что до TF 1.3 люди предлагали использовать что-то вроде control_flow_ops.with_dependencies([up_opt], ​​Score) для достижения этой цели. Это больше не представляется возможным в TF 1.3.

Таким образом, как я могу оценить метрики TF 1.3 в Keras 2.0.6? Это кажется довольно важной особенностью.

2 ответа

Вы все еще можете использоватьcontrol_dependencies

def mean_iou(y_true, y_pred):
   score, up_opt = tf.metrics.mean_iou(y_true, y_pred, NUM_CLASSES)
   K.get_session().run(tf.local_variables_initializer())
   with tf.control_dependencies([up_opt]):
       score = tf.identity(score)
   return score

Вы можете использовать следующий декоратор для переноса tf.metrics в keras.metrics:

def as_keras_metric(method):
    import functools
    from keras import backend as K
    import tensorflow as tf
    @functools.wraps(method)
    def wrapper(self, args, **kwargs):
        """ Wrapper for turning tensorflow metrics into keras metrics """
        value, update_op = method(self, args, **kwargs)
        K.get_session().run(tf.local_variables_initializer())
        with tf.control_dependencies([update_op]):
            value = tf.identity(value)
        return value
    return wrapper

Основное использование:

auc_roc = as_keras_metric(tf.metrics.auc)
recall = as_keras_metric(tf.metrics.recall)
...

Скомпилируйте модель keras:

model.compile(..., metrics=[auc_roc])

Функция украшения:

Помните о несоответствии с аргументами (например, порядок y_pred, y_true). Украсьте свой выход из этого:

@as_keras_metric
def auc_roc(y_true, y_pred):
    return tf.contrib.metrics.streaming_auc(y_pred, y_true)

Вы также можете использовать декоратор для установки параметров по умолчанию (например, для mean_iou):

@as_keras_metric
def mean_iou(y_true, y_pred, num_classes=2):
    return tf.metrics.mean_iou(y_true, y_pred, num_classes)

Для метрик, которые возвращают несколько значений, я ожидаю, что среднее значение берется во время каждой оценки эпохи. Например, использование двух пороговых значений в precision_at_thresholds возвращает два значения, но, насколько я вижу, Keras сообщает среднее значение во время тренировки.

@as_keras_metric
def precision_at_thresholds(y_true, y_pred, thresholds=[0.25, 0.50]):
    return tf.metrics.precision_at_thresholds(y_true, y_pred, thresholds)

Предостережения:

Помните, как прокомментировал fchollet, что это взлом. Это может привести к нежелательным результатам, поскольку Keras не поддерживает метрики тензорного потока.

Было 2 ключа, чтобы заставить это работать на меня. Первый использовал

sess = tf.Session()
sess.run(tf.local_variables_initializer())

Инициализировать переменные TF после использования функций TF (и компиляции), но перед выполнением model.fit(), Вы получили это в своем первоначальном примере, но большинство других примеров показывают tf.global_variables_initializer(), который не работал для меня.

Еще одна вещь, которую я обнаружил, - это объект op_update, который возвращается как вторая часть кортежа из многих метрик TF. Это то, что мы хотим. Другая часть кажется равной 0, когда метрики TF используются с Keras. Таким образом, ваш показатель IOU должен выглядеть следующим образом:

def mean_iou(y_true, y_pred):
   return tf.metrics.mean_iou(y_true, y_pred, NUM_CLASSES)[1]

from keras import backend as K

K.get_session().run(tf.local_variables_initializer())

model.fit(...)
Другие вопросы по тегам