Как добавить пользовательскую метрику в керас?(Средняя абсолютная ошибка в процентах) - PullRequest
1 голос
/ 25 сентября 2019

Я пытаюсь добавить процент средней абсолютной ошибки (pmae) в качестве пользовательской метрики в кератах.Это определяется как (MAE, деленное на среднее абсолютное значение y, умноженное на 100).Я попытался:

def pmae(y_true,y_pred):
    return K.mean(K.abs(y_pred - y_true)) / K.mean(K.abs(y_true)) * 100
...
model.compile(loss='mse', optimizer=Adam(),metrics=[pmae])

, который работает, но значение на много порядков больше (когда я смотрю на model.history.history.pmae)

Рабочая версия NumPy (на тестовом образце)это:

y_pred = model.predict(X_test)
pmae = abs(y_pred - y_test).mean() / abs(y_true).mean() * 100

Я также пытался добавить , axis=-1 к вызовам K.mean(), но без улучшений (как это предлагается в других ответах на стек).Кто-нибудь знает, что не так?

Ресурсы

  1. На сайте keras в качестве примера приводится среднее значение y:
import keras.backend as K

def mean_pred(y_true, y_pred):
    return K.mean(y_pred)

model.compile(optimizer='rmsprop',
              loss='binary_crossentropy',
              metrics=['accuracy', mean_pred])
Другие ответили на stackoverflow о других пользовательских метриках (например, Keras, пользовательская метрика RMSLE и , как реализовать пользовательскую метрику в кератах? ), но ответы там не помогли мнес расчетом pmae.

1 Ответ

0 голосов
/ 25 сентября 2019

Давайте сравним вашу реализацию с mean_absolute_percentage_error в Керасе:

def mean_absolute_percentage_error(y_true, y_pred):
    if not K.is_tensor(y_pred):
        y_pred = K.constant(y_pred)
    y_true = K.cast(y_true, y_pred.dtype)
    diff = K.abs((y_true - y_pred) / K.clip(K.abs(y_true),
                                            K.epsilon(),
                                            None))
    return 100. * K.mean(diff, axis=-1)

Исходя из этого, для вашего случая должно работать следующее:

def percent_mean_absolute_error(y_true, y_pred):
    if not K.is_tensor(y_pred):
        y_pred = K.constant(y_pred)
    y_true = K.cast(y_true, y_pred.dtype)
    diff = K.mean(K.abs((y_pred - y_true)) / K.mean(K.clip(K.abs(y_true),
                                                           K.epsilon(),
                                                           None)))
    return 100. * K.mean(diff)

Основное отличие вашей попытки состоит в том, что здесь и y_true, и y_pred приводятся к одному и тому же типу данных, а знаменатель равен по крайней мере K.epsilon() (для по умолчанию установлено значение 1e-7 )поэтому ошибка не уходит в бесконечность, если y_true приближается к 0.

...