【问题标题】:Linear least squares in scipy - accuracy of QR factorization vs other methodsscipy中的线性最小二乘 - QR分解与其他方法的准确性
【发布时间】:2013-04-22 13:05:17
【问题描述】:

我尝试使用以下方法在 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。

【问题讨论】:

    标签: scipy linear-algebra


    【解决方案1】:

    如果您使用这些二进制文件,则 QR 分解由英特尔 MKL 计算,并且可能是正确的。

    对我来说,上面的代码在1e-12 内给出了随机矩阵的正确结果的解决方案。你用什么矩阵来测试它,你如何测量误差?

    在某些情况下,最小二乘问题是病态的。例如, 对于具有较大零空间的矩阵,舍入误差会影响结果。考虑 rank-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
    

    您自制的三角求解比 lstsq 中使用的更仔细编写的 LAPACK 例程更容易出现舍入误差,因此它的准确度会有所降低。

    【讨论】:

    • 我正在使用上面的代码进行最小二乘正弦曲线拟合,所以我的 A 矩阵看起来像 A=numpy.c_[cos(a*t), cos(b*t), cos(c*t), sin(a*t), sin(b*t), sin(c*t)] 其中 t 是一个均匀间隔的 M 长度向量。此外,a、b 和 c 之间的差异也远大于 dt*M。这是否意味着 A 的列几乎是正交的,并且矩阵是满秩的?是否还有其他因素会影响舍入误差?
    • 如果您的矩阵只有 6 列,则只有当向量 t 的长度也是 6 时,它才是满秩的。此外,您没有指定如何测量解决方案中的误差。
    • 你可以在这里发布一个完整的可运行代码,并说出它为你输出的内容。
    • 我只是查看已解决的 b 向量值(如所述的 1e-2 阶)与确切值之间的差异。我没有计算 RMS 误差或任何东西。无论如何,从那以后我一直无法重现该错误 - 这可能是由于数据集不可靠。目前,这看起来是最可能的原因 - 如果我能重现错误,我会在此处发布。
    【解决方案2】:

    您也可以尝试使用截断特征分解。这意味着使用前 k 个特征值。我使用以下代码对最小二乘回归进行正则化,y=kc

    其中u 是特征向量,lambda 是特征值

    线性模型的核矩阵:

    k=np.dot(X,X.T)
    

    然后特征分解:

     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),否则您将拥有负特征值,这会阻止您的内核矩阵不是正定的。

    【讨论】:

    • 截断 SVD 可能是比截断特征分解在数值上更好的选择。
    • 没用过,能告诉我为什么吗?有兴趣了解
    • google.com/search?q=svd+least+squares --- 差不多,但舍入误差更小,可能效率更高,正则化控制更好
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-24
    • 2022-11-15
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    相关资源
    最近更新 更多