作为我的管道的一部分,我需要按6000x6000的顺序执行大矩阵的特征分解。矩阵是密集的,所以除非我简化问题(如果可能的话确定),不能使用稀疏方法。
目前我玩玩具数据。使用513x513矩阵的特征库我需要~6.5秒,而对于2049x2049矩阵我需要~130秒,这听起来很禁止,因为增加不是线性的。这是通过Eigen::SelfAdjointEigenSolver
实现的,而对于其他方法,例如Eigen::EigenSolver
或Eigen::ComplexEigenSolver
,我没有得到显着改善。当我用arma::eig_sym
尝试犰狳甚至选择“dc”时,也会发生同样的事情,这个选项可以提供更快但近似的结果。犰狳有一些方法只返回加速的第一个X特征值,但这只适用于稀疏方法。目前,我可能会逃脱前10-20个特征值。
有没有办法或图书馆/方法可以给我一个显着的加速?
答案 0 :(得分:4)
Spectra用于检索大矩阵的少量特征值。
计算最大和最小10个特征值的示例代码可能如下所示:
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include <MatOp/DenseGenMatProd.h>
#include <MatOp/DenseSymShiftSolve.h>
#include <SymEigsSolver.h>
#include <iostream>
using namespace Spectra;
int main()
{
srand(0);
// We are going to calculate the eigenvalues of M
Eigen::MatrixXd A = Eigen::MatrixXd::Random(1000, 1000);
Eigen::MatrixXd M = A.transpose() * A;
// Matrix operation objects
DenseGenMatProd<double> op_largest(M);
DenseSymShiftSolve<double> op_smallest(M);
// Construct solver object, requesting the largest 10 eigenvalues
SymEigsSolver< double, LARGEST_MAGN, DenseGenMatProd<double> >
eigs_largest(&op_largest, 10, 30);
// Initialize and compute
eigs_largest.init();
eigs_largest.compute();
std::cout << "Largest 10 Eigenvalues :\n" <<
eigs_largest.eigenvalues() << std::endl;
// Construct solver object, requesting the smallest 10 eigenvalues
SymEigsShiftSolver< double, LARGEST_MAGN, DenseSymShiftSolve<double> >
eigs_smallest(&op_smallest, 10, 30, 0.0);
eigs_smallest.init();
eigs_smallest.compute();
std::cout << "Smallest 10 Eigenvalues :\n" <<
eigs_smallest.eigenvalues() << std::endl;
return 0;
}
答案 1 :(得分:0)
我建议尝试使用Arpack-Eigen。我从Octave / Matlab得知它可以在一秒内计算随机2049x2049的最大特征值,在5-20秒内计算最大的10 [{1}}。
现在,它的文档eigs(rand(2049), 10)
指向ARPACK。 ARPACK - 艾根
https://github.com/yixuan/arpack-eigen允许您从更大的矩阵中请求10个特征值:help eigs
。