【问题标题】:Keras custom RMSLE metricKeras 自定义 RMSLE 指标
【发布时间】:2018-05-14 22:40:16
【问题描述】:

如何在 Keras 中实现此指标?我下面的代码给出了错误的结果! 请注意,我正在通过 exp(x) - 1 撤消先前的 log(x + 1) 转换,负面预测也被剪裁为 0:

def rmsle_cust(y_true, y_pred):
    first_log = K.clip(K.exp(y_pred) - 1.0, 0, None)
    second_log = K.clip(K.exp(y_true) - 1.0, 0, None)
    return K.sqrt(K.mean(K.square(K.log(first_log + 1.) - K.log(second_log + 1.)), axis=-1)

为了比较,这里是标准的 numpy 实现:

def rmsle_cust_py(y, y_pred, **kwargs):
    # undo 1 + log
    y = np.exp(y) - 1
    y_pred = np.exp(y_pred) - 1

    y_pred[y_pred < 0] = 0.0
    to_sum = [(math.log(y_pred[i] + 1) - math.log(y[i] + 1)) ** 2.0 for i,pred in enumerate(y_pred)]
    return (sum(to_sum) * (1.0/len(y))) ** 0.5

我做错了什么?谢谢!

编辑:设置axis=0 似乎给出的值非常接近正确值,但我不确定,因为我似乎使用的所有代码都使用axis=-1。

【问题讨论】:

    标签: python deep-learning keras metrics


    【解决方案1】:

    我遇到了同样的问题并搜索它,这是我找到的

    https://www.kaggle.com/jpopham91/rmlse-vectorized

    稍作修改后,这似乎对我有用,rmsle_K 方法用Keras 和TensorFlow 实现。

    import numpy as np
    import math
    from keras import backend as K
    import tensorflow as tf
    
    def rmsle(y, y0):
        assert len(y) == len(y0)
        return np.sqrt(np.mean(np.power(np.log1p(y)-np.log1p(y0), 2)))
    
    def rmsle_loop(y, y0):
        assert len(y) == len(y0)
        terms_to_sum = [(math.log(y0[i] + 1) - math.log(y[i] + 1)) ** 2.0 for i,pred in enumerate(y0)]
        return (sum(terms_to_sum) * (1.0/len(y))) ** 0.5
    
    def rmsle_K(y, y0):
        return K.sqrt(K.mean(K.square(tf.log1p(y) - tf.log1p(y0))))
    
    r = rmsle(y=[5, 20, 12], y0=[8, 16, 12])
    r1 = rmsle_loop(y=[5, 20, 12], y0=[8, 16, 12])
    r2 = rmsle_K(y=[5., 20., 12.], y0=[8., 16., 12.])
    
    print(r)
    
    print(r1)
    
    sess = tf.Session()
    
    print(sess.run(r2))
    

    结果:

    使用 TensorFlow 后端

    0.263978210565
    
    0.263978210565
    
    0.263978
    

    【讨论】:

    • 谢谢,但是 exp(x) - 1 转换呢?
    • @Fernando 虽然kaggle.com/wiki/RootMeanSquaredLogarithmicError 我认为你不需要这种转换
    • 我需要,因为我的模型适合 log(x + 1),所以我需要通过 exp(x) - 1 转换回来,然后应用 RMSLE。
    • 不会最小化日志错误也最小化实际错误,因为日志函数是单调变换?
    【解决方案2】:

    通过在 numpy 实现中使用列表 (to_sum),我怀疑您的 numpy 数组的形状为 (length,)。

    在 Keras 上,由于 axis=0 和 axis=1 的结果不同,您可能会得到类似 (length,1) 的形状。

    另外,在创建to_sum 列表时,您使用的是y[i] 和y_pred[i],这意味着您在numpy 实现中从axis=0 中获取元素。

    numpy 实现还对计算sum(to_sum) 中的平均值的所有内容求和。所以,你真的不需要在K.mean 中使用任何axis。

    如果您确定模型的输出形状是(length,) 或(length,1),则可以只使用K.mean(value) 而无需传递轴参数。

    【讨论】:

    • 我注意到了这一点,但 Keras 给出的相同 (y, y_pred) 对的结果略有不同。我不知道为什么。
    猜你喜欢
    • 2020-03-04
    • 2017-09-20
    • 2019-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 2019-01-24
    相关资源
    最近更新 更多