1. 程式人生 > >用C語言實現最小二乘法演算法

用C語言實現最小二乘法演算法

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!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


仿照上面給出的例子

\bar t = \frac {\sum_{i=1}^n t_i}{n} = \frac {1678}{10} = 167{.}8 並得到相應的\bar y = 18{.}41.

然後確定b1

b_1 = \frac{\sum_{i=1}^n (t_i- \bar {t})(y_i - \bar y)}{\sum_{i=1}^n (t_i- \bar t)^2}
= \frac{3287{.}820} {20391{.}60} = 0{.}1612 \;,

可以看出,戰艦的長度每變化1m,相對應的寬度便要變化16cm。並由下式得到常數項b0

b_0 = \bar y - b_1 \bar t = 18{.}41 - 0{.}1612 \cdot 167{.}8 = -8{.}6394 \;,

在這裡隨機理論不加闡述。可以看出點的擬合非常好,長度寬度的相關性大約為96.03%。 利用Matlab得到擬合直

線:

最小二乘法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 = 0float mean_x = 0float mean_y = 0float num1 = 0float num2 = 0float a = 0float 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;}

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述