我尝试使用以下方法解决scipy中的线性最小二乘问题Ax = b:
x = numpy.linalg.inv(A.T.dot(A)).dot(A.T).dot(b) #Usually not recommended
和
x = numpy.linalg.lstsq(A, b)
两者都给出了几乎相同的结果。我也尝试手动使用QR算法,即:
Qmat, Rmat = la.qr(A)
bpr = dot(Qmat.T,b)
n=len(bpr)
x = np.zeros(n)
for i in xrange(n-1, -1,-1):
x[i] = bpr[i]
for j in xrange(i+1, n):
x[i] -= Rmat[i, j]*x[j]
x[i] /= Rmat[i,i]
然而,这种方法给出了非常不准确的结果(错误大约为1e-2)。我在代码或数学上犯了n00b错误吗?或者,这个方法是一个问题,还是scipy本身?
我的numpy版本是1.6.1(来自http://www.lfd.uci.edu/~gohlke/pythonlibs/的mkl编译版本),x86_64上的Python 2.7.3。
答案 0 :(得分:2)
如果您使用这些二进制文件,则QR因子分解由英特尔MKL计算,可能是正确的。
对我来说,上面的代码为随机矩阵提供了正确结果的1e-12
范围内的解决方案。您使用哪些矩阵进行测试,以及如何衡量错误?
有些情况下,最小二乘问题是病态的。例如, 对于具有大空值空间的矩阵,舍入误差会影响结果。考虑秩-1矩阵:
np.random.seed(1234)
v = np.random.rand(100)
A = v[:,None] * v[None,:]
b = np.random.randn(100)
x = scipy.linalg.lstsq(A, b)[0]
print(np.linalg.norm(A.dot(x) - b))
# -> 9.63612833771
# xp obtained using your above code
print(np.linalg.norm(A.dot(xp) - b))
# -> 3262.61161684
你的home-brewn三角形求解比lstsq中使用的更精心编写的LAPACK例程更容易出现舍入误差,因此它的准确性会稍差。
答案 1 :(得分:0)
您也可以尝试使用截断的特征分解。这意味着使用top k eigen value。我使用以下代码来规范最小二乘回归,y = kc
其中u
是特征向量,lambda
是特征值
线性模型的核矩阵:
k=np.dot(X,X.T)
然后是eigendecompostion:
w, v = scipy.linalg.eigh(k, eigvals=(lo, hi))
然后
temp= np.dot(np.dot(v,np.diag(1.0/w)),v.T)
c=np.dot(temp,y)
对于正则化,你应该在核矩阵的对角线上添加一个小值(如0.001
),否则你会有负特征值,这会阻止你的核矩阵不是正定的。