Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何用C++;_C++_Algorithm_Matlab_Curve Fitting_Linear Regression - Fatal编程技术网

C++ 如何用C++;

C++ 如何用C++;,c++,algorithm,matlab,curve-fitting,linear-regression,C++,Algorithm,Matlab,Curve Fitting,Linear Regression,我曾经使用MATLAB,对于我提出的问题,我可以使用p=polyfit(x,y,1)来估计板中散射数据的最佳拟合线。我想知道哪些资源我可以依靠实现直线拟合算法与C++。我知道有很多关于这个主题的算法,对我来说,我希望算法应该是快速的,同时它可以在MATLAB中获得与polyfit函数相当的精度 我建议从头开始编写。这是一个非常简单的C++实现。您可以直接从这里的公式从数据中为最小二乘拟合(与polyfit的方法相同)编码截距和梯度 这些是封闭式公式,您可以使用循环轻松地对自己进行评估。如果您使

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

我建议从头开始编写。这是一个非常简单的C++实现。您可以直接从这里的公式从数据中为最小二乘拟合(与
polyfit
的方法相同)编码截距和梯度


这些是封闭式公式,您可以使用循环轻松地对自己进行评估。如果您使用的是更高阶拟合,那么我建议使用矩阵库或更复杂的算法,但对于上面描述的简单线性回归,这就是您所需要的。在我看来,矩阵和线性代数例程对于这样一个问题来说是多余的。

你也可以使用它,或者也可以去那里。

要适合一行
y=param[0]x+param[1]
只需这样做:

// loop over data:
{               
sum_x += x[i];
sum_y += y[i];
sum_xy += x[i] * y[i];
sum_x2 += x[i] * x[i];
}

// means
double mean_x = sum_x / ninliers;
double mean_y = sum_y / ninliers;

float varx = sum_x2 - sum_x * mean_x;
float cov = sum_xy - sum_x * mean_y;
//检查零varx

param[0] = cov / varx;
param[1] = mean_y - param[0] * mean_x;
更多关于这个话题 (公式是一样的,它们只是乘以和除以N,一个样本sz。)。如果要将平面拟合到三维数据,请使用类似的方法-


免责声明:所有二次拟合都是线性的,并且在某种意义上是最优的,因为它们减少了参数中的噪声。但是,您可能对减少数据中的噪声感兴趣。您可能还希望忽略异常值,因为它们会大大影响您的解决方案。这两个问题都可以用RANSAC解决。请参阅我的帖子:

装配一条线可以通过不同的方式完成。 最小二乘法意味着最小化平方距离之和。 但你可以拿另一个成本函数作为例子,即(非平方)距离。但通常使用平方距离(最小二乘法)。 也有可能以不同的方式定义距离。正常情况下,您只需使用“y”轴作为距离。但也可以使用总/正交距离。在那里,在x和y方向计算距离。如果您在x方向上也有错误(让它成为测量时间),并且您没有在数据中保存的准确时间开始测量,则这可能更适合。对于最小二乘和总最小二乘直线拟合,存在封闭形式的算法。因此,如果你安装了其中一个,你将得到一条线,它与数据点的距离平方和最小。就你的辩护而言,再合适不过了。您可以通过使用另一个成本函数或以另一种方式定义距离来更改定义


关于将模型拟合到数据中,你可以想到很多东西,但通常它们都使用“最小二乘线拟合”,大多数情况下你都应该很好。但是,如果你有特殊情况,有必要考虑一下你在做什么。在几分钟内完成最小二乘法。思考什么方法最适合你的问题可以帮助你理解数学,这可能需要不确定的时间:-)。

本页描述的算法比维基百科更简单,没有额外的步骤来计算平均值等。几乎从那里引用,在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;
  }
};
本质上无法描述垂直线的直线方程。如果还想涵盖数据点由垂直线“最佳”描述的情况,则需要使用

A*x + B*y + C = 0
直线方程。您仍然可以修改当前算法以生成该等式:

y = k*x + b <=>
y - k*x - b = 0 <=>
B=1, A=-k, C=-b
x = xMean <=>
x - xMean = 0 <=>
A=1, B=0, C=-xMean
的“then”块中,如果
检查分母是否等于0,而不是
//失败:它似乎是一条垂直线
,则生成以下直线方程:

y = k*x + b <=>
y - k*x - b = 0 <=>
B=1, A=-k, C=-b
x = xMean <=>
x - xMean = 0 <=>
A=1, B=0, C=-xMean
这些公式是相同的,因为
nPoints*xMean==sumX
nPoints*xMean*yMean==sumX*yMean==sumY*xMean

直线方程为Ax+By+C=0

因此,它可以很容易地(当B不太接近于零时)转换为y=(-A/B)*x+(-C/B)

typedef双标量类型;
typedef std::数组<标量类型,2>点类型;
typedef std::向量<点类型>云类型;
布尔拟合(标量类型A、标量类型B、标量类型C、云类型常量和云)
{
if(cloud.size()<2){return false;}
标量_型X=0,Y=0,XY=0,X2=0,Y2=0;
用于(自动常量和点:云)
{//所有关于X和Y的计算都是对称的吗
X+=点[0];
Y+=点[1];
XY+=点[0]*点[1];
X2+=点[0]*点[0];
Y2+=点[1]*点[1];
}
X/=cloud.size();
Y/=cloud.size();
XY/=cloud.size();
X2/=cloud.size();
Y2/=cloud.size();
A=-(XY-X*Y);/!<两种解决方案通用
标量型Bx=X2-X*X;
标量_类型By=Y2-Y*Y;
如果(晶圆厂(Bx)<晶圆厂(By))/!<测试垂直度/水平度
{//直线更垂直。
B=通过;
标准:交换(A,B);
}
其他的
{//直线更为水平。
//经典解,当我们期望更像水平线时
B=Bx;
}
C=-(A*X+B*Y);
//可选规范化:
//标量型D=sqrt(A*A+B*B);
//A/=D;
//B/=D;
//C/=D;
返回true;
}

注意:这个答案不是对这个问题的回答,而是对这个被标记为“重复”的问题的回答(我认为是错误的),无法添加新的答案

问题要求:

找到距离所有点最小的直线?通过 距离我是指点和线之间的最短距离

“点与线之间”距离最常用的解释是欧几里德距离,“从所有点”最常用的解释是距离之和(绝对
double denominator = sumX2 - 2 * sumX * xMean + nPoints * xMean * xMean;
...
_slope = (sumXY - sumY*xMean - sumX * yMean + nPoints * xMean * yMean) / denominator;
typedef double scalar_type;
typedef std::array< scalar_type, 2 > point_type;
typedef std::vector< point_type > cloud_type;

bool fit( scalar_type & A, scalar_type & B, scalar_type & C, cloud_type const& cloud )
{
    if( cloud.size() < 2 ){ return false; }

    scalar_type X=0, Y=0, XY=0, X2=0, Y2=0;

    for( auto const& point: cloud )
    { // Do all calculation symmetric regarding X and Y
        X  += point[0];
        Y  += point[1];
        XY += point[0] * point[1];
        X2 += point[0] * point[0];
        Y2 += point[1] * point[1];
    }

    X  /= cloud.size();
    Y  /= cloud.size();
    XY /= cloud.size();
    X2 /= cloud.size();
    Y2 /= cloud.size();

    A = - ( XY - X * Y ); //!< Common for both solution

    scalar_type Bx = X2 - X * X;
    scalar_type By = Y2 - Y * Y;

    if( fabs( Bx ) < fabs( By ) ) //!< Test verticality/horizontality
    { // Line is more Vertical.
        B = By;
        std::swap(A,B);
    }
    else
    {   // Line is more Horizontal.
        // Classical solution, when we expect more horizontal-like line
        B = Bx;
    }
    C = - ( A * X + B * Y );

    //Optional normalization:
    // scalar_type  D = sqrt( A*A + B*B );
    // A /= D;
    // B /= D;
    // C /= D;
    return true;
}