今天我們用c語言實現乙個簡單的線性回歸演算法;在**前面我們在回顧一下線性回歸。
線性回歸是回歸問題中的一種,線性回歸假設目標值與特徵是線性相關的,即滿足乙個多元一次方程式。通過構建損失函式,來求解損失函式最小時的引數w和b。通常表示式可以表示如下:
其中 y 為**值,自變數x和因變數y是已知的,我們要想實現的是,當乙個新增的x出現時,我們要**y的值。因此我們構建這個函式關係,是通過已知的資料求解函式模型中位置的w和b這兩個引數。
我們用均方誤差為損失函式即:
將函式帶入即為:
我們現在的任務就是求解最小化 l 時的w 和b,即將核心目標優化為
此處我們用梯度下降法進行求解
為了求偏導數,當只有乙個樣本時,即:
我們這裡就簡單的處理為求解
理解了最小誤差的求解原理我們就開始上**了。
linerregression.h
#ifndef linerregression_linerregression_h
#define linerregression_linerregression_h
//初始化函式
void set_config(double learning_rate,long int max_iter,int x_len);
//訓練
void fit(double *train_x,double *train_y);
//計算
double* _f(const double *train_x,double w,double b);
//**
double* predict(double *train_x);
//損失
double loss(const double *y_true,const double *y_pred);
//求梯度
void _calc_gradient();
//單步更新
void _train_step();
#endif
linerregression.c
#include #include #include #include "linerregression.h"
//設定固定學習率
double g_learning_rate = 0.01;
//設定梯度更新次數
long int g_max_iter = 100;
//設定初始化 w
double g_w = 5;
//設定初始化 b
double g_b = 5;
//定義儲存損失的指標
double *loss_arr_pt;
//定義儲存時時計算y的指標
double *g_out_y_pt;
//定義儲存時時**y的指標
double *y_pred_pt;
//輸入 x
double *x_pt;
//輸入 y
double *y_pt;
//訓練資料長度
int g_x_len;
//更新 梯度
double d_w;
double d_b;
double loss_val[1];
void set_config(double learning_rate, long int max_iter, int x_len)
void fit(double *train_x, double *train_y)
}double *_f(const double *train_x, double w, double b)
return g_out_y_pt;
}//**
double *predict(double *train_x)
y_pred_pt = _f(train_x, g_w, g_b);
return y_pred_pt;
}//計算損失
double loss(const double *y_true, const double *y_pred)
double loss_total = 0;
for (int i = 0; i < g_x_len; i++)
loss_val[0] = loss_total / g_x_len;
return loss_val[0];
}//求梯度
void _calc_gradient()
d_w = d_w_total / g_x_len;
d_b = d_b_total / g_x_len;
}//更新 w 和 b
void _train_step()
main.c
#include "utils/util.h"
#include "src/multiplelinearregression.h"
#include "src/linerregression.h"
int main()
for (int j = 0; j < data_size; ++j) else
}set_config(learning_rate, iteration_count, train_size);
fit(train_x, train_y);
其中用到生成隨機輸入變數方法如下:
int* getrand(double *a,int len)
return a;
}
可以看到在計算1000之後 w 和 b已經很接近我們初時設定的值了:
step 989: g_w = 20.235078,g_b = 14.003770, loss = 0.210872
step 990: g_w = 20.234798,g_b = 14.005839, loss = 0.209997
step 991: g_w = 20.234518,g_b = 14.007905, loss = 0.209125
step 992: g_w = 20.234238,g_b = 14.009966, loss = 0.208257
step 993: g_w = 20.233959,g_b = 14.012023, loss = 0.207393
step 994: g_w = 20.233681,g_b = 14.014076, loss = 0.206532
step 995: g_w = 20.233403,g_b = 14.016124, loss = 0.205674
step 996: g_w = 20.233126,g_b = 14.018169, loss = 0.204821
step 997: g_w = 20.232849,g_b = 14.020209, loss = 0.203970
step 998: g_w = 20.232573,g_b = 14.022244, loss = 0.203124
step 999: g_w = 20.232298,g_b = 14.024276, loss = 0.202281
至此我們簡單的一元線性回歸就這樣實現了。至於學習率更優雅的指定和學習停止條件我們後面再討論。 用C語言實現簡單的多元線性回歸演算法 一
簡單的一元線性回歸演算法已經在這裡 c語言簡單的一元線性回歸演算法 並且也簡單闡述了梯度求解推導過程。今天我們再呈上多元線性回歸演算法梯度下降的c語言實現,中已經加入了相應的注釋。如下 multiplelinearregression.h ifndef multiplelinearregressio...
用C語言實現乙個簡單的Linux殼層(Shell)
期末考試考完,進入聖誕假期,終於騰出手寫這篇文章了。這是我們os課的第乙份作業,要求實現乙個簡單的linux shell,用c寫出乙個類似terminal的東西。大致要求 可以迴圈接收command,根據內容實現相應動作,實現幾個常見command即可。作業目的是熟悉幾個知識點 linux的pare...
c語言 實現乙個棧
include include include include 入棧出站操作 typedef struct nodenode,pnode typedef struct stack pstack,stack void init pstack void push pstack,int bool isem...