梯度下降法的C语言实现
2015-12-29 11:37
323 查看
<span style="font-family: Arial, Helvetica, sans-serif;">int main()</span>
{ //double matrix[4][3] = {{4,3,1},{6,8,1},{18,26,1},{55,77,1}}; //double result[4] = {7,10,55,120}; double matrix[4][3]={{1,4,1},{2,5,1},{5,1,1},{4,2,1}}; double result[4]={19,26,19,20}; double error_sum = 0; double theta[3] = {0,0,0}; //theta的初值全部设为,从零开始 int i,temp; for(temp=1;temp<=1000;temp++) //这里我没有用之前别人博客上面的参考,他的代码实际上不是run了一千遍,而是run了1000/len(data)遍。
{ //temp用来表示迭代次数,然后i表示样本的数量,每次更新temp,都要迭代一轮i int k,j; for(i = 0;i<3;i++) //因为训练数据是4个 所以i从0到3 { double h = 0; for(k = 0;k <3;k++) //k负责迭代的是x的维数,也就是theta的维数,之前说过了,二位数据要设置三维的维度 { h = h + theta[k]*matrix[i][k]; //用累加和求预测函数h(x)并且记住,每次求完h算完残差之后,都要把h重新归零 } error_sum = h - result[i]; for(k = 0;k<3;k++) { theta[k] = theta[k] - 0.04*error_sum*matrix[i][k]; //梯度下降的精髓,更新k个theta值,并且减去导数方向乘以x乘以学习率alpha } } printf("%lf %lf %lf ",theta[0],theta[1],theta[2]); } }
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">之前我设计了一个二维数组的梯度下降,发现跑原blog上面的数据,可以跑出结果,但是,问题在于,跑我自己的数据的时候,每次都会变成负无穷。</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">我心想不应该啊,都是二元线性回归,而且基本都是一个方向的,怎么可能得到负无穷</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">后来我想了下,想明白了,我这里没有考虑常数项【也就是theta 0】 结果就是没有常数项,每个theta都会互相牵制地变大变小,也就失去了梯度下降的意义。</span>
而原代码,选择的数据恰好没有常数项,所以可以运行,囧。。
大家一定要以此为戒,如果你的数据是2维的,那么你要创建一个三维的数组【矩阵】,然后在最前面(或最后面)令其为 1
最后的经验。当从两维变成三维之后,迭代收敛的次数明显变慢了,以前100次迭代就能收敛到4.0和3.0 现在迭代1000次才只能变为4.2和3.89
因为我设置的学习率是0.01,当我“武断”地把它增大到0.02时,收敛速度快了一些。增大到0.04时,又快了一些。可还是不够好
所以邹博说得对,得继续添加对alpha的自适应。才能收敛得更快一点。
多说两句,我最初理解的梯度下降是“在人类无法求得导函数的解析式的时候,不得已而去转投梯度下降法去一步步猜着求解”实际上,并不是。
而是说机器是死的,它无法像人类一样,通过求导函数,然后解导函数为零的方程,得到极值点,然后去代入。【貌似写程序也可以?待试试】
因此,只能人类手工计算出它的导数(的方向),然后让它自己沿着导数方向一步一步走,当走到某一点时,导数为零了【也就是极值点了】,每次走的步伐大小要乘以这个导数呀,既然为零了,那步伐也为零了,也就是所谓的“收敛”了
而现在,用在线性回归里,我们人类可以计算的导函数就是(h(x)-y)*xj 所以,每次乘以这个就好了
参考:
http://blog.csdn.net/achaoluo007/article/details/40622319
很奇怪的一点!!只要我设置theta的数组为double theta[2] 就会显示乱码!!不知道为什么!但是输入theta【3】就可以正确输入!!可是我明明存三个数啊 theta【2】 就可以呀!(错!theta【2】里面只能存两个数!!!0,1,!!!切记!!
上面是批梯度下降的算法,如果改成随机梯度下降呢?
批梯度下降 是把 所有样本 从1到j全部run一遍(对应着那个迭代次数下面的for循环)。而随机梯度下降法,就不用run所有的j来更新一个theta了,而是【随机地】取一个j,(可以用取余,可以用随机数),然后直接用这个j更新一次theta,
分析:假设有40000个数据,迭代1000次 那么批梯度下降运行次数:40000*1000 随机梯度下降运行次数:4*1000 下降明显
相关文章推荐
- PC-Lint与CC++代码质量
- 在Visual Studio 2013 中使用C++单元测试
- C/C++语言的存储类型
- C++指针比较的问题
- 微软应该开源的15款产品,记事本、VC++ 在列
- Effective C++:条款25:考虑写出一个不抛异常的swap函数
- C/C++异常捕获try{}catch(...) // __try{ //...}__except(EXCEPTION_EXECUTE_HANDLER){ //...}
- eclipse中编写运行c/c++
- c/c++中动态内存分配处理字符串的细节问题
- 获取目录下所有文件(C/C++)
- CTBCAFBridge hpp 和 cpp 文件分析
- c++下new与delete基础用法
- ROS学习笔记(五)::RVIZ:Markers::Points and Lines (C++)
- c++ 往txt中写入数据
- c++调用 c#的dll
- C语言中宏定义(#define)时do{}while(0)的价值(转)
- ROS学习笔记(四)::RVIZ(一):Markers:sending Basic Shapes (C++)
- C++回调机制实现(转)
- HDU5600:N bulbs
- std::thread vs CreateThread