Я пытаюсь решить классическую проблему наименьших квадратов argmin (Ax - b)^2
, используя Eigen. Я знаю, что система переопределена (то есть m >= n
, где A равно m x n
), и что A имеет полный ранг (n
). Я решил использовать разреженную QR-часть Eigen, поскольку A сам по себе является разреженным. Я дошел до этого:
#include <Eigen/Sparse>
#include <Eigen/SparseQR>
void solve_least_squares(const Eigen::SparseMatrix<double>& matrix,
const Eigen::VectorXd& rhs)
{
int m = matrix.rows();
int n = matrix.cols();
assert(m >= n);
assert(matrix.isCompressed());
Eigen::SparseQR<Eigen::SparseMatrix<double>, Eigen::COLAMDOrdering<int>> decomposition(matrix);
Eigen::VectorXd t = (decomposition.matrixQ().transpose() * rhs).topRows(n);
std::cout << t << std::endl;
Eigen::VectorXd s = decomposition.matrixR().topRows(n).triangularView<Eigen::Upper>().solve(t);
return decomposition.colsPermutation().inverse()*s;
}
Но мне интересно, является ли это наиболее эффективной реализацией: во-первых, Эйген, похоже, определяет полное QR-разложение, а не сокращенное ( Q
это m x m
, а не m x n
). Это кажется расточительным, поскольку мне нужны только верхние n
строки.
В плотном случае есть любой пример в классе HouseholderQR :
MatrixXf A(MatrixXf::Random(5,3)), thinQ(MatrixXf::Identity(5,3)), Q;
A.setRandom();
HouseholderQR<MatrixXf> qr(A);
Q = qr.householderQ();
thinQ = qr.householderQ() * thinQ; // <- here
std::cout << "The complete unitary matrix Q is:\n" << Q << "\n\n";
std::cout << "The thin matrix Q is:\n" << thinQ << "\n\n";
Здесь умножение матриц используется для получения уменьшенного Q
, что кажется даже более неэффективным, чем нарезка полной матрицы.
Поскольку разложение (собственного) SVD (плотного) SVD дает возможность вычислять тонкий SVD, есть ли подобная опция для разложения QR?