2017-09-22 25 views
0

ケラス/テンソルフローを使用して方位角を予測しようとしています。 y_trueの範囲は0-359ですが、私はその範囲外にあり、包まれた予測を処理する損失関数が必要です。私はモジュラー部門tf.mod()または%のいずれかの種類をしようとすると、残念ながら、私はエラーを取得...360度予測のケラス損失関数

LookupError: No gradient defined for operation 'FloorMod' (op type: FloorMod) 

ので、私は次のようにこの問題を回避働いてきたと思います...

def mean_squared_error_360(y_true, y_pred): 
    delta = K.minimum(K.minimum(K.abs(y_pred - y_true), 
           K.abs(y_pred - (360+y_true))), 
           K.abs(y_true - (360+y_pred))) 
    return K.mean(K.square(delta), axis=-1) 

def rmse_360(y_true, y_pred): 
    return K.sqrt(mean_squared_error_360(y_true, y_pred)) 


model.compile(loss=mean_squared_error_360, 
       optimizer=rmsprop(lr=0.0001), 
       metrics=[rmse_360]) 

これは次のようなケースを処理します...私は予測に出くわしていないので、私はアドレッシングしていません。

y = 1 y_pred = 361 err = 0 
y = 359 y_pred = 1 err = 2 
y = 359 y_pred = 361 err = 2 

質問

  • これは不格好な感じ。スマートな解決策がありますか?
  • 直感的には、mean_squared_errorとroot_mean_squared_errorを損失として使用する場合の結果に違いはないと思います...勾配は異なりますが、同じ最適な重みが両方を解くでしょうか? 1つを選択する理由はありますか?私はmseがrmseよりやや簡単だと思いますが、それは簡単なはずです。私は両方を試してみましたが、rmseを使うと、mseよりも秩序だった降下のような感じがします...それらの二乗誤差の大きさについては何かありますか?

ありがとうございます。何らかの理由で

EDIT

...私のオリジナルMSEはトレーニングセットをフィットしているように見えますが、バリデーションセットは、いくつかのエポックの後に任意の実際の改善なしに、エポックにかなりうるさいエポックに見えました。 rmseはより秩序ある降下のように見えました...損失が数十エポックの間改善した後infになるまで。私は損失機能よりも大きな問題があるかもしれません。

EDIT 2 - 私の実装を追加するには、TRIG ...

ああ下に答える@Patwie !!もちろん!!残念ながら、私はtf.atan2()を持っていないtf v1.0を使用しています。不思議なことに、私はtfリポジトリでatan2の実装を見つけることができませんでしたが、問題6095のasos-benの提案がこのトリックを行うと思います。テスト実行の中https://github.com/tensorflow/tensorflow/issues/6095

def atan2(x, y, epsilon=1.0e-12): 
    x = tf.where(tf.equal(x, 0.0), x+epsilon, x) 
    y = tf.where(tf.equal(y, 0.0), y+epsilon, y)  
    angle = tf.where(tf.greater(x,0.0), tf.atan(y/x), tf.zeros_like(x)) 
    angle = tf.where(tf.logical_and(tf.less(x,0.0), tf.greater_equal(y,0.0)), tf.atan(y/x) + np.pi, angle) 
    angle = tf.where(tf.logical_and(tf.less(x,0.0), tf.less(y,0.0)), tf.atan(y/x) - np.pi, angle) 
    angle = tf.where(tf.logical_and(tf.equal(x,0.0), tf.greater(y,0.0)), 0.5*np.pi * tf.ones_like(x), angle) 
    angle = tf.where(tf.logical_and(tf.equal(x,0.0), tf.less(y,0.0)), -0.5*np.pi * tf.ones_like(x), angle) 
    angle = tf.where(tf.logical_and(tf.equal(x,0.0), tf.equal(y,0.0)), tf.zeros_like(x), angle) 
    return angle 

# y in radians 
def rmse_360_2(y_true, y_pred): 
    return K.mean(K.abs(atan2(K.sin(y_true - y_pred), K.cos(y_true - y_pred)))) 

のみ約7エポック、それが有望と思われる:ここを参照してください。

+1

ある角度が非常に低いか、または無効であるかどうかを確認します。もしそうなら、あなたはこの角度をゼロの中心に置くことができます.... –

答えて

1

私のコメントを回答に変換します。あなたが定義することによりtf.atan2

tf.atan2(tf.sin(a - b), tf.cos(a - b)) 

により角度差を取得ラジアンとして二つの角度(GT)、B(予測)を一定間隔-45、45度で自動的に差を与えます。

したがって、私はKerasこのTensorFlowコードを理解すると思う

tf.reduce_mean(tf.abs(tf.atan2(tf.sin(a - b), tf.cos(a - b)))) 

を使用することができます。

関連する問題