用C语言实现最小二乘法算法
本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.
公式参考:https://www.cnblogs.com/paiandlu/p/7843236.html
基本思想
求出这样一些未知参数使得样本点和拟合线的总误差(距离)最小
最直观的感受如下图(图引用自知乎某作者)
而这个误差(距离)可以直接相减,但是直接相减会有正有负,相互抵消了,所以就用差的平方
推导过程
1 写出拟合方程
𝑦=𝑎+𝑏𝑥y=a+bx
(3287.82)/(20391.6)
= 0.16123403754487141764
截距
拟合方程
y=0.161234x-8.6394
#include <stdio.h> /********************************************************************* * 宏定义 **********************************************************************/ /********************************************************************* * 数据fifo长度 **********************************************************************/ #define LEN 100 /********************************************************************* * 数据结构 **********************************************************************/ /********************************************************************* * 数据单元 **********************************************************************/ struct _Data_Unit { float x; float y; }; /********************************************************************* * 数据fifo **********************************************************************/ struct _Data { struct _Data_Unit data[LEN]; int len; }; /********************************************************************* * 全局变量 **********************************************************************/ /********************************************************************* * 数据fifo **********************************************************************/ struct _Data Data = { .len = 0 }; /********************************************************************* * 函数 **********************************************************************/ /********************************************************************* * 压入数据 *参数:x:测量数据x * y:测量数据y **********************************************************************/ void push(float x, float y) { int i = 0; if (Data.len < LEN) { Data.data[Data.len].x = x; Data.data[Data.len++].y = y; return; } //数据移动,去掉最后一个数据 for (i = 0; i < LEN - 1; i++) { Data.data[i].x = Data.data[i + 1].x; Data.data[i].y = Data.data[i + 1].y; } Data.data[LEN].x = x; Data.data[LEN].y = y; Data.len = LEN; } /********************************************************************* * 计算估值 *拟合曲线y = a * x + b *参数:x:需要估值的数的x值 *返回:估值y **********************************************************************/ float calc(float x) { int i = 0; float mean_x = 0; float mean_y = 0; float num1 = 0; float num2 = 0; float a = 0; float b = 0; //求t,y的均值 for (i = 0; i < Data.len; i++) { mean_x += Data.data[i].x; mean_y += Data.data[i].y; } mean_x /= Data.len; mean_y /= Data.len; printf("mean_x = %f,mean_y = %f\n", mean_x, mean_y); for (i = 0; i < Data.len; i++) { num1 += (Data.data[i].x - mean_x) * (Data.data[i].y - mean_y); num2 += (Data.data[i].x - mean_x) * (Data.data[i].x - mean_x); } b = num1 / num2; a = mean_y - b * mean_x; printf("a = %f,b = %f\n", a, b); return (a + b * x); } int main() { float length[10] = {208, 152, 113, 227, 137, 238, 178, 104, 191, 130}; float width[10] = {21.6, 15.5, 10.4, 31.0, 13.0, 32.4, 19.0, 10.4, 19.0, 11.8}; int i = 0; for (i = 0; i < 10; i++) { push(length[i], width[i]); } printf("300m长度的战舰预测宽度为为%f米\n", calc(300)); //getchar(); return 0; }
mean_x = 167.800003,mean_y = 18.410000
a = -8.645075,b = 0.161234
计算器计算:
0.161234*300-8.6394
= 39.7308