20

固有値-固有ベクトル分解を計算する〜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;
    }

結果は次のとおりです。

9.4298, 24.24059

固有値の場合、および

-0.523207, -0.83446237, -0.17299346
0.273269, -0.356554, 0.893416

それぞれ 2 つの固有ベクトルに対して (行ごとに 1 つの固有ベクトル) コードは 3 つの固有ベクトルを見つけることができません (この場合、1-2 しか見つけることができません。assert() はそれを確認しますが、それは問題ではありません)。

4

2 に答える 2

1

この記事では、Simon Funk が、非常に大きな行列の特異値分解 (SVD) を推定する簡単で効果的な方法を示しています彼の場合、行列は疎で、次元は 17,000 x 500,000 です。

さて、ここを見て、固有値分解がどのようにSVDと密接に関係しているかを説明します。したがって、特にマトリックスがスパースである場合は、Simon Funk のアプローチの修正版を検討することでメリットが得られる可能性があります。さらに、行列は正方であるだけでなく対称でもあり (共分散のような意味である場合)、さらに単純化される可能性があります。

...ただのアイデア:)

于 2013-01-23T20:05:18.060 に答える