为什么从 2D 线切换到 3D 线时最小二乘线性回归的表现如此糟糕?

数据挖掘 Python 线性回归
2021-09-28 14:22:08

最小二乘的系数向量可以这样找到:

beta = ((X'X)^-1)*X'y

理论上,这个结果对于任意数量的变量(X 列)都是正确的。

我制作了两个 Python 笔记本:一个用于单变量线性回归,另一个用于多元线性回归

两个笔记本的代码类似:

  • 创建一条随机线
# multivariate snippet. A part from the plotting part,
# this is the only part of the code that differs between the two notebooks.
beta = np.random.randint(1,6,(3,))
X = np.linspace([1, 3, 7],[1, 14, 23],100)
y = X @ beta
  • 制造噪音
mu, sigma = 0, 1
noise = np.random.normal(mu, sigma, 100)
  • 为 y 添加噪声
y_noise = y + noise
  • 尝试通过 y_noise 拟合一条线
beta_ = np.linalg.inv(X.T @ X) @ X.T @ y_noise
y_ = X @ beta_
  • 比较 y_ 和 y_noise

为什么在拟合 2D 线和 3D 线时会得到如此不同的结果?

1个回答

矩阵XTX在您的示例中接近单数:

from numpy.linalg import inv, det

print(det(X.T @ X))

1.479949989718308e-06

这使得它的逆非常大

inv(X.T @ X)

[[ 4.83118746e+11  2.66548273e+11 -1.83251938e+11]
 [ 2.66548273e+11  1.47061116e+11 -1.01104517e+11]
 [-1.83251938e+11 -1.01104517e+11  6.95093558e+10]]

这是您问题中错误的原因。下面的表达式

inv(X.T @ X) @ X.T @ X

应该产生一个单位矩阵。但在你的例子中

[[ 1.2265625   1.10289171  4.8378709 ]
 [ 0.02282715  0.61713325  0.95782902]
 [-0.01519775  0.25675456  0.33339437]] 

因此,当您将此矩阵乘以beta结果时,结果远非beta.

另一种看待这个奇点的方法是你的 3D 问题实际上不是 3D。它仍然是二维的。这就是为什么您的绘图中有一条线,而不是二维曲面。它可以通过坐标变换转换为二维表示。如果您为适当的 3D 问题制作矩阵,请说

np.random.seed(3)
X = np.hstack((np.ones((100,1)),np.random.rand(100,2)*100))

然后inv(X.T @ X) @ X.T @ X给出正确的结果:

[[ 1.00000000e+00 -1.24233956e-13 -6.21724894e-14]
 [-1.90819582e-17  1.00000000e+00  6.38378239e-16]
 [-8.67361738e-18  9.28077060e-16  1.00000000e+00]]

和公式β=(XTX)1XTy效果很好。