最小二乘法的几种拟合函数

目录

1.最小二乘法的原理和解决的问题

2.最小二乘法的公式解法

2.1  拟合h(x) = a * x

2.2 拟合 h(x) = a0 + a1*x

2.3拟合 h(x) = a0 + a1 *x + a3 * x^3


 因为采用矩阵法来进行最小二乘法的函数拟合时,会出现系数矩阵的逆矩阵不存在的情况有一定的局限性,所以本篇对公式法进行简单说明。并用c++进行代码的书写。

1.最小二乘法的原理和解决的问题

最下二乘法的形式:

目标函数 =  \sum (观测值  -  理论值)^2^{}

        观测值就是我们实际数据中的值,理论值就是我们进行函数拟合后用拟合函数计算出的值。

本篇中我们以最简单的线性回归为例进行说明。

        我们有n组样本(Xi,Yi) i = (1,2,3,……,n)

        拟合函数的形式:h(x) = a0 + a1 * x + a2 *x^2 + a3 *x^3.

        最小二乘法要做的就是找到最小的一组 a(a0 、a1、a2、a3……),使得

        \sum (h(x) -  yi)^2^{}最小。方法就是对各个系数求偏导,并让偏导数等于0即可。

2.最小二乘法的公式解法

2.1  拟合h(x) = a * x

  \sum \left ( h(xi) - yi) \right )^{2}    对a求偏导得:

 2 * \sum \left ( a*xi-yi \right )*xi = 0

 化简得:a = Lxy / Lxx

 其中  Lxx = \sum (xi - ex)^{2}  ,   Lxy = \sum \left ( xi - ex) * (yi - ey) \right ),ex为x的均值,ey为y的均值

代码如下:

double calculate(std::vector<double> xs,std::vector<double> ys){

    int len = xs.size();

    double Lxy = 0;
    double Lxx = 0;

    for(int i = 0; i < len ; i++){
        Lxy += xs[i] * ys[i];
        Lxx += qPow(xs[i],2);
    }

    double ret = 0;
    ret = Lxy / Lxx;
    return ret;
}

2.2 拟合 h(x) = a0 + a1*x

\sum \left ( h(xi) - yi) \right )^{2}对a0和a1分别求偏导的得:

a0:2*\sum \left (a0 + a1*xi - yi \right )^{} = 0

a1:   2 *\sum \left ( a0 + a1 *xi - yi \right ) * xi = 0

 联立两个方程解得:a0 = ey - a1 * ex 

                                 a1 = Lxy / Lxx(ex、ey、Lxy 和Lxx的含义同上)

代码如下:

double *calculate1(std::vector<double> xs,std::vector<double> ys){
    int len = xs.size();

    //结果
    double *ret = new double[2];

    double ex = 0;//x坐标的均值
    double ey = 0;//y坐标的均值
    double Lxx = 0;//x坐标的平方差*len
    double Lxy = 0;//(Xi-ex)*(Yi-ey)

    //辅助计算
    double xsum = 0;//x的和
    double ysum = 0;//y的和

    //计算xusm
    for(int i = 0; i < len ; i++){
        xsum += xs[i];
        ysum += ys[i];
    }
    ex = xsum / len;
    ey = double(ysum / len);
    for(int i = 0; i < len ; i++){
        Lxx += pow(xs[i]-ex,2);
        Lxy += (xs[i]-ex)*(ys[i]-ey);
    }


    ret[1] = Lxy / Lxx;//计算a1
    ret[0] = ey - ret[1]*ex;//计算a0
    return ret;
}

2.3拟合 h(x) = a0 + a1 *x + a3 * x^3

\sum \left ( h(xi) - yi) \right )^{2}对a0、a1和a3分别求偏导的得:

a0:    2*\sum \left ( a0 + a1 * x + a3 * x^3 -yi) \right ) = 0;

a1:   2*\sum \left ( a0 + a1 * x +a3 * x^3 - yi\right ) * xi = 0;

a3 :   2*\sum \left ( a0 + a1 * x + a3 *x^3 - yi \right ) * x^3 = 0

联立方程组解得:

a0 = ey - a1*ex - a3 * ex^3( ey为y 的均值,ex 为x的均值,ex^3为x^3的均值)

a1 = (Lxy * L(x^3)(x^3) - Lx^3 y * Lxy) / (Lxx *L(x^3)(x^3) - Lxy*Lyx)

a3 = (Lx^3y * Lxx - Lxy * L(x^3)*x) / (Lxx*L(x^3*x^3) - Lxy*Lyx)

Lxy、Lxx含义同上

L(x^3)(x^3)表示:\sum \left ( xi^3 - ex3 \right )^{2}

Lx3y表示:\sum \left (xi^3 - ex3 \right ) * (yi -ey)

 代码如下:

double *calculate(std::vector<double> xs,std::vector<double> ys){

    int len = xs.size();

    double ey = 0;//y的均值
    double ex1 = 0;//x的均值
    double ex3 = 0;//x的三次方的均值
    double L11 = 0;//x的平方差
    double L12 = 0;//x的3次方的平方差*len
    double L21= 0;//等于L12
    double L1y = 0;//(Xi-ex)*(Yi-ey)的和
    double L2y = 0;//(Xi^3-ex3)*(Yi-ey)的和
    double L22 = 0;//x的3次方的平方差*len
    double Lyy = 0;//y的平方差*len

    double ysum = 0;
    double xsum1 = 0;
    double xsum3 = 0;

    //计算均值
    for(int i = 0; i < len; i++){

        ysum += ys[i];//y的总和

        xsum1 += xs[i];//x的总和
        xsum3 += std::pow(xs[i],3);//x的3次方的总和
    }
    //计算各个值
    ey = ysum / len;
    ex1 = xsum1 / len;
    ex3 = xsum3 / len;

    for(int i = 0 ; i < len ;i++){
        L11 += qPow(xs[i]-ex1,2);//x的方差*len

        L12 += (xs[i]-ex1)*(qPow(xs[i],3)-ex3);

        L1y += (xs[i]-ex1)*(ys[i]-ey);
        L2y += (qPow(xs[i],3)-ex3)*(ys[i]-ey);

        L22 += qPow((qPow(xs[i],3)-ex3),2);//x的3次方的方差*len

        Lyy += qPow(ys[i]-ey,2);
    }
    L21 = L12;
    double ret[3];
    ret[2] = (L2y * L11 - L1y * L21)/(L11 * L22 - L12 * L21);
    ret[1] = (L1y * L22 - L2y * L12)/(L11 * L22 - L12 * L21);
    ret[0] = ey - ret[1]*ex1 - ret[2]*ex3;
   
    return ret;
}

以上是我在编写一个插值函数时遇到矩阵法不可以求出拟合函数后,从原始的概念入手进行的函数拟合,如有差错之处欢迎批评指正。

  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 最小二乘法是一种常见的数据拟合方法,它可以通过已知数据点来拟合出一条曲线,使得拟合曲线与数据点之间的误差最小。这种方法常用于统计学和工程学中的数据分析。 在C语言中实现最小二乘法曲线拟合可以通过数值分析库或线性代数库来实现。具体步骤包括以下几步: 1. 输入已知数据点的X和Y坐标。 2. 根据已知数据点计算拟合曲线的系数,例如多项式系数。 3. 使用拟合曲线的系数和新的X坐标来计算相应的Y坐标,可以得到一条新的曲线。 4. 可以通过比较已知数据点和新曲线之间的误差来评估拟合的好坏。 最小二乘法曲线拟合可以用于许多应用程序,例如曲线拟合、信号处理和数据压缩等领域。在科学和工程研究中,最小二乘法曲线拟合也是一个重要的工具,在计算机程序开发中也得到广泛的应用。 ### 回答2: 最小二乘法是统计学中的一种方法,常用于数学模型的构建和参数估计。在C语言中,可以使用最小二乘法进行曲线拟合。 首先,需要确定要拟合的曲线的类型(比如线性、二次、指数等)和函数式形式。然后,需要收集一组有序的数据点,包括自变量和因变量的数值,以用于曲线拟合。这些数据可以是实验结果、观测数据或者是数学模型。 接下来,使用最小二乘法计算出一组拟合参数,使得拟合曲线在数据点处的拟合误差最小。这个过程涉及到矩阵运算和线性代数的知识,需要使用C语言中的相关库函数来计算。 最后,可以使用计算得到的拟合参数来生成拟合曲线,以便进行预测和分析。如果需要,还可以对拟合曲线进行剩余误差分析,来评估拟合质量和确定信度区间。 总的来说,最小二乘法是一种强大的工具,可以在C语言中进行曲线拟合。但是需要注意数据的质量和数量,以及正确的数学建模和参数估计方法,以确保拟合结果的可靠性和应用价值。 ### 回答3: 最小二乘法是一种用于数据拟合的方法,可用于生成最佳拟合曲线。在C语言中,我们可以使用最小二乘法来构建拟合数据的曲线。最小二乘法的基本思想是通过最小化误差平方和来获取最优拟合曲线。例如,对于一个给定的数据点集,我们可以通过拟合一个曲线来估计这些数据点的趋势。 在使用C语言实现最小二乘法曲线拟合时,我们需要计算数据集的平均值,以及每个数据点的方差和协方差。这些数据可以用来计算斜率和截距,以生成最佳拟合曲线。 在C语言中,我们可以使用数学库函数和数组来实现最小二乘法曲线拟合。通过调用数学库中的函数,如pow、sqrt和fabs等函数,可以计算数据的平均值、标准偏差和相关系数。使用数组来存储数据集是一种方便的做法,它可以让我们在使用for循环时更轻松地进行数据的迭代。 总之,最小二乘法是一种有效的数据拟合方法,而在C语言中通过调用数学库函数和使用数组来实现最小二乘法曲线拟合。使用C语言实现最小二乘法曲线拟合需要仔细计算每项和确保正确性,这需要对数学和编程的知识都有深入的了解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值