Parametrierungsregression des Drehwinkels

15

Angenommen, ich habe ein Bild von oben nach unten von einem Pfeil und möchte den Winkel vorhersagen, den dieser Pfeil bildet. Dies wäre zwischen und 360 Grad oder zwischen 0 und 2 π . Das Problem ist, dass dieses Ziel kreisförmig ist, 0 und 360 Grad sind genau das gleiche, was eine Invarianz ist, die ich in mein Ziel integrieren möchte, was die Verallgemeinerung erheblich unterstützen sollte (dies ist meine Annahme). Das Problem ist, dass ich keinen sauberen Weg sehe, dies zu lösen. Gibt es Papiere, die versuchen, dieses Problem anzugehen (oder ähnliche)? Ich habe einige Ideen mit ihren möglichen Nachteilen:036002π0360

  • Verwenden Sie eine Sigmoid- oder Tanh-Aktivierung, skalieren Sie sie auf den Bereich ( und beziehen Sie die kreisförmige Eigenschaft in die Verlustfunktion ein. Ich denke, das wird ziemlich schwer scheitern, denn wenn es an der Grenze ist (schlechteste Vorhersage), wird nur ein kleines bisschen Lärm die Gewichte dazu bringen, in die eine oder andere Richtung zu gehen. Außerdem ist es schwieriger , Werte zu erreichen, die näher an der Grenze zwischen 0 und 2 π liegen, da der absolute Voraktivierungswert nahezu unendlich sein muss.0,2π)02π

  • Stellen Sie zwei Werte ein, einen und einen y- Wert, und berechnen Sie den Verlust basierend auf dem Winkel, den diese beiden Werte bilden. Ich denke, dieser hat mehr Potenzial, aber die Norm dieses Vektors ist unbegrenzt, was zu numerischer Instabilität und zu Explosionen oder 0 während des Trainings führen kann. Dies könnte möglicherweise durch die Verwendung eines seltsamen Regularisierers behoben werden, um zu verhindern, dass diese Norm zu weit von 1 abweicht.xy

Andere Optionen würden etwas mit Sinus- und Cosinusfunktionen zu tun haben, aber ich denke, dass die Zuordnung mehrerer Voraktivierungen zu demselben Ausgang auch die Optimierung und Verallgemeinerung sehr schwierig macht.

Jan van der Vegt
quelle
Ehrlich gesagt denke ich, dass der Versuch, die gesamte Rotation vorherzusagen , einfacher ist und Sie bessere Ergebnisse erzielen. Sie können zB bis abbilden , wenn Sie möchten. Der Versuch, den Winkel auf dem Einheitskreis nach Multiplikationen vorherzusagen, versucht im Wesentlichen, den Rest nach der Division durch vorherzusagen , und ich kann mir nicht vorstellen, wie das einfacher wäre, als die Gesamtgröße vorherzusagen und dann ein Vielfaches von abzuziehen . π 2 π 2 π3ππ2π2π
Tom
1
Folgende Optionen stehen zur Verfügung: a) Nebenschritt der Periodizität: Schätzen Sie Sinus und Cosinus des Winkels mithilfe einer Sigmoid-Aktivierungsfunktion. b) einzuarbeiten , die Symmetrie in die Verlustfunktion durch einen Kern , wie so . Lesen Sie mehr über Rotationsgruppen und Taco Cohens These zum Lernen von Transformationsgruppen . Leider kenne ich mich mit Gruppentheorie nicht aus, so dass ich nicht viel mehr helfen kann.
Emre
@tom Das Besondere an diesem Ansatz ist, dass es unendlich viele Voraktivierungen gibt, die demselben Winkel zugeordnet sind, obwohl sie nichts gemeinsam haben. Während sich ein positives x1 immer auf einen Winkel zwischen -1/2 und 1 \ 2 bezieht . Und Emre, ich werde mich durch eine Gruppentheorie arbeiten, die mich immer interessiert hat, also wird mich die Kombination von ML und Gruppentheorie ansprechenπππ
Jan van der Vegt,

Antworten:

15

Die zweite Möglichkeit, und y = s i n ( α ) vorherzusagen, ist völlig in Ordnung.x=cos(α)y=sin(α)

Ja, es ist nicht garantiert, dass die Norm des vorhergesagten Vektors in der Nähe von 1 liegt . Es ist jedoch unwahrscheinlich, dass es in die Luft geht, insbesondere wenn Sie Sigmoid-Aktivierungsfunktionen (die von Natur aus eingeschränkt sind) verwenden und / oder Ihr Modell gut regulieren. Warum sollte Ihr Modell einen großen Wert vorhersagen, wenn alle Trainingsmuster in [ - 1 , 1 ] waren ?(x,y)1[1,1]

Eine andere Seite ist der Vektor zu nahe an ( 0 , 0 ) . Dies kann manchmal vorkommen und dazu führen, dass falsche Winkel vorhergesagt werden. Dies kann jedoch als Vorteil Ihres Modells angesehen werden - Sie können die Norm von ( x , y ) als Maß für das Vertrauen Ihres Modells betrachten. In der Tat bedeutet eine Norm nahe 0, dass Ihr Modell nicht sicher ist, wo die richtige Richtung ist.(x,y)(0,0)(x,y)

Hier ist ein kleines Beispiel in Python, das zeigt, dass es besser ist, sin und cos vorherzusagen, den Winkel direkt vorherzusagen:

# 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

Sie können fortfahren und die Vorhersagen zeichnen, um zu sehen, dass die Vorhersagen des Sinus-Cosinus-Modells nahezu korrekt sind, obwohl möglicherweise eine weitere Kalibrierung erforderlich ist:

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();

Bildbeschreibung hier eingeben

πN2αcos(α)sin(α)z=sin(α+π4)w=cos(α+π4)

(x,y)(z,w)(x,y)arctan2

David Dale
quelle
Das ist perfekt, vielen Dank. Ich werde mehr darüber nachdenken, ich werde es auf weitere Dimensionen ausdehnen müssen
Jan van der Vegt
2

Das Arbeiten mit kartesischen Koordinaten funktioniert wie oben erwähnt. Meiner Meinung nach führt die Konvertierung von polaren Daten in kartesische Daten jedoch zu Abhängigkeiten zwischen den X- und Y-Koordinaten, die ursprünglich nicht in den Daten vorhanden waren. Beispielsweise ist das Bahnentscheidungsmodell eines Roboters in Polarkoordinaten intuitiver als kartesisch. Die Abhängigkeit des Geschwindigkeitsvektors des Roboters in Polarkoordinaten zwischen dem Winkel und der Größe besteht möglicherweise nicht einmal oder unterscheidet sich nicht von der Abhängigkeit in kartesischen Koordinaten.

Eine Problemumgehung, die ich gefunden habe, um weiterhin mit Polarkoordinaten zu arbeiten, besteht darin, eine benutzerdefinierte Fehlerfunktion zu erstellen, mit der die Winkeldifferenz mit der Funktion angdiff () in MATLAB und der Größenunterschied wie gewohnt berechnet werden.

Diese Funktion gibt '0' für die Differenz zwischen -pi und pi zurück. Hier ist ein Link zur Funktionsunterstützungsseite auf der Mathworks-Website.

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

Wenn Sie die Sigmoid-Aktivierung verwenden und Ihre Winkeldaten zwischen [0,1] normalisiert sind, sollten Sie sie vor Verwendung der Funktion angdiff () in den Bereich [-pi, pi] zurückführen und den Fehler dann wieder auf [0,1] normalisieren ] Bereich für den Backpropagation-Prozess.

Die äquivalente Funktion in Python wäre außerdem:

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))

Dies gibt ähnliche Ergebnisse wie die MATLAB-Funktion zurück und funktioniert auch mit Arrays:

[ 1.5708 -0.7854 -3.1416]
0.0
0.0

Ich hoffe, das hilft.

Stav Bar-Sheshet
quelle