WPF 最小二乘法的简单的实现

最小二乘法可根据坐标点的信息拟合出一条最优直线,y=bx+a,保证每个坐标点到直线的距离之和达到最小值。

GIF截图

方法一

代码

   /// <summary>
  ///  简单最小二乘法
 /// </summary>
 /// <param name="ep">包含Point的集合即可</param>
 /// <returns>返回两个系数,a,b</returns>
 private System.Dynamic.ExpandoObject OLS(List<EPS> ep)
 {
     dynamic model = new System.Dynamic.ExpandoObject();
     var mx = ep.Sum(z => z.X) / ep.Count;
     var my = ep.Sum(z => z.Y) / ep.Count;
     var sum2 = ep.Select(p => (p.X - mx) * (p.X - mx)).Sum();
     var smxy = ep.Select(p => (p.Y - my) * (p.X - mx)).Sum();
     model.A = smxy / sum2;
     model.B = my - model.a * mx;
     //两个系数
     return model;
 }

具体使用也很方便,返回两个系数后乘法就可以。

使用

 dynamic b = OLS(items);

 for (double i = EP[0].X; i < items.Last().X; i += 5)
 {
     //var v = Math.Pow(Math.E, b.Y);
     // var l = Math.Pow(Math.E, b.X * i);
     EP.Add(new EPS(new Point(i, b.X * i + b.Y), false));
     //EP.Add(new EPS(new Point(i, v * l), false));
    // EP.Add(new EPS(new Point(i + 5, MultiPoint(items, i + 5) + 5), false));
 }

原文链接:https://www.cnblogs.com/T-ARF/p/14615281.html

方法二

/// <summary>
/// 对一组点通过最小二乘法进行线性回归
/// </summary>
/// <param name="parray"></param>
public static void LinearRegression(Point[] parray)
{
  //点数不能小于2
  if (parray.Length < 2)
  {
    Console.WriteLine("点的数量小于2,无法进行线性回归");
    return;
  }
  //求出横纵坐标的平均值
  double averagex = 0, averagey = 0;
  foreach (Point p in parray)
  {
    averagex += p.X;
    averagey += p.Y;
  }
  averagex /= parray.Length;
  averagey /= parray.Length;
  //经验回归系数的分子与分母
  double numerator = 0;
  double denominator = 0;
  foreach (Point p in parray)
  {
    numerator += (p.X - averagex) * (p.Y - averagey);
    denominator += (p.X - averagex) * (p.X - averagex);
  }
  //回归系数b(Regression Coefficient)
  double RCB = numerator / denominator;
  //回归系数a
  double RCA = averagey - RCB * averagex;
  Console.WriteLine("回归系数A: " + RCA.ToString("0.0000"));
  Console.WriteLine("回归系数B: " + RCB.ToString("0.0000"));
  Console.WriteLine(string.Format("方程为: y = {0} + {1} * x",
    RCA.ToString("0.0000"), RCB.ToString("0.0000")));
  //剩余平方和与回归平方和
  double residualSS = 0;  //(Residual Sum of Squares)
  double regressionSS = 0; //(Regression Sum of Squares)
  foreach (Point p in parray)
  {
    residualSS +=
      (p.Y - RCA - RCB * p.X) *
      (p.Y - RCA - RCB * p.X);
    regressionSS +=
      (RCA + RCB * p.X - averagey) *
      (RCA + RCB * p.X - averagey);
  }
  Console.WriteLine("剩余平方和: " + residualSS.ToString("0.0000"));
  Console.WriteLine("回归平方和: " + regressionSS.ToString("0.0000"));
}

调用

//设置一个包含9个点的数组
  Point[] array = new Point[9];
  array[0] = new Point(0, 66.7);
  array[1] = new Point(4, 71.0);
  array[2] = new Point(10, 76.3);
  array[3] = new Point(15, 80.6);
  array[4] = new Point(21, 85.7);
  array[5] = new Point(29, 92.9);
  array[6] = new Point(36, 99.4);
  array[7] = new Point(51, 113.6);
  array[8] = new Point(68, 125.1);
  LinearRegression(array);

在这里插入图片描述

方法三

/****************声明定义*************************/
 
            float[] distance = new float[271];  
 
            float length;
 
            float[] ArrPoint_X = new float[270];
            float[] ArrPoint_Y = new float[270];
 
            ArrayList pointX = new ArrayList();
            ArrayList pointY = new ArrayList();
            float lengthX;
            float lengthY;
            float theta;
            float dis_length;
            float dis_theta;
 
/****************函数实现*************************//最小二乘法,拟合直线
            int ArrPoint_Count = 0;
            for (int i = (135 - 23 * 3); i <= (135 + 23 * 3); i++)   //边缘检测
            {
                length = distance[i];
                if ((length > 100) && (length < User_length))
                {
                    theta = (float)((i / 3) + 45);          //极坐标系往直角坐标系转换
                    lengthX = length * (float)(Math.Cos(Math.PI * theta / 180));
                    lengthY = length * (float)(Math.Sin(Math.PI * theta / 180));
                    pointX.Add(lengthX);
                    pointY.Add(lengthY);
                    ArrPoint_X[ArrPoint_Count] = lengthX;
                    ArrPoint_Y[ArrPoint_Count] = lengthY;
                    ArrPoint_Count++;
                }
            }
 
            float averagex = 0, averagey = 0;
            foreach (float i in pointX)
            {
                averagex += i;
            }
            foreach (float j in pointY)
            {
                averagey += j;
            }
            averagex /= pointX.Count;        //  取X坐标的平均数
            averagey /= pointY.Count;        //  取Y坐标的平均数
 
            //经验回归系数的分子与分母
            float numerator = 0;
            float denominator = 0;
            for (int i = 0; i < pointX.Count; i++)
            {
                numerator += (ArrPoint_X[i] - averagex) * (ArrPoint_Y[i] - averagey);
                denominator += (ArrPoint_X[i] - averagex) * (ArrPoint_X[i] - averagex);
            }
            //回归系数b(Regression Coefficient)   y = bx + a ;
            float RCB = numerator / denominator;
            //回归系数a
            float RCA = averagey - RCB * averagex;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值