2017-11-30 31 views
11

Kerasでこのメトリックを実装するにはどうすればよいですか?下の私のコードは間違った結果を与えます!私はEXPを経由して、前のログ(X + 1)の変換を元に戻すよ 注(X) - 1、また、負の予測は0にクリップされていますKerasカスタムRMSLEメトリック

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 

私は間違っていますか?ありがとう!

EDIT:設定axis=0は、正しい値に非常に近い値を示しているようですが、私が使用しているコードはすべてaxis=-1と思われます。

答えて

7

私は同じ問題に遭遇し、それを探し、ここに私は修正ビット後

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

を見つけたもので、これは、私のためKerasTensorFlowで実装rmsle_K方法を動作するようです。

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 
+0

ありがとうございますが、exp(x)-1変換はどうですか? – Fernando

+0

@Fernando私はあなたがその変換が必要だとは思わないがhttps://www.kaggle.com/wiki/RootMeanSquaredLogarithmicError – LYu

+0

私のモデルはlog(x + 1)に適合しているので、私はexp(x ) - 1を入力し、RMSLEを適用します。 – Fernando

3

numpyの実装でリスト(to_sum)を使用すると、numpyの配列の形状が(length,)であると思われます。

ケラスでは、axis=0axis=1の結果が異なるので、おそらく(length,1)のような形になります。

to_sumリストを作成するときにも、あなたがnumpyの実装でaxis=0から要素を取っていることを意味する、y[i]y_pred[i]を使用しています。

numpyの実装では、平均を計算するためのすべての値もsum(to_sum)に集計されます。したがって、K.meanにはaxisを実際に使用する必要はありません。

モデルの出力形状が(length,)または(length,1)の場合は、軸パラメータを渡さずにK.mean(value)を使用できます。

+0

を使用し、私は気づいたが、Kerasは同じ(Y、y_pred)ペアに対してわずかに異なる結果を与えています。なぜ私は考えていない。 – Fernando

関連する問題