第二种方法是完全可以预测和y = s i n (α )。x = c o s (α )ÿ= s i n (α )
是的,不能保证预测的向量的范数接近1。但这不太可能爆炸,特别是如果您使用S型激活函数(受其性质限制)和/或很好地规范化了模型。你的模型为什么要预测一个大的值,如果所有的训练样品在[ - 1 ,1 ]?(x ,y)1[ - 1 ,1 ]
另一侧是矢量太接近(0 ,0 )。这有时可能会发生,并且确实可能导致预测错误的角度。但这可能被视为模型的好处-您可以将(x ,y )的范数视为模型置信度的度量。实际上,接近0的范数意味着您的模型不确定正确的方向在哪里。(x ,y)(0 ,0 )(x ,y)
这是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(α )罪(α )ž= 罪(α + π4)w = cos(α + π4)
(x ,y)(z,w )(x ,y)arctan2