使用 np.polynomial.Polynomial
进行一元线性回归的一个注意事项¶
在使用 np.polynomial.Polynomial
进行一元线性回归时,未能得到预期的结果。经检查发现, Polynomial.fit()
会将数据缩放和平移到 window
参数上后,再进行回归估计。如果需要得到未缩放和平移的估计量,可以用 .convert().coef
。
构造模拟数据¶
我们首先构造一个简单的模拟数据:
很显然,将 \(x\) 和 \(y\) 进行一元线性回归后,得到的回归系数是 \(2\),截距是 \(0\)。
使用 np.polyfit
进行回归¶
我们使用 np.polyfit
进行回归,得到的结果是符合预期的:
使用 np.polynomial.Polynomial
进行回归¶
得到的结果是 \(6\) 和 \(4\),并不符合预期。
stackoverflow 的回答
指出,Polynomial.fit()
会将数据缩放和平移到 window
参数上后,再进行回归估计。
我们可以查看一下,默认的 window
参数是 array([-1., 1.])
:
为了理解 \(6\) 和 \(4\) 是如何得到的,下面我们手动将数据缩放和平移至 [-1., 1.]
。
缩放和平移的过程为:
其中:
- \(x\) 是原始值。
- \(x_{min}\) 和 \(x_{max}\) 是原始范围的最小值和最大值。
- \(a\) 和 \(b\) 是目标范围的最小值和最大值。
- \(x'\) 是缩放后的值。
def scale_and_shift(x, target_min=-1, target_max=1):
original_min = min(x)
original_max = max(x)
return np.array(
[
(i - original_min)
* (target_max - target_min)
/ (original_max - original_min)
+ target_min
for i in x
]
)
x = np.array([1, 2, 3, 4, 5])
scaled_x = scale_and_shift(x)
scaled_x
可以看到,[1, 2, 3, 4, 5]
经过缩放平移后变成了 [-1. , -0.5, 0. , 0.5, 1. ]
。
我们再针对下面的数据,用 np.polyfit
进行回归:
x = np.array([-1.0, -0.5, 0.0, 0.5, 1.0])
y = np.array([2, 4, 6, 8, 10])
np.polyfit(x, y, deg=1)
结果表明,将 [1, 2, 3, 4, 5]
经过缩放平移后变成 [-1. , -0.5, 0. , 0.5, 1. ]
,再与 \(y\) 进行回归,得到的回归系数是 \(4\),截距项是 \(6\)。这就是为什么之前使用 np.polynomial.Polynomial
进行回归会得到 array([6., 4.])
。
转换为未缩放平移的结果¶
如果我们希望得到未缩放平移时的回归结果,有三种实现方式。
.convert().coef
¶
第一种是使用 .convert().coef
:
x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 6, 8, 10])
np.polynomial.Polynomial.fit(x, y, deg=1).convert().coef
window=(x.min(), x.max())
¶
第二种是使用 window=(x.min(), x.max())
:
x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 6, 8, 10])
np.polynomial.Polynomial.fit(x, y, deg=1, window=(x.min(), x.max())).coef
domain=[]
¶
第三种是使用 domain=[]
:
x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 6, 8, 10])
np.polynomial.Polynomial.fit(x, y, deg=1, domain=[]).coef