今天我们用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 <stdio.h>
#include <stddef.h>
#include <malloc.h>
#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) {g_learning_rate = learning_rate;g_max_iter = max_iter;
//    g_w = gaussrand();
//    g_b = gaussrand();g_X_Len = X_Len;loss_arr_pt = malloc((size_t) max_iter);g_out_Y_pt = malloc((size_t) X_Len);y_pred_pt = malloc((size_t) X_Len);
}void fit(double *train_x, double *train_y) {X_pt = train_x;Y_pt = train_y;for (int i = 0; i < g_max_iter; ++i) {printf("step %d: ", i);_train_step();loss(NULL, NULL);loss_arr_pt[i] = loss_val[0];}
}double *_f(const double *train_x, double w, double b) {for (int i = 0; i < g_X_Len; i++) {//y = w * x + bg_out_Y_pt[i] = train_x[i] * w + b;}return g_out_Y_pt;
}//预测
double *predict(double *train_x) {if (train_x == NULL) {train_x = X_pt;}y_pred_pt = _f(train_x, g_w, g_b);return y_pred_pt;
}//计算损失
double loss(const double *y_true, const double *y_pred) {if (y_true == NULL || y_pred == NULL) {y_true = Y_pt;y_pred = predict(X_pt);}double loss_total = 0;for (int i = 0; i < g_X_Len; i++) {loss_total += (y_true[i] - y_pred[i]) * (y_true[i] - y_pred[i]);}loss_val[0] = loss_total / g_X_Len;return loss_val[0];
}//求梯度
void _calc_gradient() {double d_w_total = 0;double d_b_total = 0;for (int i = 0; i < g_X_Len; i++) {//迭代计算梯度d_w_total += ((X_pt[i] * g_w + g_b - Y_pt[i]) * X_pt[i]);d_b_total += (X_pt[i] * g_w + g_b - Y_pt[i]);}d_w = d_w_total / g_X_Len;d_b = d_b_total / g_X_Len;
}//更新 W 和 b
void _train_step() {_calc_gradient();//更新 W和bg_w = g_w - g_learning_rate * d_w;g_b = g_b - g_learning_rate * d_b;//输出时时 W 和b 以及损失printf(" g_w = %f,", g_w);printf("g_b = %f,", g_b);printf(" loss = %f\n", loss_val[0]);}

main.c


#include "utils/util.h"#include "src/MultipleLinearRegression.h"
#include "src/LinerRegression.h"int main() {//指定学习率double learning_rate = 0.01;//指定梯度下降计算次数int iteration_count = 2000;//生成输入变量的参数k、b; y = kx + bdouble k = 20.0;double b = 15;//训练数据大小int data_size = 100;int train_size = 70;int test_size = 30;double temp_rand[data_size];double X_data[data_size];double Y_data[data_size];double train_X[train_size];double train_Y[train_size];double test_X[test_size];double test_Y[test_size];//随机获取 输入变量XgetRand(X_data, data_size);for (int i = 0; i < data_size; ++i) {getRand(temp_rand, data_size);Y_data[i] = k * X_data[i] + b + temp_rand[i] / 10;}for (int j = 0; j < data_size; ++j) {if (j < train_size) {train_X[j] = X_data[j];train_Y[j] = Y_data[j];} else {test_X[j - train_size] = X_data[j];test_Y[j - train_size] = Y_data[j];}}set_config(learning_rate, iteration_count, train_size);fit(train_X, train_Y);

其中用到生成随机输入变量方法如下:

int* getRand(double *a,int len){int i;srand(time(NULL));//设置当前时间为种子for (i = 0; i < len; ++i){a[i] = rand()%10+1;//产生1~10的随机数}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语言实现一个简单的一元线性回归算法相关推荐

  1. 用C语言实现一个简单的计算器代码

    #include <stdio.h> #include <math.h> #include <stdlib.h> //预处理指令 int main(void) {d ...

  2. matlab求解一元四次函数,excel数据函数参数是四个吗|求一个简单的一元四次函数的最大值...

    求四次函数的最值 先求导,令导数等于0,求出x的值,判断单调性,将x代入原函数 4次幂的一元函数怎么计算 解析: (1) 四次方程,有通用求根公式. A 此公式复杂,实际使用较麻烦 B 其推导过程中可 ...

  3. 使用html 语言建立一个简单的网页,如何用记事本建立简单的网页(1).doc

    第九章 网页制作 实验一 用记事本建立简单的HTML文件 [实验目的] 学会用HTML语言建立一个简单的网页. [实验内容] 建立一个网页,布局自定,包括自我介绍.图片.自己的电子信箱地址等,要求在标 ...

  4. c语言编写一个简单的答题系统

    利用c语言编写一个简单的答题系统. 思路是先设计好题目和答案,再输入自己的答案,利用输入的答案与正确答案对比,从而得出你回答的对错. (一)捆绑题目和答案 我们可以利用结构体对一个题目捆绑上一个答案. ...

  5. c语言写一个简单的小游戏-推箱子

    在学习C语言之后,写了一个简单的小游戏来锻炼自己的代码以及C语言知识的掌握能力. 推箱子作为手机上最常见的简单游戏,其代码也相对简单,想法也比较简单,下面为其代码和运行图. /************ ...

  6. C语言编写一个简单的扫雷

    C语言编写一个简单的扫雷 # include <stdio.h> # include <stdlib.h> # include <math.h> # include ...

  7. 用c语言实现一个简单的输入法联想功能

    用c语言实现一个简单的输入法联想功能 手机输入法的联想功能十分常见,通过c语言同样可以实现一个简单的输入法联想功能. 首先读取一个文字量比较大的文件,通过线性表对汉字间的关系进行加权存储,再记录到总体 ...

  8. 一个简单的c 游戏编程语言,编程达人 c语言写一个简单的小游戏-推箱子

    在学习C语言之后,写了一个简单的小游戏来锻炼自己的代码以及C语言知识的掌握能力. 推箱子作为手机上最常见的简单游戏,其代码也相对简单,想法也比较简单,下面为其代码和运行图. /************ ...

  9. 计量经济学-简单的一元线性回归模型之一

    一元回归模型 回归分析和相关分析之间的差别 相关分析研究的是变量之间的线性相关性,而回归分析要研究的是解释变量和被解释变量之间的平均关系.相关分析中,变量都是随机变量:而回归分析中,解释变量是确定的, ...

最新文章

  1. python删除重复文字_python如何删除文件中重复的字段
  2. VBA——Msgbox
  3. IT工作者平日要做好自我调节
  4. World Wind Java开发之十——AnalyticSurface栅格渲染(转)
  5. 项目Beta冲刺(团队)总结
  6. 网络游戏植入营销案例
  7. 客户服务与工单管理系统—工单管理
  8. 【Try to Hack】masscan
  9. CODESYS Softmotion(一)功能介绍
  10. 华为CANN训练营笔记——应用开发全流程 [5](with 代码版)
  11. IIP3/IMD/IM3/P1dB
  12. 鸿蒙负责人王成录被曝已离职:华为技术元老,1998年哈工大博士毕业后加入
  13. 【C语言】字符个数统计 笔试常见题型
  14. 【哲理】24部经电影的24句话和24个哲理
  15. 口嫌体正直,“苹果”们纷纷下场造车
  16. 【UEditor】百度UE富文本自定义按钮添加文本
  17. 同济七版高等数学 上册 复习指导、公式推理简易过程、常用结论归纳
  18. MarkDown API
  19. 面向ad-hoc查询的实时SQL分析系统
  20. 统计网站访问量(自己开发)

热门文章

  1. 零信任网络ZTNA及SDP概念理解
  2. 家用计算机ip地址为什么类型,计算机IP地址怎么分类
  3. 一IT公司hr对软件外包感受(转)
  4. 服务器虚拟化太金苹果效果好,《我的世界》金苹果更新速度太快,如今附魔金苹果“可遇不可求”...
  5. matlab 1g等于多少byte,1G大还是1GB大???它们和MB,KB,字节又怎么换算??
  6. 如果圆桌骑士有特殊情况(Knights of the Round Table)
  7. LintCode 两个数组的交集
  8. 骆昊python100天百度网盘_GitHub - yiailake/Python-100-Days: Python - 100天从新手到大师
  9. 一个几乎对英语零基础的人,该如何有效,且高效的学习英语?
  10. 知晓云深坑:数据修改返回401解决办法