C++ 中的最大特征值(和相应的特征向量)
Posted
技术标签:
【中文标题】C++ 中的最大特征值(和相应的特征向量)【英文标题】:Largest eigenvalues (and corresponding eigenvectors) in C++ 【发布时间】:2014-06-28 15:57:14 【问题描述】:在 C++ 中为大型密集矩阵计算 k 个最大特征值和特征向量的最简单和最快的方法是什么(当然是使用一些库)?我正在寻找相当于 MATLAB 的 eigs
函数;我已经查看了 Armadillo 和 Eigen,但找不到一个,并且在我的情况下计算所有特征值需要很长时间(对于大约 30000x30000 密集的非对称实矩阵,我需要前 10 个特征向量)。
绝望,我什至尝试用犰狳的 QR 分解自己实现幂迭代,但遇到了复杂的特征值对并放弃了。 :)
【问题讨论】:
【参考方案1】:你试过https://github.com/yixuan/spectra 吗? 它类似于 ARPACK,但具有很好的类似 Eigen 的界面(它与 Eigen 兼容!)
我将它用于 30kx30k 矩阵 (PCA),效果还不错
【讨论】:
我自己在我的应用程序中尝试过这个,它使用 Eigen 处理所有与线性代数相关的事情,这非常方便:只有标题(如 Eigen)所以没有构建问题,只需 #include + 4 行代码和我有我的特征值、特征值格式的输入和输出,并且比我自己实现的 Lanczos 迭代快得多,在几秒钟内在 80k x 80k 稀疏矩阵中获得 100 个特征值(最高或最小)。【参考方案2】:AFAIK 找到 generic 矩阵的第一个 k
特征值的问题没有简单的解决方案。您提到的 Matlab 函数 eigs
应该适用于稀疏矩阵。
Matlab 可能使用 Arnoldi/Lanczos,即使您的矩阵不是稀疏的,您也可以尝试它是否适合您的情况。 Arnlodi 的参考包是ARPACK,它有一个 C++ 接口。
【讨论】:
我不确定它使用哪种算法,但 Matlab 的eigs
确实比查找大型密集矩阵的所有特征值快得多。
eigs
使用 Arnoldi,旨在输出第一个较大的 k
特征值。比查找所有特征值快还是慢取决于您的k
有多大。
谢谢! Arpack 没有世界上最友好的界面,但它确实有效。 4 分 20 秒解决我的问题(大小为 30K x 30K 的矩阵的 10 个特征向量)非常好。【参考方案3】:
Eigen 有一个运行良好的 EigenValues 模块。但是,我从来没有在这么大的东西上使用过它。
【讨论】:
是的,但我在那里找不到任何计算最高k
特征值的东西。查找所有特征值会很慢。
我看到了一些示例函数here 计算主要特征值/向量。【参考方案4】:
这是我如何在C++ Eigen 中获得 NxN 实值(浮点)、密集、对称矩阵 A 的 k 个最大特征向量:
#include <Eigen/Dense>
...
Eigen::MatrixXf A(N,N);
...
Eigen::SelfAdjointEigenSolver<Eigen::MatrixXf> solver(N);
solver.compute(A);
Eigen::VectorXf lambda = solver.eigenvalues().reverse();
Eigen::MatrixXf X = solver.eigenvectors().block(0,N-k,N,k).rowwise().reverse();
请注意,特征值和相关的特征向量按升序返回,因此我将它们反转以首先获得最大值。
如果您想要其他(非对称)矩阵的特征值和特征向量,它们通常会很复杂,您需要改用 Eigen::EigenSolver
类。
【讨论】:
以上是关于C++ 中的最大特征值(和相应的特征向量)的主要内容,如果未能解决你的问题,请参考以下文章