回転角のパラメーター化回帰


15

矢印のトップダウン画像があり、この矢印が作る角度を予測したいとします。これは間であろう及び度、又は間にと。問題は、このターゲットが円形であり、度と度がまったく同じであるということです。これは、ターゲットに組み込む不変性であり、一般化に大きく役立つはずです(これは私の仮定です)。問題は、これを解決する明確な方法が見当たらないということです。この問題(または同様のもの)に取り組む試みの論文はありますか?私はそれらの潜在的な欠点についていくつかのアイデアを持っています。036002π0360

  • 、シグモイド又はTANH活性化を使用する(それをスケーリング0,2π)の範囲と損失関数に円形のプロパティを組み込みます。境界線上にある場合(最悪の予測)、わずかなノイズのみが重みを何らかの方法で押し上げるため、これはかなり難しいと思います。また、近い方の境界に値02π絶対事前活性値が無限大に近いことが必要となるため、到達するのがより困難になります。

  • と 2つの値に回帰し、これらの2つの値がなす角度に基づいて損失を計算します。これにはもっと可能性があると思いますが、このベクトルの標準には制限がなく、数値の不安定性につながり、トレーニング中に爆発するか0になる可能性があります。これは、この規範が1から離れすぎないようにするために、奇妙なレギュラーを使用することで解決できる可能性があります。xy

他のオプションはサイン関数とコサイン関数で何かをすることですが、複数の事前アクティベーションが同じ出力にマッピングされると、最適化と一般化も非常に難しくなると思います。


正直なところ、回転を予測しようとする方が簡単で、より良い結果が得られると思います。あなたは、例えばからマッピングすることができますπあなたがしたい場合は事実の後に。乗算後の単位円上の角度を予測しようとすると、本質的に予測しようとしている残りので除算した後に2 π、と私はそれが全体的な大きさを予測した後の倍数減算するよりも容易であろうどのように見ることができない2 πを3ππ2π2π
トム

1
オプションは、a)周期性のサイドステップ:シグモイド活性化関数を使用して角度の正弦と余弦を推定します。b)そのようにカーネルを通して対称性を損失関数に組み込みます。ローテーショングループと、トランスフォーメーショングループの学習に関するTaco Cohenの論文を読んでください。残念なことに、私は集団理論について知識がないので、それ以上のことはできません。
エムレ

@tomこのアプローチについてのことは、共通のことはないが、同じ角度にマップする無限の事前アクティベーションがあるということです。一方で、正x1は常に-1/2の間の角度を指しと1個の\ 2 π。そして、エムレ、私はいくつかのグループ理論を進めていきます。常に興味を持っているので、MLとグループ理論の組み合わせが魅力的ですππ
Jan van der Vegt

回答:


15

2番目の方法、およびy = s i n α )の予測はまったく問題ありません。バツ=cosαy=snα

はい、予測ベクトルのノルムは1に近いことが保証されていません。しかし、特にシグモイド活性化関数(それらは自然に制限されている)を使用する場合、および/またはモデルを適切に正則化する場合、爆発する可能性はありません。なぜ、あなたのモデルは、すべての訓練サンプルがでた場合は、大きな値を予測する必要があり、[ - 1 1 ]バツy1[11]

別の側面は、ベクターである近すぎると0 0 。これは時々発生する可能性があり、実際に間違った角度を予測する可能性があります。しかし、それはあなたのモデルの利点とみなされるかもしれません-あなたのモデルの信頼性の尺度としてのノルムx y を考慮することができます。実際、0に近いノルムは、モデルが正しい方向がどこにあるのかわからないことを意味します。バツy00バツy

これは、sinとcosを予測する方が角度を直接予測する方が良いことを示すPythonの小さな例です。

# predicting the angle (in radians)
import numpy as np
from sklearn.neural_network import MLPRegressor
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import r2_score
# generate toy data
np.random.seed(1)
X = np.random.normal(size=(100, 2))
y = np.arctan2(np.dot(X, [1,2]), np.dot(X, [3,0.4]))
# simple prediction
model = MLPRegressor(random_state=42, activation='tanh', max_iter=10000)
y_simple_pred = cross_val_predict(model, X, y)
# transformed prediction
joint = cross_val_predict(model, X, np.column_stack([np.sin(y), np.cos(y)]))
y_trig_pred = np.arctan2(joint[:,0], joint[:,1])
# compare
def align(y_true, y_pred):
    """ Add or remove 2*pi to predicted angle to minimize difference from GT"""
    y_pred = y_pred.copy()
    y_pred[y_true-y_pred >  np.pi] += np.pi*2
    y_pred[y_true-y_pred < -np.pi] -= np.pi*2
    return y_pred
print(r2_score(y, align(y, y_simple_pred))) # R^2 about 0.57
print(r2_score(y, align(y, y_trig_pred)))   # R^2 about 0.99

次に、予測をプロットして、サイン-コサインモデルの予測がほぼ正しいことを確認しますが、さらにキャリブレーションが必要になる場合があります。

import matplotlib.pyplot as plt
plt.figure(figsize=(12, 3))
plt.subplot(1,4,1)
plt.scatter(X[:,0], X[:,1], c=y)
plt.title('Data (y=color)'); plt.xlabel('x1'); plt.ylabel('x2')
plt.subplot(1,4,2)
plt.scatter(y_simple_pred, y)
plt.title('Direct model'); plt.xlabel('prediction'); plt.ylabel('actual')
plt.subplot(1,4,3)
plt.scatter(y_trig_pred, y)
plt.title('Sine-cosine model'); plt.xlabel('prediction'); plt.ylabel('actual')
plt.subplot(1,4,4)
plt.scatter(joint[:,0], joint[:,1], s=5)
plt.title('Predicted sin and cos'); plt.xlabel('cos'); plt.ylabel('sin')
plt.tight_layout();

ここに画像の説明を入力してください

πN2αcosααz=α+π4w=cosα+π4

バツyzwバツyarctan2


これは完璧です、どうもありがとう。私は、私はより多くの次元に拡張することが必要に行くよ、もっとそれに見ていきます
Vegt DERヤンファンを

2

デカルト座標での作業は、上記のようにうまく機能します。しかし、私の意見では、極データをデカルトに変換すると、元々データに存在しなかったX座標とY座標の間に依存関係が作成されます。たとえば、ロボットの経路決定モデルは、デカルト座標よりも極座標でより直感的です。角度と大きさの間の極座標でのロボットの速度ベクトルの依存関係は存在しないか、デカルト座標の依存関係と異なる場合があります。

極座標での作業を継続することがわかった回避策は、MATLABのangdiff()関数と通常の大きさの差を使用して角度差を計算するカスタムエラー関数を作成することです。

この関数は、-piとpiの差に対して「0」を返します。Mathworks Webサイトの関数サポートページへのリンクを次に示します。

https://www.mathworks.com/help/robotics/ref/angdiff.html

Sigmoidアクティベーションを使用しており、角度データが[0,1]の間で正規化されている場合、angdiff()関数を使用する前に[-pi、pi]範囲に戻してから、エラーを[0,1 ]逆伝播プロセスの範囲。

さらに、Pythonの同等の関数は次のようになります。

import numpy as np


def angdiff(a, b):
    delta = np.arctan2(np.sin(b-a), np.cos(b-a))
    delta = np.around(delta, 4)  # Since np.sin(pi) result is 1.22e-16
    delta += 0.  # Since np.around return -0.
    return delta


pi = np.pi
a = np.asarray([pi/2, 3*pi/4, 0])
b = np.asarray([pi, pi/2, -pi])

print(angdiff(a, b))
print(angdiff(pi, -pi))
print(angdiff(-pi, pi))

これは、MATLAB関数と同様の結果を返し、配列でも機能します。

[ 1.5708 -0.7854 -3.1416]
0.0
0.0

お役に立てば幸いです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.