2023-12-03 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=1nxi

y ˉ = 1 n ∑ i = 1 n y i \huge \bar{y}=\frac{1}{n}\sum_{i=1}^ny_i yˉ=n1i=1nyi

然后,计算 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=1n(xixˉ)(yiyˉ)

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=1n(xixˉ)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 

// 最小二乘法
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 *numAdouble *numB为求得的系数ab的返回值。

在主函数中,定义了两个数组BOD5CODCr,分别存储了25组数据点。

然后,调用函数leastSquareMethod计算出系数a和b的值,并将结果输出到控制台上。


总结

根据数学公式翻译成C语言, 简单的公式还是不太难的, 需要注意的是精度, 以及是否可能产生溢出, 通常来讲, double足够了.


点击 快速C语言入门


你可能感兴趣的:(c语言,最小二乘法)