Numpy 最小二乘法:正态方程与奇异值分解

Numpy 最小二乘法:正态方程与奇异值分解,numpy,linear-regression,least-squares,svd,Numpy,Linear Regression,Least Squares,Svd,我试着编写我自己的线性回归代码,遵循正常方程beta=inv(X'X)X'Y。但是,平方误差远大于numpy.linalg中的lstsq函数。有谁能向我解释一下为什么SVD方法(lstsq使用)比正态方程更精确?谢谢我怀疑矩阵X'X对您的数据有很高的敏感性。试图计算这样一个矩阵的数值逆会导致很大的误差。显式计算逆矩阵通常是个坏主意(例如,请参见或) 您可以使用检查条件编号 这里有一个例子。首先创建X和Y: In [186]: X = np.random.randn(500, 30) In [1

我试着编写我自己的线性回归代码,遵循正常方程
beta=inv(X'X)X'Y
。但是,平方误差远大于
numpy.linalg
中的
lstsq
函数。有谁能向我解释一下为什么SVD方法(lstsq使用)比正态方程更精确?谢谢

我怀疑矩阵
X'X
对您的数据有很高的敏感性。试图计算这样一个矩阵的数值逆会导致很大的误差。显式计算逆矩阵通常是个坏主意(例如,请参见或)

您可以使用检查条件编号

这里有一个例子。首先创建
X
Y

In [186]: X = np.random.randn(500, 30)

In [187]: Y = np.linspace(0, 1, len(X))
对于此随机
X
,条件编号不大:

In [188]: np.linalg.cond(X.T.dot(X))
Out[188]: 2.4456380658308148
正常方程和
lstsq
给出了相同的结果(根据使用该函数的默认参数):

现在通过使两列几乎相同来调整
X
。这使得
X'X
几乎是单数,并给出了一个很大的条件数:

In [192]: X[:,0] = X[:,1] + 1e-8*np.random.randn(len(X))

In [193]: np.linalg.cond(X.T.dot(X))
Out[193]: 3954529794300611.5
现在,正态方程给出的结果与
lstsq
不同:

In [194]: betan = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(Y)

In [195]: betal, res, rnk, s = np.linalg.lstsq(X, Y)

In [196]: np.allclose(betan, betal)
Out[196]: False

我怀疑您数据的矩阵
X'X
具有较高的精度。试图计算这样一个矩阵的数值逆会导致很大的误差。显式计算逆矩阵通常是个坏主意(例如,请参见或)

您可以使用检查条件编号

这里有一个例子。首先创建
X
Y

In [186]: X = np.random.randn(500, 30)

In [187]: Y = np.linspace(0, 1, len(X))
对于此随机
X
,条件编号不大:

In [188]: np.linalg.cond(X.T.dot(X))
Out[188]: 2.4456380658308148
正常方程和
lstsq
给出了相同的结果(根据使用该函数的默认参数):

现在通过使两列几乎相同来调整
X
。这使得
X'X
几乎是单数,并给出了一个很大的条件数:

In [192]: X[:,0] = X[:,1] + 1e-8*np.random.randn(len(X))

In [193]: np.linalg.cond(X.T.dot(X))
Out[193]: 3954529794300611.5
现在,正态方程给出的结果与
lstsq
不同:

In [194]: betan = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(Y)

In [195]: betal, res, rnk, s = np.linalg.lstsq(X, Y)

In [196]: np.allclose(betan, betal)
Out[196]: False

请给出一个可复制的例子。有几个可能的原因,但如果没有你的数据,我们只能猜测你问题的答案(无论如何我会这么做:)。请给出一个可重复的例子。有几个可能的原因,但如果没有您的数据,我们只能猜测您问题的答案(无论如何,我会这么做:)。