При обучении нейронной сети на обучающей выборке на выходе нейросети вычисляются два ключевых параметра эффективности обучения — ошибка и точность предсказания. Для этого используются функция потери (loss) и метрика точности. Эти метрики различаются в зависимости от поставленной задачи (классификация или сегментация изображения, детекция объекта, регрессия). В Keras мы можем определить свои собственные функцию потери и метрики точности под свою конкретную задачу. О таких кастомных функциях и пойдет речь в статье. Кому интересно, прошу под кат.

Кастомные функции потери в Keras


Для примера предположим, что нам необходимо реализовать функцию ошибки Mean Average Error (MAE). Кастомную функцию потерь MAE можно реализовать следующим образом:

from keras import backend as K

def mae(y_true, y_pred):
    true_value = K.sum(y_true * K.arange(0, 100, dtype="float32"), axis=-1)
    pred_value = K.sum(y_pred * K.arange(0, 100, dtype="float32"), axis=-1)
    mae = K.mean(K.abs(true_value - pred_value))
return mae

Здесь мы используем функции sum, arange, mean и abs, определенные в Keras.

Точно так же можно определить свою метрику точности. К примеру определим метрику earth_movers_distance для сравнения двух гистограмм:

from keras import backend as K

def earth_movers_distance(y_true, y_pred):
    cdf_true = K.cumsum(y_true, axis=-1)
    cdf_pred = K.cumsum(y_pred, axis=-1)
    emd = K.sqrt(K.mean(K.square(cdf_true - cdf_pred), axis=-1))
    return K.mean(emd)

Чтобы использовать наши метрики mae и earth_movers_distance импортируем соответствующие функции из отдельного модуля и добавим их в параметры loss и metrics при компиляции модели:

from utils.metrics import mae, earth_movers_distance

loss = earth_movers_distance
model.compile(optimizer=optimizer, loss=loss, metrics=[mae, "accuracy"])

Загрузка модели Keras с кастомной функцией потери


При обучении модели в Keras можно сохранять веса модели в h5 файл для последующей загрузки обученной модели на этапе предсказания. Если мы используем кастомные функции потерь и метрики качества, то мы можем столкнуться с проблемой. Когда мы загружаем обученные веса из файла h5 для модели с помощью метода load_weights мы можем получить такую ошибку:

ValueError: Unknown loss function:earth_movers_distance

Это известный баг в Keras (о нем писали в официальном репозитории на github).

Чтобы решить проблему нужно добавить наши кастомные функции потери и метрики качества в Keras:

from keras.utils.generic_utils import get_custom_objects
get_custom_objects().update({"earth_movers_distance": earth_movers_distance, "age_mae": age_mae})

Пока на этом все. Всем удачи и до новых встреч!

Комментарии (3)


  1. Celsius
    24.11.2019 15:15
    +1

    Вообще-то достаточно инициализировать функцию и подать название в load_model, в виде custom_objects = {'имя_функции': функция_потерь}


    1. vovaekb90 Автор
      24.11.2019 15:58

      спасибо за совет! Нужно будет попробовать. Проще получается


  1. OLZ1
    24.11.2019 18:21

    Подкину моих фавориток-метрик регрессионного анализа:

    — RMS-потеря, или среднеквадратичная ошибка (RMSE)

    def rmse(y_true, y_pred):
        return backend.sqrt(backend.mean(backend.square(y_pred - y_true), axis=-1))

    — R-квадрат (R2), или коэффициент детерминации
    def r2(y_true, y_pred):
        SS_res =  backend.sum(backend.square(y_true-y_pred)) 
        SS_tot = backend.sum(backend.square(y_true-backend.mean(y_true))) 
        return (1-SS_res/(SS_tot+backend.epsilon()))