Regulación de parametrización del ángulo de rotación


15

Digamos que tengo una imagen de arriba hacia abajo de una flecha, y quiero predecir el ángulo que forma esta flecha. Esto sería entre 0 0 y 360 grados, o entre y . El problema es que este objetivo es circular, y grados son exactamente lo mismo, lo que es una invariancia que me gustaría incorporar en mi objetivo, lo que debería ayudar a la generalización de manera significativa (esta es mi suposición). El problema es que no veo una forma limpia de resolver esto, ¿hay algún documento que intente abordar este problema (o similares)? Tengo algunas ideas con sus posibles desventajas:0 00 3602π0 0360

  • Use una activación sigmoide o tanh, escale al rango ( e incorpore la propiedad circular en la función de pérdida. Creo que esto fallará bastante, porque si está en la frontera (peor predicción), solo un poco de ruido empujará a los pesos a ir de una manera u otra. Además, los valores más cercanos al borde de y serán más difíciles de alcanzar porque el valor absoluto de preactivación deberá estar cerca del infinito.0 2 π0 0,2π)0 02π

  • Regrese a dos valores, un valor e , y calcule la pérdida en función del ángulo que forman estos dos valores. Creo que este tiene más potencial, pero la norma de este vector es ilimitada, lo que podría conducir a una inestabilidad numérica y podría llevar a explosiones o ir a 0 durante el entrenamiento. Potencialmente, esto podría resolverse utilizando algún regularizador extraño para evitar que esta norma se aleje demasiado de 1.yXy

Otras opciones serían hacer algo con las funciones seno y coseno, pero creo que el hecho de que las preactivaciones múltiples se asignen a la misma salida también dificultará la optimización y las generalizaciones.


Honestamente, creo que tratar de predecir la rotación total será más fácil y obtener mejores resultados. Puede asignar desde, por ejemplo, a después del hecho si lo desea. Intentar predecir el ángulo en el círculo unitario después de las multiplicaciones es esencialmente tratar de predecir el resto después de dividir por , y no puedo ver cómo eso sería más fácil que predecir la magnitud general y luego restar múltiplos de . π3ππ2 π2π2π
tom

1
Las opciones son a) escalonar la periodicidad: estimar el pecado y el cos del ángulo usando una función de activación sigmoidea. b) incorporar la simetría en la función de pérdida a través de un núcleo como este . Lea sobre los grupos de rotación y la tesis de Taco Cohen sobre los grupos de transformación del aprendizaje . Lamentablemente, no conozco la teoría de grupos, por lo que no puedo ayudar mucho más.
Emre

@tom Lo que pasa con ese enfoque es que hay preactivaciones infinitas que se asignan al mismo ángulo mientras no tienen nada en común. Mientras que un x1 positivo siempre se refiere a un ángulo entre -1/2 y 1 \ 2 π . Y Emre, trabajaré en la teoría de grupos, siempre me ha interesado, por lo que la combinación de ML y teoría de grupos me atraeráππ
Jan van der Vegt

Respuestas:


15

La segunda forma, predecir e y = s i n ( α ) está totalmente bien.X=Cos(α)y=sin(α)

Sí, no se garantiza que la norma del vector predicho esté cerca de 1 . Pero no es probable que explote, especialmente si usa funciones de activación sigmoideas (que están limitadas por su naturaleza) y / o regulariza bien su modelo. ¿Por qué debería su modelo predecir un valor grande, si todas las muestras de entrenamiento se encontraban en [ - 1 , 1 ] ?(x,y)1[1,1]

Otro lado es el vector demasiado cerca de ( 0 , 0 ) . Esto puede suceder a veces y, de hecho, podría predecir ángulos incorrectos. Pero puede verse como un beneficio de su modelo: puede considerar la norma de ( x , y ) como una medida de confianza de su modelo. De hecho, una norma cercana a 0 significa que su modelo no está seguro de dónde está la dirección correcta.(X,y)(0 0,0 0)(X,y)

Aquí hay un pequeño ejemplo en Python que muestra que es mejor predecir pecado y cos, que predecir el ángulo directamente:

# 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

Puede continuar y trazar las predicciones, para ver que las predicciones del modelo seno-coseno son casi correctas, aunque puede necesitar alguna calibración adicional:

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

ingrese la descripción de la imagen aquí

πnorte2αcos(α)pecado(α)z=pecado(α+π4 4)w=cos(α+π4 4)

(X,y)(z,w)(X,y)arctan2


Esto es perfecto, muchas gracias. Lo investigaré más, voy a necesitar extenderlo a más dimensiones
Jan van der Vegt

2

Trabajar con coordenadas cartesianas funciona bien como se mencionó anteriormente. Sin embargo, en mi opinión, la conversión de datos polares a cartesiano crea dependencias entre las coordenadas X e Y que originalmente no estaban presentes en los datos. Por ejemplo, el modelo de decisión de trayectoria de un robot es más intuitivo en coordenadas polares que el cartesiano. La dependencia del vector de velocidad del robot en coordenadas polares entre el ángulo y la magnitud podría incluso no existir o ser diferente de la dependencia en coordenadas cartesianas.

Una solución alternativa que he encontrado para seguir trabajando con coordenadas polares es crear una función de error personalizada para calcular la diferencia de ángulo usando la función angdiff () en MATLAB y la diferencia de magnitud como de costumbre.

Esta función devuelve '0' para la diferencia entre -pi y pi. Aquí hay un enlace a la página de soporte de funciones en el sitio web de Mathworks.

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

Si está utilizando la activación Sigmoid y sus datos de ángulos se normalizan entre [0,1], debe devolverlos al rango [-pi, pi] antes de usar la función angdiff () y luego normalizar el error nuevamente a [0,1 ] rango para el proceso de retropropagación.

Además, la función equivalente en Python sería:

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

Esto devuelve resultados similares a los de la función MATLAB y también funciona con matrices:

[ 1.5708 -0.7854 -3.1416]
0.0
0.0

Espero que ayude.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.