C言語で簡単な多元線形回帰アルゴリズムを実現する(一)
5766 ワード
簡単な一元線形回帰アルゴリズムはここで「C言語の簡単な一元線形回帰アルゴリズム」であり,勾配解の導出過程も簡単に述べた.
今日,多重線形回帰アルゴリズムの勾配が低下したC言語実装を示し,コードには対応する注釈が加わった.次のようになります.
MultipleLinearRegression.h
MultipleLinearRegression.h
main.c
さらに10000回訓練すると損失が小さくなり、各パラメータも予め設定したパラメータに対応していることがわかります.
これはC言語の単純な実現にすぎず,学習率も固定値,訓練回数も固定値とした.もし皆さんが他の良い実現方法があれば、伝言の推薦を歓迎します.また、長い間C言語で開発されていないため、文法の不完全さがあるに違いない.もっと良いアドバイスやその他の疑問があれば、交流を歓迎します.弟はお待ちしています.
今日,多重線形回帰アルゴリズムの勾配が低下したC言語実装を示し,コードには対応する注釈が加わった.次のようになります.
MultipleLinearRegression.h
#ifndef MULTIPLELINEARREGRESSION_MULTIPLELINEARREGRESSION_H
#define MULTIPLELINEARREGRESSION_MULTIPLELINEARREGRESSION_H
// 10
#define SAMPLE_COUNT 10
// 6
#define PARAMETER_COUNT 6
void init(double learning_rate, long int X_Len,long int X_arg_count,int channel);
void fit(double train_x[SAMPLE_COUNT][PARAMETER_COUNT],double train_y[PARAMETER_COUNT],double temp[PARAMETER_COUNT],double theta[PARAMETER_COUNT]);
double _f(const double train_x[PARAMETER_COUNT],double theta[PARAMETER_COUNT]);
double* predict(double train_x[SAMPLE_COUNT][PARAMETER_COUNT],double theta[PARAMETER_COUNT]);
double loss(double train_x[SAMPLE_COUNT][PARAMETER_COUNT],double train_y[PARAMETER_COUNT],
double temp[PARAMETER_COUNT],double *loss_val);
void calc_gradient(double train_x[SAMPLE_COUNT][PARAMETER_COUNT],double train_y[PARAMETER_COUNT],double *temp,double *theta);
void train_step(double temp[PARAMETER_COUNT],double theta[PARAMETER_COUNT]);
#endif //MULTIPLELINEARREGRESSION_MULTIPLELINEARREGRESSION_H
MultipleLinearRegression.h
#include "MultipleLinearRegression.h"
#include
#include
//int type_count = 5;
int g_X_Len = 10;
double g_learning_rate = 0.01;
int g_X_arg_count = 5;
int g_channel = 1;
double g_out_Y_pt = 0;
//
double *y_pred_pt = 0;
//
double loss_val[1] = {1.0};
/*
* learning_rate
*
* X_Len
*
* X_arg_count
*
* channel
* */
void init(double learning_rate, long int X_Len,long int X_arg_count,int channel){
g_learning_rate = learning_rate;
g_X_Len = X_Len;
g_X_arg_count = X_arg_count;
g_channel = channel;
y_pred_pt = malloc((size_t) X_Len);
}
void fit(double train_x[SAMPLE_COUNT][PARAMETER_COUNT],double train_y[PARAMETER_COUNT],
double temp[PARAMETER_COUNT],double theta[PARAMETER_COUNT]){
for (int i = 0; i < 10000; ++i) {
printf("step %d:
", i);
calc_gradient(train_x,train_y,temp,theta);
loss_val[0] = loss(train_x,train_y,theta,loss_val);
}
}
double _f(const double train_x[PARAMETER_COUNT],double theta[PARAMETER_COUNT]){
g_out_Y_pt = -1;
for (int i = 0; i < PARAMETER_COUNT; ++i) {
g_out_Y_pt += theta[i]*train_x[i];
}
return g_out_Y_pt;
}
//
double* predict(double train_x[SAMPLE_COUNT][PARAMETER_COUNT],double theta[PARAMETER_COUNT]){
for (int i = 0; i < SAMPLE_COUNT; ++i) {
y_pred_pt[i] = _f(train_x[i],theta);
}
return y_pred_pt;
}
//
double loss(double train_x[SAMPLE_COUNT][PARAMETER_COUNT],double train_y[PARAMETER_COUNT],
double theta[PARAMETER_COUNT],double *loss_val){
predict(train_x,theta);
loss_val[0] = -1;
for (int i = 0; i < SAMPLE_COUNT; i++) {
loss_val[0] += (train_y[i] - y_pred_pt[i]) * (train_y[i] - y_pred_pt[i]);
}
loss_val[0] = loss_val[0] / SAMPLE_COUNT;
printf(" loss_val = %f
", loss_val[0]);
return loss_val[0];
}
//
void calc_gradient(double train_x[SAMPLE_COUNT][PARAMETER_COUNT],double train_y[PARAMETER_COUNT],
double temp[PARAMETER_COUNT], double theta[PARAMETER_COUNT]) {
for (int i = 0; i < g_X_arg_count -1; i++) {
double sum = 0;
for (int j = 0; j < g_X_Len; j++) {
double hx = 0;
for (int k = 0; k < g_X_arg_count; k++) {
hx += theta[k] * train_x[j][k];
}
sum += (hx - train_y[j]) * train_x[j][i];
}
temp[i] = sum / g_X_Len * 0.01;
}
printf("
--------------------
");
train_step(temp, theta);
}
//
void train_step(double temp[PARAMETER_COUNT],double theta[PARAMETER_COUNT]) {
for (int i = 0; i < g_X_arg_count - 1; i++) {
theta[i] = theta[i] - temp[i];
printf(" theta[%d] = %f
",i, theta[i]);
}
}
main.c
//#include "src/LinerRegression.h"
#include "utils/util.h"
#include "src/MultipleLinearRegression.h"
int main() {
// 5 ; 1 b
// Y= 4*X1 + 9*X2 + 10*X3 + 2*X4 + 1*X5 + 6 ( )
double X_pt[10][6] = {{1, 7.41, 3.98, 8.34, 8.0, 0.95},
{1, 6.26, 5.12, 9.57, 0.3, 7.79},
{1, 1.52, 1.95, 4.01, 7.96, 2.19},
{1, 1.91, 8.58, 6.64, 2.99, 2.18},
{1, 2.2, 6.88, 0.88, 0.5, 9.74},
{1, 5.17, 0.14, 4.09, 9.0, 2.63},
{1, 9.13, 5.54, 6.36, 9.98, 5.27},
{1, 1.17, 4.67, 9.02, 5.14, 3.46},
{1, 3.97, 6.72, 6.12, 9.42, 1.43},
{1, 0.27, 3.16, 7.07, 0.28, 1.77}};
double Y_pt[10] = {171.81, 181.21, 87.84, 165.42, 96.26, 89.47, 181.21, 156.65, 163.83, 108.55};
// temp
double temp[6] = {1.0,1.0,1.0,1.0,1.0,1.0};
double theta[6] = {1.0,1.0,1.0,1.0,1.0,1.0};
//
init(0.01,10,5+1,1);
fit(X_pt,Y_pt,temp,theta);
return 0;
}
さらに10000回訓練すると損失が小さくなり、各パラメータも予め設定したパラメータに対応していることがわかります.
step 9999:
--------------------
theta[0] = 5.994281
theta[1] = 3.999957
theta[2] = 9.000404
theta[3] = 10.000375
theta[4] = 2.000242
loss_val = 0.900745
Process finished with exit code 0
これはC言語の単純な実現にすぎず,学習率も固定値,訓練回数も固定値とした.もし皆さんが他の良い実現方法があれば、伝言の推薦を歓迎します.また、長い間C言語で開発されていないため、文法の不完全さがあるに違いない.もっと良いアドバイスやその他の疑問があれば、交流を歓迎します.弟はお待ちしています.