1. 程式人生 > 其它 >C#實現最小二乘法

C#實現最小二乘法

技術標籤:編碼日記c#技術

根據http://zh.wikipedia.org/wiki/%E6%9C%80%E5%B0%8F%E4%BA%8C%E4%B9%98%E6%B3%95裡面的說法:

線性函式模型

典型的一類函式模型是線性函式模型。最簡單的線性式是,寫成矩陣式,為

直接給出該式的引數解:

其中\bar t = \frac{1}{n} \sum_{i=1}^n t_i,為t值的算術平均值。也可解得如下形式:

b1為斜率,b0為截距,可以先根據x,y陣列,以及上面的公式先計算出斜率,再計算截距。

因為原來參考程式碼中,返回為一個數組,根據與原來程式碼的相容性,呼叫LinearResult(double[],double[])方法返回是一個數組。result[0]為斜率,result[1]為截距。

  1. class Linear

  2. {

  3. public double[] LinearResult(double[] arrayX, double[] arrayY)

  4. {

  5. double[] result = { 0, 0 };

  6. if (arrayX.Length == arrayY.Length)

  7. {

  8. double averX = arrayX.Average();

  9. double averY = arrayY.Average();

  10. result[0] = Scale(averX, averY, arrayX, arrayY);

  11. result[1] = Offset(result[0],averX,averY);

  12. }

  13. return result;

  14. }

  15. private double Scale(double averX, double averY, double[] arrayX, double[] arrayY)

  16. {

  17. double scale = 0;

  18. if (arrayX.Length == arrayY.Length)

  19. {

  20. double Molecular = 0;

  21. double Denominator = 0;

  22. for (int i = 0; i < arrayX.Length; i++)

  23. {

  24. Molecular += (arrayX[i] - averX) * (arrayY[i] - averY);

  25. Denominator += Math.Pow((arrayX[i] - averX), 2);

  26. }

  27. scale = Molecular / Denominator;

  28. }

  29. return scale;

  30. }

  31. private double Offset(double scale, double averX,double averY)

  32. {

  33. double offset = 0;

  34. offset = averY - scale * averX;

  35. return offset;

  36. }

  37. }

/// <summary> /// 計算一元一次方程係數(利用最小二乘法) /// 20200320新增 /// </summary> /// <param name="xValues"></param> /// <param name="yValues"></param> /// <returns></returns> private double[] CalCoefficientOfLinearEquation(double[] xValues, double[] yValues) { if (xValues.Length != yValues.Length) return null; int valCount = xValues.Length; //計算X2=∑(xi)^2 , X=∑ xi , Yx=∑(xi*yi) , Y=∑ yi double X2 = 0; double X = 0; double Yx = 0; double Y = 0; for (int i = 0; i < valCount; i++) { X2 += Math.Pow(xValues[i], 2); X += xValues[i]; Yx += xValues[i] * yValues[i]; Y += yValues[i]; } //計算線性方程係數y=ax+b double a = (Yx * valCount - X * Y) / (X2 * valCount - X * X); double b = (X2 * Y - Yx * X) / (X2 * valCount - X * X); //返回係數的陣列 double[] temp = new double[] { a, b }; return temp; }