证明AX=0的最小二乘解是ATA最小特征值对应的特征向量

坑爹的,csdn没法编辑公式,我只能在word上写好截图了。




因此,如果能构造AX=0,则最小二乘解就直接求ATA的最小特征解就可以了,这里举一个平面拟合的例子:

假如有一束点云,如何从点云里把平面求出来。啥也不说了,上代码吧:

Bool ComplanationFit(Geometries::Coordinate *pPoints, Int32 nPointcount, Double tolerance)
{
if ((pPoints == NULL) || (nPointcount < 4) || (tolerance < 0.0))
{
return false;
}
/*
* 解XTX的特征值
*/
Eigen::MatrixXd X = Eigen::MatrixXd::Zero(nPointcount, 4);
for (Int32 i = 0; i < nPointcount; i++)
{
Coordinate c = pPoints[i];
X(i, 0) = c.x;
X(i, 1) = c.y;
X(i, 2) = c.z;
X(i, 3) = 1.0;
}
Eigen::MatrixXd XTX = X.transpose() * X;


Eigen::EigenSolver<Eigen::MatrixXd> es(XTX);


std::complex<Double> d[4];
  d[0] = es.eigenvalues()[0];
d[1] = es.eigenvalues()[1];
d[2] = es.eigenvalues()[2];
d[3] = es.eigenvalues()[3];


int iMin = 0; double dMax = DBL_MAX;
for (int i = 0; i < 4; i++)
{
if (d[i].real() < dMax)
{
iMin = i;
dMax = d[i].real();
}
}
Eigen::VectorXcd V = es.eigenvectors().col(iMin);
//平面方程
double dA = V(0).real();
double dB = V(1).real();
double dC = V(2).real();
double dD = V(3).real();


//投射到该平面
for (int i = 0; i < nPointcount; i++)
{
double x = pPoints[i].x;
double y = pPoints[i].y;
double z = pPoints[i].z;
double t = (dA * x + dB * y + dC * z + dD) / (dA * dA + dB * dB + dC * dC);


pPoints[i].x = x - dA * t;
pPoints[i].y = y - dB * t;
pPoints[i].z = z - dC * t;
}
return true;
}




### 点云数据最小二乘曲线拟合方法 对于点云数据的最小二乘曲线拟合,通常涉及几个核心步骤。首先,定义目标函数来描述期望的曲线模型;其次,利用给定的数据集计算参数的最佳估计值,使得残差平方和达到最小化。 #### 定义目标函数 假设要拟合一条多项式曲线 \( y = a_0 + a_1x + a_2x^2 + ... + a_nx^n \),其中\(a_i\)表示待求系数。为了找到最优的系数向量\(\mathbf{A}=[a_0,a_1,...,a_n]^T\),可以构建如下形式的目标函数: \[ J(\mathbf{A})=\sum_{i=1}^{m}(y_i-(a_0+a_1x_i+...+a_nx_i^n))^2 \] 该表达式代表所有测量点到预测曲线上对应位置的距离之平方总和[^1]。 #### 构建设计矩阵 接下来建立一个设计矩阵X用于存储输入变量的信息。每一列对应于不同幂次项下的自变量取值组合而成的新特征向量。例如,在二次回归情况下: | X | Y | |---|---| |x₁²,x₂²,…,xn²|x₁,y₁…yn| 这样就可以把原始问题转化为线性代数中的标准方程组AX=B的形式来进行求了[^2]。 #### 参数优化过程 采用正规方程法或者其他数值迭代算法(比如梯度下降)去寻找能够使J(A)取得极小值的一组最佳权重w*。具体来说就是决下面这个正则化的最小化问题: \[ w^*=(X^TX)^{-1}X^TY \] 这一步骤可以通过调用MATLAB内置命令`polyfit()`轻松完成,它会自动返回所选次数下最合适的多项式系数数组[^3]。 #### 实现案例展示 以下是基于Python环境下使用numpy库的一个简单例子,展示了如何对一组离散坐标点执行最小二乘直线拟合并绘制图形的结果。 ```python import numpy as np from matplotlib import pyplot as plt def fit_curve(x_data, y_data, degree): A = [] for i in range(len(x_data)): row = [pow(x_data[i], j) for j in range(degree + 1)] A.append(row) ATA_inv = np.linalg.inv(np.dot(np.transpose(A), A)) ATY = np.dot(np.transpose(A), y_data) coefficients = np.dot(ATA_inv, ATY).tolist() return list(reversed(coefficients)) if __name__ == "__main__": x_points = [-5,-4,-3,-2,-1,0,1,2,3,4,5] y_points = [8.9,6.7,4.5,2.3,0.1,-2.1,-4.3,-6.5,-8.7,-10.9,-13.1] fitted_coefficients = fit_curve(x_points, y_points, 1) print(f"Fitted Coefficients: {fitted_coefficients}") # Plotting the original points and fitted line. fig, ax = plt.subplots(figsize=(8, 6)) ax.scatter(x_points, y_points, color='blue', label="Original Data Points") x_line = np.linspace(min(x_points)-1,max(x_points)+1,num=100) y_line = sum([c * pow(x_line,i) for i,c in enumerate(reversed(fitted_coefficients))]) ax.plot(x_line, y_line,color='red',label=f'Fitted Line (Degree={len(fitted_coefficients)-1})') ax.legend(loc="best") plt.show() ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神气爱哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值