当前位置:   article > 正文

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

最小二乘法拟合

目录

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的均值

代码如下:

  1. double calculate(std::vector<double> xs,std::vector<double> ys){
  2. int len = xs.size();
  3. double Lxy = 0;
  4. double Lxx = 0;
  5. for(int i = 0; i < len ; i++){
  6. Lxy += xs[i] * ys[i];
  7. Lxx += qPow(xs[i],2);
  8. }
  9. double ret = 0;
  10. ret = Lxy / Lxx;
  11. return ret;
  12. }

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的含义同上)

代码如下:

  1. double *calculate1(std::vector<double> xs,std::vector<double> ys){
  2. int len = xs.size();
  3. //结果
  4. double *ret = new double[2];
  5. double ex = 0;//x坐标的均值
  6. double ey = 0;//y坐标的均值
  7. double Lxx = 0;//x坐标的平方差*len
  8. double Lxy = 0;//(Xi-ex)*(Yi-ey)
  9. //辅助计算
  10. double xsum = 0;//x的和
  11. double ysum = 0;//y的和
  12. //计算xusm
  13. for(int i = 0; i < len ; i++){
  14. xsum += xs[i];
  15. ysum += ys[i];
  16. }
  17. ex = xsum / len;
  18. ey = double(ysum / len);
  19. for(int i = 0; i < len ; i++){
  20. Lxx += pow(xs[i]-ex,2);
  21. Lxy += (xs[i]-ex)*(ys[i]-ey);
  22. }
  23. ret[1] = Lxy / Lxx;//计算a1
  24. ret[0] = ey - ret[1]*ex;//计算a0
  25. return ret;
  26. }

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)

 代码如下:

  1. double *calculate(std::vector<double> xs,std::vector<double> ys){
  2. int len = xs.size();
  3. double ey = 0;//y的均值
  4. double ex1 = 0;//x的均值
  5. double ex3 = 0;//x的三次方的均值
  6. double L11 = 0;//x的平方差
  7. double L12 = 0;//x的3次方的平方差*len
  8. double L21= 0;//等于L12
  9. double L1y = 0;//(Xi-ex)*(Yi-ey)的和
  10. double L2y = 0;//(Xi^3-ex3)*(Yi-ey)的和
  11. double L22 = 0;//x的3次方的平方差*len
  12. double Lyy = 0;//y的平方差*len
  13. double ysum = 0;
  14. double xsum1 = 0;
  15. double xsum3 = 0;
  16. //计算均值
  17. for(int i = 0; i < len; i++){
  18. ysum += ys[i];//y的总和
  19. xsum1 += xs[i];//x的总和
  20. xsum3 += std::pow(xs[i],3);//x的3次方的总和
  21. }
  22. //计算各个值
  23. ey = ysum / len;
  24. ex1 = xsum1 / len;
  25. ex3 = xsum3 / len;
  26. for(int i = 0 ; i < len ;i++){
  27. L11 += qPow(xs[i]-ex1,2);//x的方差*len
  28. L12 += (xs[i]-ex1)*(qPow(xs[i],3)-ex3);
  29. L1y += (xs[i]-ex1)*(ys[i]-ey);
  30. L2y += (qPow(xs[i],3)-ex3)*(ys[i]-ey);
  31. L22 += qPow((qPow(xs[i],3)-ex3),2);//x的3次方的方差*len
  32. Lyy += qPow(ys[i]-ey,2);
  33. }
  34. L21 = L12;
  35. double ret[3];
  36. ret[2] = (L2y * L11 - L1y * L21)/(L11 * L22 - L12 * L21);
  37. ret[1] = (L1y * L22 - L2y * L12)/(L11 * L22 - L12 * L21);
  38. ret[0] = ey - ret[1]*ex1 - ret[2]*ex3;
  39. return ret;
  40. }

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/102135
推荐阅读
相关标签
  

闽ICP备14008679号