c++ - 如何用 C++ 拟合二维散点数据

标签 c++ algorithm matlab curve-fitting linear-regression

我以前使用 MATLAB,对于我提出的问题,我可以使用 p = polyfit(x,y,1) 来估计板中散点数据的最佳拟合线。我想知道我可以依靠哪些资源来用 C++ 实现线拟合算法。我知道这个主题有很多算法,对我来说,我希望算法应该很快,同时它可以在 MATLAB 中获得与 polyfit 函数相当的精度。

最佳答案

这个页面描述的算法比维基百科更简单,没有额外的步骤来计算均值等:http://faculty.cs.niu.edu/~hutchins/csci230/best-fit.htm .几乎从那里引用,在 C++ 中是:

#include <vector>
#include <cmath>

struct Point {
  double _x, _y;
};
struct Line {
  double _slope, _yInt;
  double getYforX(double x) {
    return _slope*x + _yInt;
  }
  // Construct line from points
  bool fitPoints(const std::vector<Point> &pts) {
    int nPoints = pts.size();
    if( nPoints < 2 ) {
      // Fail: infinitely many lines passing through this single point
      return false;
    }
    double sumX=0, sumY=0, sumXY=0, sumX2=0;
    for(int i=0; i<nPoints; i++) {
      sumX += pts[i]._x;
      sumY += pts[i]._y;
      sumXY += pts[i]._x * pts[i]._y;
      sumX2 += pts[i]._x * pts[i]._x;
    }
    double xMean = sumX / nPoints;
    double yMean = sumY / nPoints;
    double denominator = sumX2 - sumX * xMean;
    // You can tune the eps (1e-7) below for your specific task
    if( std::fabs(denominator) < 1e-7 ) {
      // Fail: it seems a vertical line
      return false;
    }
    _slope = (sumXY - sumX * yMean) / denominator;
    _yInt = yMean - _slope * xMean;
    return true;
  }
};

请注意,如果对点的“最佳”描述是垂直线,则此算法和维基百科 (http://en.wikipedia.org/wiki/Simple_linear_regression#Fitting_the_regression_line) 中的算法都会失败。他们失败是因为他们使用了

y = k*x + b 

本质上不能描述垂直线的线方程。如果你还想涵盖数据点被垂直线“最佳”描述的情况,你需要一个使用的线拟合算法

A*x + B*y + C = 0

线方程。您仍然可以修改当前算法以生成该等式:

y = k*x + b <=>
y - k*x - b = 0 <=>
B=1, A=-k, C=-b

就上面的代码而言:

B=1, A=-_slope, C=-_yInt

然后在 if 的“then” block 中检查分母是否等于 0,而不是 //Fail: it seems a vertical line,生成以下直线方程:

x = xMean <=>
x - xMean = 0 <=>
A=1, B=0, C=-xMean

我刚刚注意到我所指的原始文章已被删除。这个网页提出了一些不同的线拟合公式:http://hotmath.com/hotmath_help/topics/line-of-best-fit.html

double denominator = sumX2 - 2 * sumX * xMean + nPoints * xMean * xMean;
...
_slope = (sumXY - sumY*xMean - sumX * yMean + nPoints * xMean * yMean) / denominator;

公式是相同的,因为 nPoints*xMean == sumXnPoints*xMean*yMean == sumX * yMean == sumY * xMean

关于c++ - 如何用 C++ 拟合二维散点数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11449617/

相关文章:

c++ - opencv中拜耳模式代码的含义是什么

c++ - 如何在 matlab 中使用 kd-tree 文件交换和 mex?

c++ - 错误 LNK2019 : unresolved external symbol _CreateFastString referenced in function _wmain

c++ - 在 C++ 中检查数组的顺序

java - 如何将字节数组转换为其数值(Java)?

algorithm - GBrank : what is the final model?

c# - 从较长的字符串创建人类可读的短字符串

matlab - 非模态 questdlg.m 提示

matlab - 通过将子矩阵分布到三维来 reshape 矩阵

c++ - 从函数内部推断函数返回类型