2012-06-16 24 views
17

Tengo una matriz de covarianza similar a ~ 3000x3000 en la que calculo la descomposición eigenvalue-eigenvector (es una matriz OpenCV, y uso cv::eigen() para hacer el trabajo).descomposición de vector propio/vector de C++, solo necesito primero n vectores rápido

Sin embargo, en realidad solo necesito, por ejemplo, los primeros 30 valores propios/vectores, no me importa el resto. Teóricamente, esto debería permitir acelerar el cálculo significativamente, ¿verdad? Quiero decir, eso significa que tiene 2970 autovectores menos que necesitan ser calculados.

¿Qué biblioteca C++ me permitirá hacer eso? Tenga en cuenta que el método de OpenCV eigen() tiene los parámetros para eso, sino que la documentación dice que son ignorados, y yo probado yo mismo, son de hecho ignorados: D

ACTUALIZACIÓN: he conseguido hacerlo con ARPACK. Pude compilarlo para Windows e incluso para usarlo. Los resultados parecen prometedores, una ilustración se puede ver en este ejemplo de juguete:

#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; 
    } 

Los resultados son:

9.4298, 24.24059 

para los valores propios, y

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

para los 2 vectores propios, respectivamente (un eigenvector por fila) El código no puede encontrar 3 vectores propios (solo puede encontrar 1-2 en este caso, un assert() se asegura de eso, pero bueno, eso no es un problema).

+2

por los 'primeros 30 valores propios/vectores', ¿quiere decir que los valores propios con los módulos más grandes, más grandes partes real, o algo más? Después de googlear, parece que [SLEPc] (http://www.grycap.upv.es/slepc/) puede tener lo que estás buscando. – James

+0

Estoy buscando los 30 vectores propios que corresponden a los 30 autovalores reales más grandes, resultantes de una autodescomposición de una matriz simétrica real. – NameZero912

+2

Usaría ARPACK para esto. Obtendrá sus 30 autovectores al instante. –

Respuesta

1

En el artículo this, Simon Funk muestra una forma simple y efectiva de estimar una descomposición de valores singulares (SVD) de una matriz muy grande. En su caso, la matriz es escasa, con dimensiones: 17,000 x 500,000.

Ahora, al mirar here, describe cómo la descomposición de los valores propios se relaciona estrechamente con la SVD. Por lo tanto, puede beneficiarse al considerar una versión modificada del enfoque de Simon Funk, especialmente si su matriz es escasa. Además, su matriz no es solo cuadrada sino también simétrica (si eso es lo que quiere decir con una covarianza), lo que probablemente conduzca a una simplificación adicional.

... Es sólo una idea :)

Cuestiones relacionadas