最小二乘法:正规方程vs svd

时间:2016-04-01 22:43:12

标签: numpy linear-regression least-squares svd

我尝试按照beta = inv(X'X)X'Y的正规方程编写自己的线性回归代码。但是,平方误差远大于lstsq中的numpy.linalg函数。有人可以向我解释为什么SVD方法(lstsq使用)比正常方程更准确吗?谢谢

1 个答案:

答案 0 :(得分:3)

我怀疑您的数据的矩阵X'X有一个高condition number。试图计算这种矩阵的数值逆可能导致大的误差。显式计算逆矩阵通常是个坏主意(例如,参见http://www.johndcook.com/blog/2010/01/19/dont-invert-that-matrix/http://epubs.siam.org/doi/abs/10.1137/1.9780898718027.ch14)。

您可以使用numpy.linalg.cond检查条件编号。

这是一个例子。首先创建XY

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给出相同的结果(根据numpy.allclose使用该函数的默认参数时):

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

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

In [191]: np.allclose(betan, betal)
Out[191]: True

现在通过使两列几乎相同来调整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