分享

C#利用最小二乘法拟合任意次函数曲线...

 logicsoft 2022-12-06 发布于浙江

一、背景知识

给出一组离散点,确定一个函数逼近原函数,插值是这样的一种手段。在实际中,数据不可避免的会有误差,插值函数会将这些误差也包括在内。

因此,我们需要一种新的逼近原函数的手段: ①不要求过所有的点(可以消除误差影响); ②尽可能表现数据的趋势,靠近这些点。

二、定义

最小二乘法(又称最小平方法)是一种数学技术。它通过最小化误差的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小 [1]  [6-7]  。

最小二乘法还可用于曲线拟合,其他一些优化问题也可通过最小化能量或最大化熵用最小二乘法来表达,具体可以查阅相关资料

三、最小二乘法拟合任意次函数曲线实例

  1. public class LeastSquare//最小二乘法
  2. {
  3. ///<summary>
  4. ///用最小二乘法拟合二元多次曲线(任意次)
  5. ///</summary>
  6. ///<param name="arrX">已知点的x坐标集合</param>
  7. ///<param name="arrY">已知点的y坐标集合</param>
  8. ///<param name="length">已知点的个数</param>
  9. ///<param name="dimension">方程的最高次数</param>
  10. #region 总计算方法
  11. public static double[] MultiLine(double[] arrX, double[] arrY, int length, int dimension)//二元多次线性方程拟合曲线
  12. {
  13. int n = dimension + 1; //dimension次方程需要求 dimension+1个 系数
  14. double[,] Guass = new double[n, n + 1]; //高斯矩阵 例如:y=a0+a1*x+a2*x*x
  15. for (int i = 0; i < n; i++)
  16. {
  17. int j;
  18. for (j = 0; j < n; j++)
  19. {
  20. Guass[i, j] = SumArr(arrX, j + i, length);
  21. }
  22. Guass[i, j] = SumArr(arrX, i, arrY, 1, length);
  23. }
  24. return ComputGauss(Guass, n);//返回值是函数的系数
  25. }
  26. #endregion
  27. #region 求数组的元素的n次方的和1(中间方法)
  28. public static double SumArr(double[] arr, int n, int length)
  29. {
  30. double s = 0;
  31. for (int i = 0; i < length; i++)
  32. {
  33. if (arr[i] != 0 || n != 0)
  34. s = s + Math.Pow(arr[i], n);
  35. else
  36. s = s + 1;
  37. }
  38. return s;
  39. }
  40. #endregion
  41. #region 求数组的元素的n次方的和2(中间方法)
  42. public static double SumArr(double[] arr1, int n1, double[] arr2, int n2, int length)
  43. {
  44. double s = 0;
  45. for (int i = 0; i < length; i++)
  46. {
  47. if ((arr1[i] != 0 || n1 != 0) && (arr2[i] != 0 || n2 != 0))
  48. s = s + Math.Pow(arr1[i], n1) * Math.Pow(arr2[i], n2);
  49. else
  50. s = s + 1;
  51. }
  52. return s;
  53. }
  54. #endregion
  55. #region 返回值是函数的系数(中间方法)
  56. public static double[] ComputGauss(double[,] Guass, int n)
  57. {
  58. int i, j;
  59. int k, m;
  60. double temp;
  61. double max;
  62. double s;
  63. double[] x = new double[n];
  64. for (i = 0; i < n; i++) x[i] = 0.0;//初始化
  65. for (j = 0; j < n; j++)
  66. {
  67. max = 0;
  68. k = j;
  69. for (i = j; i < n; i++)
  70. {
  71. if (Math.Abs(Guass[i, j]) > max)
  72. {
  73. max = Guass[i, j];
  74. k = i;
  75. }
  76. }
  77. if (k != j)
  78. {
  79. for (m = j; m < n + 1; m++)
  80. {
  81. temp = Guass[j, m];
  82. Guass[j, m] = Guass[k, m];
  83. Guass[k, m] = temp;
  84. }
  85. }
  86. if (0 == max)
  87. {
  88. // "此线性方程为奇异线性方程"
  89. return x;
  90. }
  91. for (i = j + 1; i < n; i++)
  92. {
  93. s = Guass[i, j];
  94. for (m = j; m < n + 1; m++)
  95. {
  96. Guass[i, m] = Guass[i, m] - Guass[j, m] * s / (Guass[j, j]);
  97. }
  98. }
  99. }//结束for (j=0;j<n;j++)
  100. for (i = n - 1; i >= 0; i--)
  101. {
  102. s = 0;
  103. for (j = i + 1; j < n; j++)
  104. {
  105. s = s + Guass[i, j] * x[j];
  106. }
  107. x[i] = (Guass[i, n] - s) / Guass[i, i];
  108. }
  109. return x;
  110. }
  111. #endregion
  112. }

 

文章知识点与官方知识档案匹配,可进一步学习相关知识

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多