如何将自定义指标添加到keras? (平均绝对误差百分比)

时间:2019-09-25 18:40:09

标签: python tensorflow keras neural-network deep-learning

我正在尝试将平均绝对错误百分比(pmae)添加为keras中的自定义指标。定义为(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()调用中,但没有任何改进(如其他stackoverflow答案中所建议)。有人知道怎么了吗?

资源

  1. keras website给出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])
  1. 其他人已经在堆栈溢出方面回答了其他自定义指标(例如Keras custom RMSLE metrichow to implement custom metric in keras?),但是那里的回答并没有帮助我进行pmae计算。

1 个答案:

答案 0 :(得分:0)

让我们将您的实现与Keras中的mean_absolute_percentage_error进行比较:

buildscript {
    ext {
        buildToolsVersion = "28.0.3"
        minSdkVersion = 16
        compileSdkVersion = 28
        targetSdkVersion = 28
        supportLibVersion = "28.0.0"
    }
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:3.4.1")

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        mavenLocal()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url("$rootDir/../node_modules/react-native/android")
        }
        maven {
            // Android JSC is installed from npm
            url("$rootDir/../node_modules/jsc-android/dist")
        }

        google()
        jcenter()

    }
}

基于此,以下内容应适合您的情况:

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(即set to 1e-7 by default) ,因此如果K.epsilon()接近y_true,则错误不会变为无穷大。