最小二乘法解的矩阵形式推导

首先,什么是最小二乘? 
维基百科给出了一个定义,戳这里

在我看来,最小二乘法是一种数据拟合方法。

我们从矩阵的角度来理解: 
首先我们给出一个矩阵中的定义: 

R(A)={Ax|xRn},ARn×n

有了上面的定义之后,我们就可以写出最小二乘问题的矩阵形式: 
bR(A),bRn,minxRnAxb2

用bi格高一点的说法来说,就是求在欧几里得空间中以2-范数作为距离,使得向量Ax与b之间距离最小的x。  
我们的目标是求: 
minxRnAxb2

当然我们知道,使得距离最小的向量x与使得距离平方最小的向量x是相同的,于是我们可以将所求的目标改写为: 
minxRnAxb22

结合一些矩阵、行列式的知识,我们知道: 
Axb22=(Axb)T(Axb)

根据我们大一学过的高数知识,我们知道,求最极值问题直接对应的就是导数为零,因此我们试图将所给出的原式的矩阵形式求导:

不过首先我们需要补充矩阵微积分(matrix calculus)的一些知识 
(PS:是矩阵微积分吧…我没有翻译错吧….) 

xTax=aTxx=a

xTAxx=Ax+ATx

如果矩阵A是对称的(symmetric matrix): 
Ax+ATx=2Ax

接下来,我们对原式化简并求其对x的导数: 

Axb22=xTATAxbTAxxTATb+bTb

求导得到: 
Axb22x=2ATAx2ATb=0

于是我们就得到了,最小二乘法解的矩阵形式: 
x=(ATA)1ATb

当然了,这里是最简答的线性最小二乘法,还有更为复杂的非线性以及矩阵A不满秩的情况(hdq说他老师能默写出这个过程…),等以后有时间了,我会再补充上去的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
最小二乘法拟合圆是一种常用的曲线拟合方法,可以用于将一组点拟合成一个圆。其原理是将点到圆心的距离的平方作为误差,通过最小化误差来求圆心坐标和半径。 以下是最小二乘法拟合圆的公式推导及其在C语言中的实现: 1. 公式推导 设圆的方程为:(x-a)^2 + (y-b)^2 = r^2 将每个点代入圆的方程中,得到如下方程组: (x1-a)^2 + (y1-b)^2 = r^2 (x2-a)^2 + (y2-b)^2 = r^2 ... (xn-a)^2 + (yn-b)^2 = r^2 将圆心坐标和半径表示为未知数,即: A = [a,b,r] 则上述方程组可以表示为: f(A) = [ (x1-a)^2 + (y1-b)^2 - r^2, (x2-a)^2 + (y2-b)^2 - r^2, ... (xn-a)^2 + (yn-b)^2 - r^2 ] 误差函数为: E(A) = f(A)^T * f(A) 对误差函数求导,得到: dE/dA = -2 * J^T * f(A) 其中,J为雅可比矩阵,表示误差函数对未知数的偏导数,即: J = [ -2*(x1-a), -2*(y1-b), -2*r; -2*(x2-a), -2*(y2-b), -2*r; ... -2*(xn-a), -2*(yn-b), -2*r ] 将雅可比矩阵和方程组代入上式,得到: dE/dA = -2 * ( J^T * J * A + J^T * f(A) ) 令dE/dA = 0,得: A = ( J^T * J )^-1 * J^T * f(A) 即可求出圆心坐标和半径。 2. C语言实现 在C语言中,可以使用矩阵运算库(如Eigen)来实现矩阵的乘法、转置和求逆等操作。以下是一个简单的C语言实现: ```c #include <Eigen/Dense> #include <vector> using namespace Eigen; using namespace std; // 最小二乘法拟合圆 // 输入:points-点集,格式为vector<Vector2d> // 输出:圆心坐标和半径,格式为Vector3d Vector3d fitCircle(const vector<Vector2d>& points) { int n = points.size(); // 构建J和f(A)矩阵 MatrixXd J(n, 3); VectorXd f(n); for (int i = 0; i < n; i++) { double x = points[i](0); double y = points[i](1); J(i, 0) = -2 * x; J(i, 1) = -2 * y; J(i, 2) = -2; f(i) = -(x * x + y * y); } // 求圆心坐标和半径 Vector3d A = (J.transpose() * J).inverse() * J.transpose() * f; A(0) = -A(0) / 2; A(1) = -A(1) / 2; A(2) = sqrt(A(0) * A(0) + A(1) * A(1) - A(2)); return A; } ``` 使用示例: ```c vector<Vector2d> points; points.push_back(Vector2d(0, 1)); points.push_back(Vector2d(1, 0)); points.push_back(Vector2d(0, -1)); points.push_back(Vector2d(-1, 0)); Vector3d A = fitCircle(points); cout << "圆心坐标:" << A.head<2>().transpose() << endl; cout << "半径:" << A(2) << endl; ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值