zoukankan      html  css  js  c++  java
  • 最小二乘线性及平面拟合原理及C++实现

    一、线性最小二乘拟合

    使用一个简单函数在整体上逼近已知函数,使其在整体上尽可能与原始数据曲线近似。记为:

     称之为拟合曲线,若该函数为插值多项式,则所有偏差为零。

    但实际情况中,我们不可能要求近似曲线

    y =

     严格通过这么多数据点。但为了使其尽可能反映所给数据的变化趋势,我们可以要求偏差的绝对值尽可能小,甚至是所有偏差中的最大值尽可能小。我们可以通过使选取的近似曲线在节点xi 处的偏差的平方和达到最小来实现这一目标,这一原则就是 最小二乘原则。

    按最小原则选择的拟合曲线就称为最小二乘拟合曲线,此方法称为最小二乘法。

    实用公式推导:

     假设我们此处有这样一组数据点,这些点的分布接近于在一条直线上,因此选一条直线(一条曲线则加入对应方程推导)来拟合这组数据,令:

    根据最小二乘原则,有:

     

     令a0,a1为未知数,则此处转换为求二元函数S(a0,a1)的极小点问题:

     由此可得:

     联立解得:

     

     

    即得到了待求的拟合直线段。

    C++实现:

    bool gFittingLine(double *xArray, double *yArray, int firstIndex, int lastIndex,
    				  double &a, double &b)
    {
       int count = lastIndex-firstIndex+1;
        if(count < 2) return false;
        double s0 = (double)count, s1 = 0, s2 = 0, t0 = 0, t1 = 0;
        for(int i=firstIndex;i<=lastIndex;i++) 
    	{
    		s1 += xArray[i];
    		s2 += (xArray[i]*xArray[i]);
    		t0 += yArray[i];
    		t1 += (xArray[i]*yArray[i]);
        }
        double d = s0*s2-s1*s1;
        b = (s2*t0-s1*t1)/d;
        a = (s0*t1-s1*t0)/d;
        return true;
    }
    

      实现对二维平面离散点的曲线拟合

    二、最小二乘面拟合

    对空间中的一系列散点,寻求一个近似平面,与线性最小二乘一样,只是变换了拟合方程:

    使用平面的一般方程:

    Ax + By + CZ + D = 0

    可以令平面方程为:

     由最小二乘法知:

     同样分别取 a0,a1,a2的偏导数:

     即是:

     换算为矩阵形式有:

     可以直接通过克拉默法则求出a0,a1,a2的行列式表达式,有:

     c++实现(gDaterm3() 为自定义的三阶行列式计算函数):

    bool gFittingPlane(double *x, double *y, double *z, int n, double &a, double &b, double &c)
    {
    	int i;
    	double x1, x2, y1, y2, z1, xz, yz, xy, r;
    
    	x1 = x2 = y1 = y2 = z1 = xz = yz = xy = 0;
    	for(i=0; i<n; i++)
    	{
    		x1 += x[i];
    		x2 += x[i]*x[i];
    		xz += x[i]*z[i];
    
    		y1 += y[i];
    		y2 += y[i]*y[i];
    		yz += y[i]*z[i];
    
    		z1 += z[i]; 
    		xy += x[i]*y[i];
    	}
    
    	r = gDeterm3(x2, xy, x1, xy, y2, y1, x1, y1, n);
    	if(IS_ZERO(r)) return false;
    
    	a = gDeterm3(xz, xy, x1, yz, y2, y1, z1, y1, n) / r;
    	b = gDeterm3(x2, xz, x1, xy, yz, y1, x1, z1, n) / r;
    	c = gDeterm3(x2, xy, xz, xy, y2, yz, x1, y1, z1) / r;
    
    	return true;
    }
    

      

  • 相关阅读:
    mysql 数据库 II(数据类型)
    mysql 数据库 I
    网络协议
    Python 类IV(类成员,异常处理等)
    Python 类III(三大特性,约束,super)
    Python 类II
    类加载机制
    Java新篇章之集合
    Java 类类型之 String 类型
    java 多态
  • 原文地址:https://www.cnblogs.com/zhangli07/p/12013561.html
Copyright © 2011-2022 走看看