最小二乘法可根据坐标点的信息拟合出一条最优直线,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;