Параметризаційна регресія кута повороту


15

Скажімо, у мене зображення стрілки зверху вниз, і я хочу передбачити кут цієї стрілки. Це буде від до 360 градусів, або від 0 до 2 π . Проблема полягає в тому, що ця ціль кругла, 0 і 360 градусів точно така ж, і це інваріантність, яку я хотів би включити в свою ціль, яка повинна суттєво допомогти узагальненню (це моє припущення). Проблема полягає в тому, що я не бачу чіткого способу вирішення цього питання, чи є документи, які намагаються вирішити цю проблему (чи подібні)? У мене є кілька ідей з їх потенційними недоліками:036002π0360

  • Використовуйте активацію сигмоїда чи тана, масштабуйте його до діапазону ( та включіть у функцію втрати кругову властивість. Я думаю, що це вийде досить важко, тому що якщо це буде на кордоні (найгірший прогноз), лише невеликий шум буде штовхати ваги в той чи інший бік. Також значення, ближче до кордону 0 і 2 π, буде важче досягти, оскільки абсолютне значення попередньої активації потрібно буде близько до нескінченного.0,2π)02π

  • Регресуйте до двох значень, значень та y та обчисліть втрати на основі кута цих двох значень. Я думаю, що цей потенціал має більше, але норма цього вектора є необмеженою, що може призвести до числової нестабільності і може призвести до вибухів або підняття до 0 під час тренування. Це потенційно може бути вирішено, використовуючи якийсь дивний регуляризатор, щоб запобігти надходженню цієї норми від 1.ху

Інші варіанти можуть робити щось із функціями синуса та косинуса, але мені здається, що те, що декілька попередніх активацій відображаються на одному виході, також ускладнить оптимізацію та узагальнення.


Чесно кажучи, я думаю, що спроба передбачити загальне обертання буде простішою та принесе вам кращі результати. Ви можете зробити карту від, наприклад, до π після факту, якщо ви хочете. Намагання передбачити кут на одиничне коло після множення по суті намагається передбачити залишок після ділення на 2 π , і я не бачу, як це було б простіше, ніж передбачити загальну величину і потім відняти кратні 2 π . 3ππ2π2π
Том

1
Варіантами є а) бічний крок періодичності: оцініть sin та cos кута за допомогою сигмовидної функції активації. б) включити симетрію у функцію втрати через ядро так . Читайте про групи ротації та тезу Така Коена про групи трансформації навчання . На жаль, я не знаю теорії груп, тому не можу допомогти набагато більше.
Емре

@tom Справа в цьому підході полягає в тому, що існує нескінченна попередня активація, яка відображається під тим же кутом, в той час як вони не мають нічого спільного. Тоді як позитивний x1 завжди відноситься до кута між -1/2 та 1 \ 2 π . І Емре, я буду працювати через деяку теорію групи, вона мене завжди цікавила, тому поєднання МЛ та теорії груп мені сподобаєтьсяππ
Ян ван дер Вегт

Відповіді:


15

Другий спосіб, прогнозуючи і y = s i n ( α ) , цілком нормально.х=cос(α)у=сiн(α)

Так, норма прогнозованого вектора не гарантована як близька до 1 . Але це, швидше за все, не вибухне, особливо якщо ви використовуєте функції активації сигмоїдів (які обмежені за своєю природою) та / або добре регулюєте модель. Чому ваша модель повинна передбачати велике значення, якщо всі навчальні зразки були в [ - 1 , 1 ] ?(х,у)1[-1,1]

Інша сторона - вектор занадто близький до ( 0 , 0 ) . Іноді це може статися і справді може призвести до прогнозування неправильних ракурсів. Але це може розглядатися як користь вашої моделі - ви можете розглядати норму ( x , y ) як міру впевненості вашої моделі. Дійсно, норма, близька до 0, означає, що ваша модель не впевнена, де правильний напрямок.(х,у)(0,0)(х,у)

Ось невеликий приклад в Python, який показує, що краще передбачити гріх і cos, що передбачити кут безпосередньо:

# 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=гріх(α+π4)ш=cos(α+π4)

(х,у)(z,ш)(х,у)arctan2


Це ідеально, спасибі велике. Я детальніше розглядаю це, мені потрібно буде розширити його на інші виміри
Jan van der Vegt

2

Робота з декартовими координатами працює добре, як було сказано вище. Однак, на мій погляд, перетворення полярних даних в декартові створює залежності між координатами X і Y, які спочатку не були в даних. Наприклад, модель рішення маршруту робота більш інтуїтивна в полярних координатах, ніж декартова. Залежність вектора швидкості роботи від полярних координат між кутом і величиною може навіть не існувати або бути різною, ніж залежність декартових координат.

Обхід, який я знайшов, щоб продовжувати працювати з полярними координатами, - це створити власну функцію помилок для обчислення різниці кутів за допомогою функції angdiff () у MATLAB та різниці величин, як зазвичай.

Ця функція повертає "0" для різниці між -pi та pi. Ось посилання на сторінку підтримки функцій на веб-сайті Mathworks.

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

Якщо ви використовуєте активацію Sigmoid, і ваші дані кутів нормалізуються між [0,1], слід повернути їх до діапазону [-pi, pi] перед використанням функції angdiff (), а потім нормалізувати помилку назад до [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

Сподіваюся, що це допомагає.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.