21xrx.com
2024-09-19 10:02:31 Thursday
登录
文章检索 我的文章 写文章
C++最小二乘算法实现
2023-07-05 02:29:26 深夜i     --     --
C++ 最小二乘算法 实现

最小二乘法是一种常见的线性回归方法,可以用于拟合一条直线或多项式曲线,使得拟合曲线与给定数据的误差平方和最小。C++是一种广泛使用的编程语言,它拥有强大的数学计算库和图形界面库,可以很方便地实现最小二乘法。

C++实现最小二乘法的基本思路是,先定义一个目标函数(即误差平方和),然后通过微积分求解该函数的最小值点,即得到拟合曲线的系数。对于一条直线拟合,目标函数的形式通常为:$\displaystyle f(a,b)=\sum_{i=1}^n(y_i-ax_i-b)^2$,其中$a$和$b$分别为直线的斜率和截距,$x_i$和$y_i$为拟合数据点的横纵坐标。对于一条$m$次多项式拟合,目标函数的形式为:$\displaystyle f(a_0,a_1,\cdots,a_m)=\sum_{i=1}^n(y_i-a_0-a_1x_i-\cdots-a_mx_i^m)^2$,其中$a_0,a_1,\cdots,a_m$为多项式的系数。

在C++中,可以使用Eigen、Boost、GSL等数学计算库来实现最小二乘法。以Eigen为例,可以通过定义矩阵和向量来描述拟合数据和拟合曲线的系数。对于一条直线拟合,可以定义如下矩阵和向量:


#include <Eigen/Dense>

using Eigen::MatrixXd;

using Eigen::VectorXd;

int main() {

  // 输入拟合数据

  int n;

  std::cin >> n;

  MatrixXd X(n, 2);

  VectorXd y(n);

  for (int i = 0; i < n; i++) {

    std::cin >> X(i, 0) >> y(i);

    X(i, 1) = 1; // 加上截距项

  }

  // 求解最小二乘问题

  VectorXd theta = (X.transpose() * X).ldlt().solve(X.transpose() * y);

  // 输出拟合结果

  std::cout << "y = " << theta(0) << "x + " << theta(1) << std::endl;

  return 0;

}

对于一条$m$次多项式拟合,需要定义$m+1$维的向量来表示拟合曲线的系数。具体实现见下:


#include <Eigen/Dense>

using Eigen::MatrixXd;

using Eigen::VectorXd;

int main() {

  // 输入拟合数据

  int n, m;

  std::cin >> n >> m;

  MatrixXd X(n, m+1);

  VectorXd y(n);

  for (int i = 0; i < n; i++) {

    std::cin >> X(i, 0);

    y(i) = 0;

    for (int j = 1; j <= m; j++) {

      X(i, j) = X(i, j-1) * X(i, 0); // 计算各次项的值

    }

  }

  X.col(0).setOnes(); // 加上截距项

  // 求解最小二乘问题

  VectorXd theta = (X.transpose() * X).ldlt().solve(X.transpose() * y);

  // 输出拟合结果

  std::cout << "y = " << theta(m) << "x^" << m;

  for (int i = m-1; i >= 0; i--) {

    std::cout << " + " << theta(i) << "x^" << i;

  }

  std::cout << std::endl;

  return 0;

}

以上两个例子中,使用了Eigen库中的矩阵乘法、逆矩阵和分解求解方法来实现最小二乘法的求解过程。可以看到,C++实现最小二乘法的过程并不复杂,只需要掌握数学基础和熟悉所用的数学计算库即可。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复