C++特征值/向量分解,只需要快速前n个向量

Nam*_*912 17 c++ eigenvector

我有一个~3000x3000协方差相似的矩阵,我在其上计算特征值 - 特征向量分解(它是一个OpenCV矩阵,我用来cv::eigen()完成工作).

但是,我实际上只需要前30个特征值/向量,我不关心其余的.从理论上讲,这应该可以显着加快计算速度,对吧?我的意思是,这意味着它有2970个需要计算的特征向量.

哪个C++库允许我这样做?请注意,OpenCV的eigen()方法确实有参数,但文档说它们被忽略了,我自己测试了,它们确实被忽略了:D

更新: 我设法用ARPACK做到了.我设法为Windows编译它,甚至使用它.结果看起来很有希望,在这个玩具示例中可以看到一个例子:

#include "ardsmat.h"
#include "ardssym.h"
int     n = 3;           // Dimension of the problem.
    double* EigVal = NULL;  // Eigenvalues.
    double* EigVec = NULL; // Eigenvectors stored sequentially.


    int lowerHalfElementCount = (n*n+n) / 2;
    //whole matrix:
    /*
    2  3  8
    3  9  -7
    8  -7 19
    */
    double* lower = new double[lowerHalfElementCount]; //lower half of the matrix
    //to be filled with COLUMN major (i.e. one column after the other, always starting from the diagonal element)
    lower[0] = 2; lower[1] = 3; lower[2] = 8; lower[3] = 9; lower[4] = -7; lower[5] = 19;
    //params: dimensions (i.e. width/height), array with values of the lower or upper half (sequentially, row major), 'L' or 'U' for upper or lower
    ARdsSymMatrix<double> mat(n, lower, 'L');

    // Defining the eigenvalue problem.
    int noOfEigVecValues = 2;
    //int maxIterations = 50000000;
    //ARluSymStdEig<double> dprob(noOfEigVecValues, mat, "LM", 0, 0.5, maxIterations);
    ARluSymStdEig<double> dprob(noOfEigVecValues, mat);

    // Finding eigenvalues and eigenvectors.

    int converged = dprob.EigenValVectors(EigVec, EigVal);
    for (int eigValIdx = 0; eigValIdx < noOfEigVecValues; eigValIdx++) {
        std::cout << "Eigenvalue: " << EigVal[eigValIdx] << "\nEigenvector: ";

        for (int i = 0; i < n; i++) {
            int idx = n*eigValIdx+i;
            std::cout << EigVec[idx] << " ";
        }
        std::cout << std::endl;
    }
Run Code Online (Sandbox Code Playgroud)

结果是:

9.4298, 24.24059
Run Code Online (Sandbox Code Playgroud)

对于特征值,和

-0.523207, -0.83446237, -0.17299346
0.273269, -0.356554, 0.893416
Run Code Online (Sandbox Code Playgroud)

对于2个特征向量分别(每行一个特征向量)代码无法找到3个特征向量(在这种情况下它只能找到1-2,断言()确保这一点,但是,这不是问题).

arr*_*sea 1

本文中,Simon Funk 展示了一种简单有效的方法来估计非常大的矩阵的奇异值分解 (SVD)。在他的例子中,矩阵是稀疏的,尺寸为:17,000 x 500,000。

现在,看这里,描述特征值分解如何与 SVD 密切相关。因此,您可能会受益于考虑 Simon Funk 方法的修改版本,特别是在您的矩阵稀疏的情况下。此外,您的矩阵不仅是方形的,而且是对称的(如果这就是您所说的类似协方差的意思),这可能会导致额外的简化。

...只是一个想法:)