การถดถอยแบบปรับพารามิเตอร์ของมุมการหมุน


15

สมมติว่าฉันมีรูปลูกศรจากบนลงล่างและฉันต้องการทำนายมุมที่ลูกศรนี้สร้างขึ้น นี้จะอยู่ระหว่างและองศาหรือระหว่างและ2ปัญหาคือเป้าหมายนี้มีลักษณะเป็นวงกลมและองศาเหมือนกันทุกประการซึ่งเป็นค่าคงที่ที่ฉันต้องการรวมไว้ในเป้าหมายของฉันซึ่งจะช่วยให้การวางนัยทั่วไปเป็นนัยสำคัญ (นี่คือสมมุติฐานของฉัน) ปัญหาคือฉันไม่เห็นวิธีการแก้ปัญหานี้ที่สะอาดมีเอกสารใดบ้างที่พยายามแก้ไขปัญหานี้ (หรือสิ่งที่คล้ายกัน)? ฉันมีความคิดบางอย่างกับข้อเสียที่เป็นไปได้:036002π0360

  • ใช้การเปิดใช้งาน sigmoid หรือ tanh ปรับขนาดเป็นช่วง (และรวมคุณสมบัติแบบวงกลมในฟังก์ชันการสูญเสีย ฉันคิดว่าสิ่งนี้จะล้มเหลวอย่างหนักเพราะถ้าอยู่บนเส้นขอบ (การคาดคะเนที่เลวร้ายที่สุด) เพียงเสียงเล็ก ๆ เท่านั้นที่จะผลักดันให้น้ำหนักไปทางใดทางหนึ่ง นอกจากนี้ค่าที่ใกล้กับชายแดนของและจะเข้าถึงได้ยากขึ้นเนื่องจากค่าการเปิดใช้งานแบบสัมบูรณ์จะต้องใกล้เคียงกับอนันต์0,2π)02π

  • ถอยกลับไปที่ค่าสองค่า aและและคำนวณการสูญเสียตามมุมทั้งสองค่าทำ ฉันคิดว่าอันนี้มีศักยภาพมากกว่า แต่บรรทัดฐานของเวกเตอร์นี้ไม่มีขอบเขตซึ่งอาจนำไปสู่ความไม่แน่นอนของตัวเลขและอาจนำไปสู่การระเบิดหรือเป็น 0 ในระหว่างการฝึก สิ่งนี้สามารถแก้ไขได้โดยใช้ regularizer แปลก ๆ เพื่อป้องกันบรรทัดฐานนี้ไม่ให้อยู่ห่างจาก 1 มากเกินไปyxy

ตัวเลือกอื่น ๆ กำลังทำอะไรบางอย่างกับฟังก์ชั่นไซน์และโคไซน์ แต่ฉันรู้สึกเหมือนความจริงที่ว่าแผนที่การเปิดใช้งานล่วงหน้าหลายรายการไปยังเอาต์พุตเดียวกันจะทำให้การเพิ่มประสิทธิภาพและการสรุปทั่วไปทำได้ยากมาก


สุจริตฉันคิดว่าพยายามทำนายการหมุนทั้งหมดจะง่ายขึ้นและให้ผลลัพธ์ที่ดีกว่า คุณสามารถแมปจากถึงหลังจากข้อเท็จจริงหากคุณต้องการ การพยายามทำนายมุมบนหน่วยวงกลมหลังจากการคูณคือการพยายามทำนายส่วนที่เหลือหลังจากหารด้วยและฉันไม่เห็นว่ามันจะง่ายกว่าการทำนายขนาดโดยรวมแล้วลบการคูณของ . เธ3ππ2 π2π2π
ทอม

1
ตัวเลือกคือ a) ขั้นตอนด้านเป็นระยะ: ประมาณบาปและ cos ของมุมโดยใช้ฟังก์ชั่นการเปิดใช้งาน sigmoid ข) รวมสมมาตรเข้าสู่ฟังก์ชั่นการสูญเสียที่ผ่านการเคอร์เนลเช่นดังนั้น อ่านข้อมูลเกี่ยวกับกลุ่มการหมุนและวิทยานิพนธ์ Taco โคเฮนในการเรียนรู้กลุ่มการเปลี่ยนแปลง น่าเสียดายที่ฉันไม่มีความรู้เกี่ยวกับทฤษฎีกลุ่มดังนั้นฉันจึงไม่สามารถช่วยได้มากขึ้น
Emre

@tom สิ่งที่เกี่ยวกับวิธีการนี้คือมีการเปิดใช้งานล่วงหน้าที่ไม่มีที่สิ้นสุดซึ่งแมปไปที่มุมเดียวกันในขณะที่พวกเขาไม่มีอะไรเหมือนกัน ในขณะที่ x1 บวกเสมอหมายถึงมุมระหว่าง -1/2 และ 1 \ 2 π และ Emre ฉันจะทำงานของฉันผ่านทฤษฎีกลุ่มบางอย่างมันให้ความสนใจฉันเสมอดังนั้นการรวมกันของ ML และทฤษฎีกลุ่มจะดึงดูดฉันππ
Jan van der Vegt

คำตอบ:


15

วิธีที่สองการทำนายและy = s i n ( α )ก็โอเคโดยสิ้นเชิงx=โอs(α)Y=sผมn(α)

ใช่บรรทัดฐานของการคาดการณ์เวกเตอร์ไม่รับประกันว่าจะได้อยู่ใกล้1 แต่มันก็ไม่น่าจะเกิดขึ้นโดยเฉพาะอย่างยิ่งถ้าคุณใช้ฟังก์ชั่นการเปิดใช้งาน sigmoid (ซึ่งถูก จำกัด โดยธรรมชาติ) และ / หรือทำให้โมเดลของคุณเป็นปกติ ทำไมรูปแบบของคุณควรคาดการณ์ค่าขนาดใหญ่หากทุกตัวอย่างการฝึกอบรมอยู่ใน[ - 1 , 1 ] ?(x,Y)1[-1,1]

อีกด้านหนึ่งเป็นเวกเตอร์ใกล้เกินไปที่( 0 , 0 ) บางครั้งสิ่งนี้อาจเกิดขึ้นและอาจส่งผลในการทำนายมุมที่ผิด แต่มันอาจถูกมองว่าเป็นประโยชน์ของแบบจำลองของคุณ - คุณสามารถพิจารณาบรรทัดฐานของ( x , y )เป็นเครื่องวัดความมั่นใจของแบบจำลองของคุณ จริง ๆ แล้วค่ามาตรฐานใกล้กับ 0 หมายความว่าแบบจำลองของคุณไม่แน่ใจว่าทิศทางที่ถูกต้องอยู่ที่ใด(x,Y)(0,0)(x,Y)

นี่คือตัวอย่างเล็ก ๆ ใน 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();

ป้อนคำอธิบายรูปภาพที่นี่

πยังไม่มีข้อความ2αcos(α)บาป(α)Z=บาป(α+π4)W=cos(α+π4)

(x,Y)(Z,W)(x,Y)arctan2


มันสมบูรณ์แบบขอบคุณมาก ฉันจะดูมันให้มากขึ้นฉันจะต้องขยายมันให้กว้างขึ้น
ม.ค. 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 ช่วง] สำหรับกระบวนการ backpropagation

นอกจากนี้ฟังก์ชันเทียบเท่าใน 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

หวังว่าจะช่วย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.