Regresja parametryzacji kąta obrotu


15

Powiedzmy, że mam strzałkę z góry na dół i chcę przewidzieć kąt, pod jakim ta strzała się tworzy. Będzie to od 0 do stopni lub od do . Problem polega na tym, że ten cel jest okrągły, i stopni są dokładnie takie same, co jest niezmiennością, którą chciałbym włączyć do mojego celu, co powinno znacznie pomóc w uogólnieniu (to moje założenie). Problem polega na tym, że nie widzę czystego sposobu rozwiązania tego problemu. Czy są jakieś dokumenty, które próbują rozwiązać ten problem (lub podobne)? Mam kilka pomysłów na temat ich potencjalnych wad:36002π0360

  • Użyj aktywacji sigmoidalnej lub tanh, przeskaluj ją do zakresu ( i włącz właściwość kołową do funkcji straty. Myślę, że to zawiedzie dość mocno, ponieważ jeśli jest na granicy (najgorsza prognoza), tylko niewielki hałas popchnie ciężary, aby przejść w jedną lub drugą stronę. Również wartości bliższe granicy i będą trudniejsze do osiągnięcia, ponieważ bezwzględna wartość przed aktywacją będzie musiała być bliska nieskończoności.0,2π)02π

  • Regres do dwóch wartości, i i oblicza stratę na podstawie kąta te dwie wartości wprowadzone. Myślę, że ten ma większy potencjał, ale norma tego wektora jest nieograniczona, co może prowadzić do niestabilności numerycznej i może prowadzić do wysadzenia lub do 0 podczas treningu. Można to potencjalnie rozwiązać za pomocą dziwnego regulizatora, aby zapobiec zbyt dużej oddaleniu tej normy od 1.yxy

Innymi opcjami byłyby robienie czegoś z funkcjami sinus i cosinus, ale wydaje mi się, że fakt, że wiele wstępnych aktywacji odwzorowuje na to samo wyjście, również utrudni optymalizację i uogólnienia.


Szczerze mówiąc, myślę, że próba przewidzenia całkowitego obrotu będzie łatwiejsza i zapewni lepsze wyniki. Możesz mapować od np. do π po fakcie, jeśli chcesz. Próba przewidywania kąta na kole jednostkowym po pomnożeniu jest zasadniczo próbą przewidzenia reszty po podzieleniu przez 2 π , i nie widzę, jak byłoby to łatwiejsze niż przewidywanie całkowitej wielkości, a następnie odjęcie wielokrotności 2 π . 3)ππ2)π2)π
tom

1
Dostępne są następujące opcje: a) krok boczny okresowość: oszacuj sin i cos kąta za pomocą funkcji aktywacji sigmoidalnej. b) włączyć symetrię do funkcji utraty przez jądro podobne do tego . Przeczytaj o grupach rotacyjnych i tezie Taco Cohena na temat uczenia się grup transformacyjnych . Niestety nie mam wiedzy na temat teorii grup, więc nie mogę nic więcej poradzić.
Emre

@tom To podejście polega na tym, że istnieją nieskończone wstępne aktywacje, które odwzorowują pod tym samym kątem, podczas gdy nie mają one ze sobą nic wspólnego. Podczas gdy dodatni x1 zawsze odnosi się do kąta między -1/2 a 1 \ 2 π . I Emre, przejdę przez teorię grup, zawsze mnie to interesowało, więc połączenie ML i teorii grup spodoba mi sięππ
Jan van der Vegt

Odpowiedzi:


15

Drugi sposób przewidywania i strony Y = s I n ( alfa ) jest zupełnie dobrze.x=doos(α)y=sjan(α)

Tak, nie można zagwarantować , że norma przewidywanego wektora będzie bliska 1 . Ale raczej nie wybuchnie, szczególnie jeśli użyjesz funkcji aktywacji sigmoidów (które są ograniczone przez ich naturę) i / lub dobrze uregulujesz swój model. Dlaczego model powinien przewidzieć dużą wartość, jeżeli wszystkie próbki szkoleniowe były w [ - 1 , 1 ] ?(x,y)1[-1,1]

Drugą stroną jest wektor zbyt blisko ( 0 , 0 ) . Może się to czasem zdarzyć i rzeczywiście może skutkować przewidywaniem niewłaściwych kątów. Ale może to być postrzegane jako korzyść twojego modelu - możesz rozważyć normę ( x , y ) jako miarę pewności swojego modelu. Rzeczywiście, norma bliska 0 oznacza, że ​​twój model nie jest pewien, gdzie jest właściwy kierunek.(x,y)(0,0)(x,y)

Oto mały przykład w Pythonie, który pokazuje, że lepiej przewidzieć grzech i cos, niż bezpośrednio przewidzieć kąt:

# 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

Możesz kontynuować i wykreślić prognozy, aby zobaczyć, że prognozy modelu sinus-cosinus są prawie prawidłowe, chociaż może wymagać dalszej kalibracji:

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

wprowadź opis zdjęcia tutaj

πN.2)αsałata(α)grzech(α)z=grzech(α+π4)w=sałata(α+π4)

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


To jest idealne, wielkie dzięki. Przyjrzę się temu bardziej, będę musiał rozszerzyć go na więcej wymiarów
Jan van der Vegt

2

Praca ze współrzędnymi kartezjańskimi działa dobrze, jak wspomniano powyżej. Jednak moim zdaniem konwersja danych biegunowych na kartezjański tworzy zależności między współrzędnymi X i Y, które nie były pierwotnie obecne w danych. Na przykład model decyzyjny ścieżki robota jest bardziej intuicyjny we współrzędnych biegunowych niż kartezjański. Zależność wektora prędkości robota od współrzędnych biegunowych między kątem a wielkością może nawet nie istnieć lub być inna niż zależność od współrzędnych kartezjańskich.

Obejście, które znalazłem, aby kontynuować pracę ze współrzędnymi biegunowymi, polega na utworzeniu niestandardowej funkcji błędu w celu obliczenia różnicy kątów za pomocą funkcji angdiff () w MATLAB i różnicy wielkości jak zwykle.

Ta funkcja zwraca „0” dla różnicy między -pi i pi. Oto link do strony wsparcia funkcji na stronie Mathworks.

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

Jeśli używasz aktywacji Sigmoid, a dane dotyczące kątów są znormalizowane między [0,1], powróć do zakresu [-pi, pi] przed użyciem funkcji angdiff (), a następnie normalizuj błąd z powrotem do [0,1 ] zakres dla procesu propagacji wstecznej.

Ponadto równoważną funkcją w Pythonie byłoby:

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

Zwraca podobne wyniki jak funkcja MATLAB i działa również z tablicami:

[ 1.5708 -0.7854 -3.1416]
0.0
0.0

Mam nadzieję, że to pomaga.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.