最小二乘法(Least Squares Method)是一种常用的拟合方法,用于在数据点之间找到最佳的直线(或其他函数)拟合。以下是一个用C#实现简单线性回归(即一元最小二乘法)的示例代码。
1. 最小二乘法简介
对于一组数据点 (x1,y1),(x2,y2),…,(xn,yn)(x_1, y_1), (x_2, y_2), \ldots, (x_n, y_n)(x1,y1),(x2,y2),…,(xn,yn),最小二乘法通过最小化误差平方和来找到最佳拟合直线 y=ax+by = ax + by=ax+b,其中:
- aaa 是斜率
- bbb 是截距
误差平方和 SSS 定义为:
S=∑i=1n(yi−(axi+b))2S = \sum_{i=1}^{n} (y_i - (ax_i + b))^2S=∑i=1n(yi−(axi+b))2
通过求导并设导数为零,可以得到斜率 aaa 和截距 bbb 的公式:
a=n∑xiyi−∑xi∑yin∑xi2−(∑xi)2a = \frac{n\sum{x_i y_i} - \sum{x_i}\sum{y_i}}{n\sum{x_i^2} - (\sum{x_i})^2}a=n∑xi2−(∑xi)2n∑xiyi−∑xi∑yi b=∑yi−a∑xinb = \frac{\sum{y_i} - a\sum{x_i}}{n}b=n∑yi−a∑xi
2. C#实现代码
using System;
using System.Collections.Generic;
using System.Linq;
namespace LeastSquaresMethod
{
class Program
{
static void Main(string[] args)
{
// 示例数据点
List<DataPoint> dataPoints = new List<DataPoint>
{
new DataPoint(1, 2),
new DataPoint(2, 3),
new DataPoint(3, 5),
new DataPoint(4, 4),
new DataPoint(5, 6)
};
// 计算最小二乘法拟合结果
var result = LeastSquaresFit(dataPoints);
Console.WriteLine($"拟合直线: y = {result.Slope:F4}x + {result.Intercept:F4}");
// 可选:计算拟合优度(R²)
double rSquared = CalculateRSquared(dataPoints, result.Slope, result.Intercept);
Console.WriteLine($"拟合优度 (R²): {rSquared:F4}");
}
// 数据点结构
public class DataPoint
{
public double X { get; set; }
public double Y { get; set; }
public DataPoint(double x, double y)
{
X = x;
Y = y;
}
}
// 拟合结果结构
public class FitResult
{
public double Slope { get; set; }
public double Intercept { get; set; }
}
// 最小二乘法拟合函数
public static FitResult LeastSquaresFit(List<DataPoint> points)
{
int n = points.Count;
double sumX = points.Sum(p => p.X);
double sumY = points.Sum(p => p.Y);
double sumXY = points.Sum(p => p.X * p.Y);
double sumX2 = points.Sum(p => p.X * p.X);
double denominator = n * sumX2 - sumX * sumX;
if (denominator == 0)
{
throw new InvalidOperationException("无法计算拟合参数,因为分母为零。");
}
double slope = (n * sumXY - sumX * sumY) / denominator;
double intercept = (sumY - slope * sumX) / n;
return new FitResult { Slope = slope, Intercept = intercept };
}
// 计算拟合优度 R²
public static double CalculateRSquared(List<DataPoint> points, double slope, double intercept)
{
double meanY = points.Average(p => p.Y);
double ssTot = points.Sum(p => Math.Pow(p.Y - meanY, 2));
double ssRes = points.Sum(p => Math.Pow(p.Y - (slope * p.X + intercept), 2));
return 1 - (ssRes / ssTot);
}
}
}
3. 代码说明
-
数据结构:
DataPoint
类用于存储单个数据点的 xxx 和 yyy 值。FitResult
类用于存储拟合直线的斜率和截距。
-
LeastSquaresFit 方法:
- 计算所需的各类求和,如 ∑x\sum{x}∑x、∑y\sum{y}∑y、∑xy\sum{xy}∑xy 和 ∑x2\sum{x^2}∑x2。
- 使用最小二乘法公式计算斜率 aaa 和截距 bbb。
- 返回包含斜率和截距的
FitResult
对象。
-
CalculateRSquared 方法:
- 计算拟合优度 R2R^2R2,表示模型对数据的解释程度。
- R2R^2R2 值越接近1,表示拟合效果越好。
-
Main 方法:
- 创建示例数据点。
- 调用
LeastSquaresFit
方法进行拟合。 - 输出拟合直线方程。
- 计算并输出拟合优度 R2R^2R2。
4. 运行结果示例
运行上述代码,可能得到如下输出:
拟合直线: y = 0.8000x + 1.2000
拟合优度 (R²): 0.8205