当前位置:   article > 正文

SVD 最小二乘法解 亲测ok!_svd.matrixu()

svd.matrixu()

线性最小二乘问题

m个方程求解n个未知数,有三种情况:

  1. m=n且A为非奇异,则有唯一解,x=A.inverse()*b
  2. m>n,约束的个数大于未知数的个数,称为超定问题(overdetermined)
  3. m<n,负定/欠定问题(underdetermined)

通常我们遇到的都是超定问题,此时Ax=b的解是不存在的,从而转向解最小二乘问题:

J(x)为凸函数,一阶导数为0,得到:

,称之为正规方程

一般解:

奇异值分解与线性最小二乘问题

列满秩,A的奇异值分解:(公式1)

其中U和V为半酉阵,分别满足

其中,这里的几个符号的大小:U:m\timesm   :n\timesn   V:n\timesn

注意:为什么这里是n\timesn,是因为我上面写的公式1中UGV,G=,G的尺寸是m\times

为 U 的 前 n 列矩阵,即

则:

等号当且仅

时成立,所以:

这就是我们千辛万苦要求的线性最小二乘问题的解!!!

用eigen库计算的例子:

  1. //Ax=b
  2. MatrixXd A= MatrixXd::Zero(15,8);
  3. Eigen::JacobiSVD<MatrixXd> svd(A, Eigen::ComputeFullU | Eigen::ComputeFullV);
  4. Eigen::Matrix<double, 15, 15> U = svd.matrixU();
  5. Eigen::Matrix<double, 8, 8> V = svd.matrixV();
  6. Eigen::Matrix<double, 8, 8> Gama = svd.singularValues().asDiagonal();
  7. Eigen::Matrix<double, 15, 1> b;
  8. Eigen::Matrix<double, 8, 1> x = V * Gama.inverse()*(U.block<15,8>(0,0).transpose())*b;

 svd解法:修改 A 和 data(代表XYZ)

         修改未知量的个数;

  1. //解决问题: Ax=XYZ
  2. {
  3. int numberOfpara = 3;
  4. std::vector<double> data = { 1.7,1.6,1.6,1.5,1.2,1.3,2.3,2,1.7,1.2};
  5. typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> MatrixXd;
  6. MatrixXd A;
  7. A.resize(data.size(), numberOfpara);
  8. A.fill(0);
  9. /*A << 1.2, 0.1, 1.2, 2.3, 1.4,
  10. 1.12, 1.03, 2, 2.06, 1.4,
  11. 1.32, 1.24, 2.1, 2.05, 1.3,
  12. 1.4, 0.77, 1.5, 2.02, 1.3,
  13. 1.3, 1.37, 2, 2, 1.2,
  14. 1.16, 0.8, 1.7, 2, 1.3,
  15. 1.9, 1.23, 1.8, 1.99, 1.5,
  16. 1.65, 1.27, 1.9, 1.99, 1.4,
  17. 1.09, 0.89, 2, 1.99, 1.3,
  18. 1.5, 0.75, 1.1, 1.99, 1.2;*/
  19. cout << "Here is the matrix m:" << endl << A << endl;
  20. int row=A.rows();
  21. int col = A.cols();
  22. typedef Eigen::Matrix<double, Eigen::Dynamic, 1> VectorXd;
  23. Eigen::Map<VectorXd> XYZ(data.data(), row, 1);
  24. cout << "Here is the matrix XYZ:" << endl << XYZ << endl;
  25. // svd解法
  26. Eigen::JacobiSVD<MatrixXd> svd(A, Eigen::ComputeFullU | Eigen::ComputeFullV);
  27. MatrixXd U, V, Gama, x;
  28. U.resize(row, row);
  29. V.resize(col, col);
  30. Gama.resize(col, col);
  31. x.resize(col, 1);
  32. U = svd.matrixU();
  33. V = svd.matrixV();
  34. Gama = svd.singularValues().asDiagonal();
  35. x = V * Gama.inverse()*(U.block(0, 0, row, col).transpose())*XYZ;
  36. cout << "Here is the x:" << endl << x << endl;
  37. //验证结果
  38. cout << "Here is the eps:" << endl << A * x - XYZ;
  39. //x转化为vector
  40. std::vector<double> out(&x(0, 0), x.data() + x.cols()*x.rows());

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/78175
推荐阅读
相关标签
  

闽ICP备14008679号