Huber Regressor returns 系数符号不一致
Huber Regressor returns inconsistent sign of coefficient
我一直在尝试对时间序列执行 Huber 回归 (sklearn.linear_model)。
我遇到了一个奇怪的现象:有时returns一个非常小的负系数,有时是正系数,尽管数字不断向上变化。
例如:
HuberRegressor(epsilon=1.35,max_iter=10000).fit(X=np.arange(12).reshape(-1,1),y=pd.Series([0,0,0,0,0,0,0,0,0,0,0,1])).coef_
array([3.1380359e-08])
HuberRegressor(epsilon=1.35,max_iter=10000).fit(X=np.arange(12).reshape(-1,1),y=pd.Series([0,0,0,0,0,0,0,0,0,0,0,2])).coef_
array([-2.20536164e-10])
HuberRegressor(epsilon=1.35,max_iter=10000000).fit(X=np.arange(12).reshape(-1,1),y=pd.Series([0,0,0,0,0,0,0,0,0,0,0,5])).coef_
array([7.63157014e-07])
HuberRegressor(epsilon=1.35,max_iter=10000).fit(X=np.arange(12).reshape(-1,1),y=pd.Series([0,0,0,0,0,0,0,0,0,0,0,248])).coef_
array([-4.49809127e-07])
所以,我所做的只是提高最后一个观察值 (1,2,5,248),但系数的符号却发生了变化。
由于这是 Huber 回归,1,3,5,248 都被识别为异常值,因为所有其他值都是零。我应该识别模型中的不同之处吗?
TL;DR
当调整您的示例以重现错误时,我感觉这是由于浮点算术错误造成的,因为您正在使用带浮点算术的数值算法评估零斜率。
浮点运算错误
如果用实数进行计算,得到错误的符号可能很奇怪,但这是浮点数的常见现象。
让您的 MCVE 适应:
import numpy as np
from sklearn import linear_model
u = 1
c = []
x = np.arange(12).reshape(-1,1)
for k in [0, 1, 2, 5, 25, 100, 200, 500, 1000]:
y = np.array([u]*(len(x)-1)+[k])
m = linear_model.HuberRegressor(tol=1e-16).fit(X=x, y=y)
c.append(m.coef_[0])
[-5.923749784709837e-09,
-4.9322755264475916e-11,
2.5190368660836694e-10,
8.3699110105873e-07,
-4.3671163925160265e-10,
1.2964166828133428e-08,
1.5063190859596705e-06,
1.5063100994140354e-06,
1.5063152932632047e-06]
我承认在这种情况下大多数 returned 数字通常太大而不能被视为零,但我仍然怀疑是这种情况,因为更改 tol
开关确实会影响结果并更改为非零斜率 return 预期结果。
工作用例
我们可以改变数据来评估单一斜率,我们得到以下结果:
c = []
x = np.arange(12).reshape(-1,1)
for k in [0, 1, 2, 5, 25, 100, 200, 500, 1000]:
y = np.array(list(x[:-1])+[k])
m = linear_model.HuberRegressor(tol=1e-16).fit(X=x, y=y)
c.append(m.coef_[0])
[0.9999999423436053,
0.9999991468916037,
0.9999999916835522,
0.9999999916837012,
1.0000000059171992,
1.000000006233575,
1.000000006237059,
1.000002303772441,
1.0000023037721706]
现在信息低于或高于单位,这是预期的结果。
我的直觉是:您执行的测试给出了一个奇怪的结果,因为它处于机器精度(可接受的零值)和算法精度具有相同幅度的边界,因此是不好的迹象。当系数的值明显大于算法精度时,该现象消失。
这是浮点运算的常见问题,需要开发人员设计 stable 和准确的算法,这是一项复杂的任务。涵盖它的许多方面的一个很好的参考是:
N. J. Higham. Accuracy and Stability of Numerical Algorithms. Society
for Industrial and Applied Mathematics, Philadelphia, PA, USA, second
edition, 2002. ISBN 0-89871-521-0
我的建议:你可以在 sklearn 上提出一个问题来强调这个观察,他们可能会在他们的单元测试套件中添加一个新的测试来处理这个特定的用例,并为你提供更多关于什么是在引擎盖下进行。
我一直在尝试对时间序列执行 Huber 回归 (sklearn.linear_model)。 我遇到了一个奇怪的现象:有时returns一个非常小的负系数,有时是正系数,尽管数字不断向上变化。
例如:
HuberRegressor(epsilon=1.35,max_iter=10000).fit(X=np.arange(12).reshape(-1,1),y=pd.Series([0,0,0,0,0,0,0,0,0,0,0,1])).coef_
array([3.1380359e-08])
HuberRegressor(epsilon=1.35,max_iter=10000).fit(X=np.arange(12).reshape(-1,1),y=pd.Series([0,0,0,0,0,0,0,0,0,0,0,2])).coef_
array([-2.20536164e-10])
HuberRegressor(epsilon=1.35,max_iter=10000000).fit(X=np.arange(12).reshape(-1,1),y=pd.Series([0,0,0,0,0,0,0,0,0,0,0,5])).coef_
array([7.63157014e-07])
HuberRegressor(epsilon=1.35,max_iter=10000).fit(X=np.arange(12).reshape(-1,1),y=pd.Series([0,0,0,0,0,0,0,0,0,0,0,248])).coef_
array([-4.49809127e-07])
所以,我所做的只是提高最后一个观察值 (1,2,5,248),但系数的符号却发生了变化。 由于这是 Huber 回归,1,3,5,248 都被识别为异常值,因为所有其他值都是零。我应该识别模型中的不同之处吗?
TL;DR
当调整您的示例以重现错误时,我感觉这是由于浮点算术错误造成的,因为您正在使用带浮点算术的数值算法评估零斜率。
浮点运算错误
如果用实数进行计算,得到错误的符号可能很奇怪,但这是浮点数的常见现象。
让您的 MCVE 适应:
import numpy as np
from sklearn import linear_model
u = 1
c = []
x = np.arange(12).reshape(-1,1)
for k in [0, 1, 2, 5, 25, 100, 200, 500, 1000]:
y = np.array([u]*(len(x)-1)+[k])
m = linear_model.HuberRegressor(tol=1e-16).fit(X=x, y=y)
c.append(m.coef_[0])
[-5.923749784709837e-09,
-4.9322755264475916e-11,
2.5190368660836694e-10,
8.3699110105873e-07,
-4.3671163925160265e-10,
1.2964166828133428e-08,
1.5063190859596705e-06,
1.5063100994140354e-06,
1.5063152932632047e-06]
我承认在这种情况下大多数 returned 数字通常太大而不能被视为零,但我仍然怀疑是这种情况,因为更改 tol
开关确实会影响结果并更改为非零斜率 return 预期结果。
工作用例
我们可以改变数据来评估单一斜率,我们得到以下结果:
c = []
x = np.arange(12).reshape(-1,1)
for k in [0, 1, 2, 5, 25, 100, 200, 500, 1000]:
y = np.array(list(x[:-1])+[k])
m = linear_model.HuberRegressor(tol=1e-16).fit(X=x, y=y)
c.append(m.coef_[0])
[0.9999999423436053,
0.9999991468916037,
0.9999999916835522,
0.9999999916837012,
1.0000000059171992,
1.000000006233575,
1.000000006237059,
1.000002303772441,
1.0000023037721706]
现在信息低于或高于单位,这是预期的结果。
我的直觉是:您执行的测试给出了一个奇怪的结果,因为它处于机器精度(可接受的零值)和算法精度具有相同幅度的边界,因此是不好的迹象。当系数的值明显大于算法精度时,该现象消失。
这是浮点运算的常见问题,需要开发人员设计 stable 和准确的算法,这是一项复杂的任务。涵盖它的许多方面的一个很好的参考是:
N. J. Higham. Accuracy and Stability of Numerical Algorithms. Society for Industrial and Applied Mathematics, Philadelphia, PA, USA, second edition, 2002. ISBN 0-89871-521-0
我的建议:你可以在 sklearn 上提出一个问题来强调这个观察,他们可能会在他们的单元测试套件中添加一个新的测试来处理这个特定的用例,并为你提供更多关于什么是在引擎盖下进行。