我是靠谱客的博主 背后胡萝卜,最近开发中收集的这篇文章主要介绍Eigen求最小二乘解,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一个超定方程组,例如 A x = b Ax = b Ax=b,没有解。在这种情况下,在 A x − b Ax-b Axb尽可能小的意义上,搜索最接近解的向量 x x x是有意义的。该 x x x称为最小二乘解(如果使用欧几里得范数)。

此处使用的三种求解方法为:SVD分解,QR分解,正规矩阵(normal equation)。在这三种方程中,SVD分解通常准确率最高,但是速度最慢;正规矩阵速度最快,但是准确率最低;QR分解位于两者之间。

求解问题

  Eigen::MatrixXd A = Eigen::MatrixXd::Random(3, 2);
  std::cout << "Here is the matrix A:n" << A << std::endl;
  Eigen::VectorXd b = Eigen::VectorXd::Random(3);
  std::cout << "Here is the right hand side b:n" << b.transpose() << std::endl;
Here is the matrix A:
 0.680375   0.59688
-0.211234  0.823295
 0.566198 -0.604897
Here is the right hand side b:
-0.329554  0.536459 -0.444451

SVD分解

可以直接使用BDCSVD类中的solve()方法求解线性方程。单纯计算奇异值是不足够的,还需要计算奇异向量,但是稀疏SVD分解足够计算最小二乘解。

  // using the SVD decomposition
  std::cout << "The solution using the SVD decomposition is:n"
            << A.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV)
                   .solve(b)
                   .transpose()
            << std::endl;
The solution using the SVD decomposition is:
-0.669626  0.314253

QR分解

Eigen中QR分解类有三个:HouseholderQR(没有枢转,快速但不稳定),ColPivHouseholderQR(列枢转,因此有一些慢但是更准确),FullPivHouseholderQR(完全旋转,最慢,但是最稳定)。

  // using the QR decomposition
  std::cout << "The solution using the QR decomposition is:n"
            << A.colPivHouseholderQr().solve(b).transpose() << std::endl;
The solution using the QR decomposition is:
-0.669626  0.314253

正规矩阵

求解 A x = b Ax = b Ax=b的最小二乘解等于求解正规矩阵 A T A x = A T b A^TAx = A^Tb ATAx=ATb

  // using normal equations
  std::cout << "The solution using normal equations is:n"
            << (A.transpose() * A).ldlt().solve(A.transpose() * b).transpose()
            << std::endl;
The solution using normal equations is:
-0.669626  0.314253

如果矩阵 A A A是病态的,那么这不是一个好方法,因为 A T A A^TA ATA A A A的平方。这意为着使用正规方程所造成的损失是使用其他方法所造成损失的两倍。

代码

#include <Eigen/Dense>
#include <iostream>

int main(int argc, char **argv) {
  Eigen::MatrixXd A = Eigen::MatrixXd::Random(3, 2);
  std::cout << "Here is the matrix A:n" << A << std::endl;
  Eigen::VectorXd b = Eigen::VectorXd::Random(3);
  std::cout << "Here is the right hand side b:n" << b.transpose() << std::endl;

  // using the SVD decomposition
  std::cout << "The solution using the SVD decomposition is:n"
            << A.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV)
                   .solve(b)
                   .transpose()
            << std::endl;

  // using the QR decomposition
  std::cout << "The solution using the QR decomposition is:n"
            << A.colPivHouseholderQr().solve(b).transpose() << std::endl;

  // using normal equations
  std::cout << "The solution using normal equations is:n"
            << (A.transpose() * A).ldlt().solve(A.transpose() * b).transpose()
            << std::endl;

  return 0;
}

最后

以上就是背后胡萝卜为你收集整理的Eigen求最小二乘解的全部内容,希望文章能够帮你解决Eigen求最小二乘解所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部