用C語言實現最小二乘法演算法
阿新 • • 發佈:2018-11-15
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
用C語言實現最小二乘法演算法
本文部落格連結:http://blog.csdn.net/jdh99,作者:jdh,轉載請註明.
環境:
主機:WIN8
開發環境:MINGW
說明:
參考維基百科最小二乘法資料:
測試文中戰列艦例子:用戰列艦的長度預測寬度
簡單線性模型 y = b0 + b1t 的例子[編輯]
隨機選定10艘戰艦,並分析它們的長度與寬度,尋找它們長度與寬度之間的關係。由下面的描點圖可以直觀地看出,一艘戰艦的長度(t)與寬度(y)基本呈線性關係。散點圖如下:
以下圖表列出了各戰艦的資料,隨後步驟是採用最小二乘法確定兩變數間的線性關係。
編號 | 長度 (m) | 寬度 (m) | ti - t | yi - y | |||
---|---|---|---|---|---|---|---|
i | ti | yi | ti* | yi* | ti*yi* | ti*ti* | yi*yi* |
1 | 208 | 21.6 | 40.2 | 3.19 | 128.238 | 1616.04 | 10.1761 |
2 | 152 | 15.5 | -15.8 | -2.91 | 45.978 | 249.64 | 8.4681 |
3 | 113 | 10.4 | -54.8 | -8.01 | 438.948 | 3003.04 | 64.1601 |
4 | 227 | 31.0 | 59.2 | 12.59 | 745.328 | 3504.64 | 158.5081 |
5 | 137 | 13.0 | -30.8 | -5.41 | 166.628 | 948.64 | 29.2681 |
6 | 238 | 32.4 | 70.2 | 13.99 | 982.098 | 4928.04 | 195.7201 |
7 | 178 | 19.0 | 10.2 | 0.59 | 6.018 | 104.04 | 0.3481 |
8 | 104 | 10.4 | -63.8 | -8.01 | 511.038 | 4070.44 | 64.1601 |
9 | 191 | 19.0 | 23.2 | 0.59 | 13.688 | 538.24 | 0.3481 |
10 | 130 | 11.8 | -37.8 | -6.61 | 249.858 | 1428.84 | 43.6921 |
總和(Σ) | 1678 | 184.1 | 0.0 | 0.00 | 3287.820 | 20391.60 | 574.8490 |
仿照上面給出的例子
並得到相應的.
然後確定b1
可以看出,戰艦的長度每變化1m,相對應的寬度便要變化16cm。並由下式得到常數項b0:
在這裡隨機理論不加闡述。可以看出點的擬合非常好,長度和寬度的相關性大約為96.03%。 利用Matlab得到擬合直
線:
演算法結果:
mean_x = 167.800003,mean_y = 18.410000
a = -8.645075,b = 0.161234
300m長度的戰艦預測寬度為為39.725140米
原始碼:
#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;}