求解超定的稀疏线性系统会产生高误差解

时间:2017-12-28 15:53:25

标签: python sparse-matrix linear-algebra eigen

我的代码

所以我写了一个迭代求解稀疏超定线性系统的算法。这意味着我的代码如下所示:

   construct_A_matrix();
   construct_B_matrix();
   while(someCondition){
    x=solveSystem(A,B) //solve Ax=B. This system is overdetermined 
                       //since A has more rows than cols.
    update_A_matrix(x) //update A based on x
    update_B_matrix(x) //update B based on x
    iterationsCounter++
    }
    useX();

在solveSystem中,我使用了eigen的SimplicialLDLTConjugate Gradient解算器(我将它们用于调试目的,如果代码工作,我将只使用其中一个)。我用来解决系统的代码是:

for Conjugate Gradient

     using SpMatrix = Eigen::SparseMatrix<double>;
     Eigen::ConjugateGradient<SpMatrix, Eigen::Lower | Eigen::Upper>
     solver;
     SpMatrix At = A.transpose();
     SpMatrix AtA = At * A;
     solver.compute(AtA);
     EigenMatrix newVertexPositions = solver.solve(At * B);
     std::cout << "estimated error: " << solver.error() << std::endl;
     double residual=(A.transpose() * (A * x) - A.transpose() * B).norm()/(A.transpose() * B).norm();

和SimplicialLDLT

    using SpMatrix = Eigen::SparseMatrix<double>;
    Eigen::SimplicialLDLT<SpMatrix> solver;
    SpMatrix At = A.transpose();
    SpMatrix AtA = At * A;
    solver.compute(AtA);
    if (solver.info() != Eigen::Success)
            std::cout << "Decomposition failed!" << std::endl;
    EigenMatrix AtB = At * B;
    EigenMatrix x = solver.solve(AtB);
    if (solver.info() != Eigen::Success)
            std::cout << "Solving failed!" << std::endl;
    //simplicialLDLT has no error() function
    double residual=(A.transpose() * (A * x) - A.transpose() * B).norm() /(A.transpose() * B).norm();

问题

经过上述循环的一些迭代后,求解器的残差/误差上升,我得到的解是错误的。

SimplicialLDLT产生的结果比Conjugate Gradient更好,但一段时间后仍然是错误的。这可以在下面以图形方式看到。正如您所看到的,SimplicialLDLT的残差增长晚于共轭梯度

enter image description here enter image description here

所以这是我的问题,我想弄清楚为什么会发生这种情况。我注意到,当A和B的值上升时,残差会增加.update_A_matrix和update_B_matrix逐渐增加矩阵的值A和迭代计数器一起增加。

亲自尝试

Here你可以为每个求解器找到一个文件夹,在这个文件夹中你会找到市场格式的矩阵A,B和x,用于上述while块的最后一次迭代。还有一个信息文件,您可以在其中找到上述循环的每次迭代,A和B的最大值和最小值以及残差值。您可以使用以下代码加载A,B和X:

#include <Eigen/Sparse> //system solving and Eigen::SparseMatrix
#include <ctime> //measure time to execute
#include <unsupported/Eigen/SparseExtra> //loadMarket

using SpMatrix = Eigen::SparseMatrix<double>;
using Matrix = Eigen::MatrixXd;
int main() {
  SpMatrix A, B;
  Matrix X;
  Eigen::loadMarket(A, "/AMatrixDirectory/A.mtx");
  Eigen::loadMarket(B, "/BMatrixDirectory/B.mtx");
  Eigen::loadMarket(B, "/BMatrixDirectory/X.mtx");
}

或在python中:

import scipy.io as sio
A=sio.mmread('/AMatrixDirectory/A.mtx')
B=sio.mmread('/AMatrixDirectory/B.mtx')
X=sio.mmread('/AMatrixDirectory/B.mtx')

我很想知道

  1. 为什么残余物首先上升。
  2. 如何防止它上升。

1 个答案:

答案 0 :(得分:0)

你说你有一个稀疏的超定系统但是使用的方法甚至不适合它。当稀疏时,通常使用套索方法,即L1正则化。该地区已经做了大量的工作。当您采用正规方程时,您可以设置条件数。这是两种类型regularization.的教程。还有一种称为压缩感知的东西。