旋转角度的参数化回归


15

假设我有一个自上而下的箭头图片,并且我想预测该箭头所成的角度。这将在到度之间,或者在到。问题在于该目标是圆形的,度和度是完全相同的,这是我希望在目标中纳入的不变性,这将有助于显着地推广(这是我的假设)。问题是我没有找到解决这个问题的干净方法,是否有任何论文试图解决这个问题(或类似的问题)?对于它们的潜在缺点,我确实有一些想法:036002π0360

  • 使用S形或tanh激活,将其缩放到(范围,并将圆形属性合并到损失函数中。我认为这将相当困难,因为如果它在边界上(最差的预测),则只有很小的噪音会推动砝码向另一方向移动。而且,更接近于和边界的值将更难达到,因为绝对预激活值将需要接近无穷大。0,2π)02π

  • 回归到和这两个值,并根据这两个值所成的角度计算损耗。我认为这有更大的潜力,但此向量的范数不受限制,这可能会导致数值不稳定,并可能导致训练过程中爆炸或趋于零。可以通过使用一些怪异的正则化函数来防止此规范离1太远,从而解决此问题。xy

其他选项可能会对正弦和余弦函数有所帮助,但我感觉到这样的事实,即多个预激活映射到相同的输出也会使优化和泛化变得非常困难。


老实说,我认为尝试预测旋转会更容易,并且可以获得更好的结果。如果需要,您可以在事实之后从例如映射到。试图在乘法后预测单位圆上的角度本质上是在预测除以之后的余数,我看不出这比预测总体幅度然后减去倍数更容易。3ππ2 π2π2π
tom

1
选项是:a)避免周期性:使用S形激活函数估算角度的正弦和余弦。b)像这样通过核将对称性纳入损失函数。阅读轮换小组塔可·科恩(Taco Cohen)关于学习转变小组的论文。不幸的是,我对群体理论不了解,所以我无能为力。
Emre's

@tom关于这种方法的事情是,有无限的预激活可以映射到相同的角度,而它们之间没有共同之处。而正X1总是指的角度之间-1/2 1和\ 2 π。而且Emre,我将通过一些小组理论努力工作,它一直使我感兴趣,因此ML和小组理论的结合将吸引我ππ
Jan van der Vegt

Answers:


15

第二种方法是完全可以预测y = s i n α X=CØsαÿ=s一世ñα

是的,不能保证预测的向量的范数接近1。但这不太可能爆炸,特别是如果您使用S型激活函数(受其性质限制)和/或很好地规范化了模型。你的模型为什么要预测一个大的值,如果所有的训练样品在[ - 1 1 ]Xÿ1[-11]

另一侧是矢量太接近0 0 。这有时可能会发生,并且确实可能​​导致预测错误的角度。但这可能被视为模型的好处-您可以将x y )的范数视为模型置信度的度量。实际上,接近0的范数意味着您的模型不确定正确的方向在哪里。Xÿ00Xÿ

这是Python中的一个小示例,它表明预测正弦和余弦,直接预测角度更好:

# 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ααž=α+π4w=cosα+π4

XÿžwXÿarctan2


非常完美,非常感谢。我会对其进行更多研究,我需要将其扩展到更大的维度
Jan van der Vegt

2

如上所述,使用笛卡尔坐标可以很好地工作。但是,在我看来,将极坐标数据转换为笛卡尔坐标会在X和Y坐标之间创建依赖关系,而这些依赖关系最初并不存在于数据中。例如,机器人的路径决策模型在极坐标下比直角坐标系更直观。机器人速度矢量在角度和大小之间的极坐标中的依赖性甚至可能不存在或不同于笛卡尔坐标中的依赖性。

我发现可以继续使用极坐标的一种解决方法是创建一个自定义误差函数,以使用MATLAB中的angdiff()函数和通常的幅度差来计算角度差。

对于-pi和pi之间的差异,此函数返回“ 0”。这是Mathworks网站上功能支持页面的链接。

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

如果您正在使用Sigmoid激活,并且角度数据在[0,1]之间进行了归一化,则应在使用angdiff()函数之前将其返回到[-pi,pi]范围,然后将误差归一化为[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

希望能有所帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.