2023-12-03 C语言最小二乘法备忘
点击 <C 语言编程核心突破> 快速C语言入门
C语言最小二乘法备忘
- 前言
- 一、数学公式
- 二、代码
- 总结
前言
要解决问题: 最小二乘法实现线性回归的C语言实现, 这个数学公式转为C语言.
一、数学公式
设有 n n n 组数据
( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯ , ( x n , y n ) \huge (x_1,y_1),(x_2,y_2),\cdots,(x_n,y_n) (x1,y1),(x2,y2),⋯,(xn,yn)
要求解线性方程
y = a x + b \huge y=ax+b y=ax+b
使得所有数据到直线的距离之和最小。
首先,计算数据的均值
x
ˉ
=
1
n
∑
i
=
1
n
x
i
\huge \bar{x}=\frac{1}{n}\sum_{i=1}^nx_i
xˉ=n1i=1∑nxi
和
y ˉ = 1 n ∑ i = 1 n y i \huge \bar{y}=\frac{1}{n}\sum_{i=1}^ny_i yˉ=n1i=1∑nyi
然后,计算 x x x 和 y y y 的协方差
s x y = 1 n ∑ i = 1 n ( x i − x ˉ ) ( y i − y ˉ ) \huge s_{xy}=\frac{1}{n}\sum_{i=1}^n(x_i-\bar{x})(y_i-\bar{y}) sxy=n1i=1∑n(xi−xˉ)(yi−yˉ)
和 x x x 的方差
s x 2 = 1 n ∑ i = 1 n ( x i − x ˉ ) 2 \huge s_{x}^2=\frac{1}{n}\sum_{i=1}^n(x_i-\bar{x})^2 sx2=n1i=1∑n(xi−xˉ)2
最后,直线的斜率 a a a 和截距 b b b 分别为:
a = s x y s x 2 \huge a=\frac{s_{xy}}{s_{x}^2} a=sx2sxy
b = y ˉ − a x ˉ \huge b=\bar{y}-a\bar{x} b=yˉ−axˉ
以上就是最小二乘法线性回归的数学公式,不使用矩阵。
二、代码
最小二乘法是一种数学优化技术,它通过最小化误差的平方和寻找数据的最佳函数匹配。
下面是一个使用C语言实现最小二乘法的例子:
#include <stdio.h>
// 最小二乘法
void leastSqaureMethod(double arrayX[], double arrayY[], const int num,
double *numA, double *numB)
{
// 计算x和y的总和, 以计算平均值
double sumX = 0.0;
double sumY = 0.0;
for (int i = 0; i != num; ++i)
{
sumX += arrayX[i];
sumY += arrayY[i];
}
// 计算x和y的平均值
double aveX = sumX / num;
double aveY = sumY / num;
// 计算n倍的x和y的协方差, 以及x的方差
double nSXY = 0.0;
double nS2X = 0.0;
for (int i = 0; i != num; ++i)
{
nSXY += (arrayX[i] - aveX) * (arrayY[i] - aveY);
nS2X += (arrayX[i] - aveX) * (arrayX[i] - aveX);
}
// 计算系数a和b
*numA = nSXY / nS2X;
*numB = aveY - (*numA) * aveX;
}
int main()
{
double BOD5[] = {234, 251, 252, 285, 231, 202, 201, 238, 257,
211, 225, 220, 226, 268, 279, 300, 286, 254,
221, 232, 210, 219, 218, 222, 231};
double CODCr[] = {532, 634, 559, 691, 484, 482, 474, 556, 512,
423, 541, 498, 551, 584, 621, 614, 547, 587,
529, 577, 485, 501, 500, 532, 561};
double numA;
double numB;
leastSqaureMethod(BOD5, CODCr, 25, &numA, &numB);
printf("f(x) = %lf * x + %lf\n", numA, numB);
return 0;
}
此程序中的函数leastSquareMethod
实现了最小二乘法,用于通过给定的一组数据点,求出最佳拟合直线的系数a和b的值。
其中,double arrayX[]
和double arrayY[]
分别为输入数据点的横坐标和纵坐标数组,const int num
为数据点的数量,double *numA
和double *numB
为求得的系数a
和b
的返回值。
在主函数中,定义了两个数组BOD5
和CODCr
,分别存储了25组数据点。
然后,调用函数leastSquareMethod
计算出系数a和b的值,并将结果输出到控制台上。
总结
根据数学公式翻译成C语言, 简单的公式还是不太难的, 需要注意的是精度, 以及是否可能产生溢出, 通常来讲, double
足够了.
点击 <C 语言编程核心突破> 快速C语言入门