При обучении нейронной сети на обучающей выборке на выходе нейросети вычисляются два ключевых параметра эффективности обучения — ошибка и точность предсказания. Для этого используются функция потери (loss) и метрика точности. Эти метрики различаются в зависимости от поставленной задачи (классификация или сегментация изображения, детекция объекта, регрессия). В Keras мы можем определить свои собственные функцию потери и метрики точности под свою конкретную задачу. О таких кастомных функциях и пойдет речь в статье. Кому интересно, прошу под кат.
Для примера предположим, что нам необходимо реализовать функцию ошибки Mean Average Error (MAE). Кастомную функцию потерь MAE можно реализовать следующим образом:
Здесь мы используем функции sum, arange, mean и abs, определенные в Keras.
Точно так же можно определить свою метрику точности. К примеру определим метрику earth_movers_distance для сравнения двух гистограмм:
Чтобы использовать наши метрики mae и earth_movers_distance импортируем соответствующие функции из отдельного модуля и добавим их в параметры loss и metrics при компиляции модели:
При обучении модели в Keras можно сохранять веса модели в h5 файл для последующей загрузки обученной модели на этапе предсказания. Если мы используем кастомные функции потерь и метрики качества, то мы можем столкнуться с проблемой. Когда мы загружаем обученные веса из файла h5 для модели с помощью метода load_weights мы можем получить такую ошибку:
Это известный баг в Keras (о нем писали в официальном репозитории на github).
Чтобы решить проблему нужно добавить наши кастомные функции потери и метрики качества в 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)
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()))
Celsius
Вообще-то достаточно инициализировать функцию и подать название в load_model, в виде custom_objects = {'имя_функции': функция_потерь}
vovaekb90 Автор
спасибо за совет! Нужно будет попробовать. Проще получается