Regressione della parametrizzazione dell'angolo di rotazione


15

Diciamo che ho una foto dall'alto in basso di una freccia e voglio prevedere l'angolazione di questa freccia. Questo sarebbe tra e 360 gradi, o tra 0 e 2 π . Il problema è che questo obiettivo è circolare, 0 e 360 gradi sono esattamente gli stessi che è un'invarianza che vorrei incorporare nel mio obiettivo, il che dovrebbe aiutare in modo significativo la generalizzazione (questo è il mio presupposto). Il problema è che non vedo un modo chiaro per risolvere questo problema, ci sono dei documenti che provano ad affrontare questo problema (o simili)? Ho alcune idee con i loro potenziali lati negativi:036002π0360

  • Utilizzare un'attivazione sigmoide o tanh, ridimensionarla nell'intervallo ( e incorporare la proprietà circolare nella funzione di perdita. Penso che questo fallirà abbastanza duramente, perché se è al confine (peggiore previsione) solo un po 'di rumore spingerà i pesi per andare in un modo o nell'altro. Inoltre, i valori più vicini al bordo di 0 e 2 π saranno più difficili da raggiungere perché il valore di pre-attivazione assoluta dovrà essere vicino all'infinito.0,2π)02π

  • Regredire a due valori, una ed y di valore e calcolare la perdita in base all'angolo questi due valori fanno. Penso che questo abbia più potenziale, ma la norma di questo vettore è illimitata, il che potrebbe portare a instabilità numerica e potrebbe portare a scoppi o andare a 0 durante l'allenamento. Questo potrebbe essere potenzialmente risolto utilizzando uno strano regolarizzatore per impedire a questa norma di andare troppo lontano da 1.xy

Altre opzioni farebbero qualcosa con le funzioni seno e coseno, ma sento che il fatto che più pre-attivazioni si associno allo stesso output renderà anche molto difficili l'ottimizzazione e le generalizzazioni.


Sinceramente penso che provare a prevedere la rotazione totale sarà più facile e ottenere risultati migliori. Se lo si desidera, è possibile mappare ad esempio da a π dopo il fatto. Cercare di prevedere l'angolo sul cerchio unitario dopo le moltiplicazioni sta essenzialmente cercando di prevedere il resto dopo aver diviso per 2 π , e non riesco a vedere come sarebbe più facile che prevedere l'entità complessiva e sottrarre multipli di 2 π . 3ππ2π2π
Tom,

1
Le opzioni sono a) un passo laterale della periodicità: stimare il peccato e il cos dell'angolo usando una funzione di attivazione sigmoidea. b) incorporare la simmetria nella funzione di perdita attraverso un kernel in questo modo . Leggi i gruppi di rotazione e la tesi di Taco Cohen sull'apprendimento dei gruppi di trasformazione . Sfortunatamente non sono informato sulla teoria dei gruppi, quindi non posso aiutare molto di più.
Emre,

@tom La cosa su questo approccio è che ci sono infinite pre-attivazioni che mappano allo stesso angolo mentre non hanno nulla in comune. Mentre un x1 positivo si riferisce sempre ad un angolo compreso tra -1/2 e 1 \ 2 π . Ed Emre, mi occuperò della teoria dei gruppi, mi ha sempre interessato, quindi la combinazione di ML e teoria dei gruppi mi ππ
attirerà

Risposte:


15

Il secondo modo, prevedere e y = s iX=coS(α) è del tutto ok.y=Sion(α)

Sì, non è garantito che la norma del vettore previsto sia vicina a 1 . Ma è improbabile che esploda, specialmente se usi le funzioni di attivazione sigmoide (che sono delimitate dalla loro natura) e / o regolarizzi bene il tuo modello. Perché il tuo modello dovrebbe prevedere un valore elevato, se tutti i campioni di addestramento fossero in [ - 1 , 1 ] ?(x,y)1[1,1]

Un altro lato è il vettore troppo vicino a ( 0 , 0 ) . Questo a volte può accadere e può effettivamente comportare la previsione di angoli sbagliati. Ma può essere visto come un vantaggio del tuo modello. Puoi considerare la norma di ( x ,(x,y)(0,0) come una misura difiduciadel tuo modello. In effetti, una norma vicina a 0 significa che il tuo modello non è sicuro di dove sia la giusta direzione.(x,y)

Ecco un piccolo esempio in Python che mostra che è meglio prevedere sin e cos, che prevedere direttamente l'angolo:

# 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

Puoi continuare e tracciare le previsioni, per vedere che le previsioni del modello seno-coseno sono quasi corrette, anche se potrebbe essere necessaria un'ulteriore calibrazione:

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

inserisci qui la descrizione dell'immagine

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

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


Questo è perfetto, grazie mille. Lo esaminerò di più, dovrò estenderlo a più dimensioni
Jan van der Vegt,

2

Lavorare con le coordinate cartesiane funziona bene come menzionato sopra. Tuttavia, a mio avviso, la conversione di dati polari in cartesiani crea dipendenze tra le coordinate X e Y che non erano originariamente presenti nei dati. Ad esempio, il modello di decisione del percorso di un robot è più intuitivo in coordinate polari che cartesiano. La dipendenza del vettore di velocità del robot in coordinate polari tra l'angolo e la magnitudine potrebbe anche non esistere o essere diversa dalla dipendenza nelle coordinate cartesiane.

Una soluzione alternativa che ho trovato per continuare a lavorare con le coordinate polari è quella di creare una funzione di errore personalizzata per calcolare la differenza di angolo usando la funzione angdiff () in MATLAB e la differenza di grandezza come al solito.

Questa funzione restituisce '0' per la differenza tra -pi e pi. Ecco un collegamento alla pagina di supporto delle funzioni sul sito Web di Mathworks.

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

Se si utilizza l'attivazione di Sigmoid e i dati relativi agli angoli sono normalizzati tra [0,1], è necessario riportarli nell'intervallo [-pi, pi] prima di utilizzare la funzione angdiff () e quindi normalizzare l'errore di nuovo su [0,1 ] intervallo per il processo di backpropagation.

Inoltre, la funzione equivalente in Python sarebbe:

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

Ciò restituisce risultati simili alla funzione MATLAB e funziona anche con le matrici:

[ 1.5708 -0.7854 -3.1416]
0.0
0.0

Spero possa aiutare.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.