1、梯度下降-矩阵形式

上篇文章介绍了一元线性回归,包括Python实现和sklearn实现的实例、对比,以及一些问题点,详情可以看这里:

链接: 手写算法-Python代码实现一元线性回归

里面封装的one_variable_linear()类只适用于一元线性回归,

本篇文章修改代码,推广至多元线性回归,并介绍2种更简洁的方法。

先给大家复习一下矩阵的基本知识:

转置矩阵:

损失函数可表示为:

可以求得:矩阵形式下,偏导的表达式是:

下面附上我的推导证明过程(刚写的):

有了上述表达式,我们修改上次的代码如下:

class linear(): def __init__(self): pass #梯度下降法迭代训练模型参数,x为特征数据,y为标签数据,a为学习率,epochs为迭代次数 def fit(self,x,y,a,epochs): #计算总数据量 m=x.shape[0] #给x添加偏置项 X = np.concatenate((np.ones((m,1)),x),axis=1) #计算总特征数 n = X.shape[1] #初始化W的值,要变成矩阵形式 W=np.mat(np.ones((n,1))) #X转为矩阵形式 xMat = np.mat(X) #y转为矩阵形式,这步非常重要,且要是m x 1的维度格式 yMat =np.mat(y.reshape(-1,1)) #循环epochs次 for i in range(epochs): W=W-a*xMat.T*(xMat*W-yMat) return W def predict(self,x,w): #这里的x也要加偏置,训练时x是什么维度的数据,预测也应该保持一样 return np.dot(x,w)1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

依然用上次的测试数据集,2个代码比较如下:

import numpy as np

import pandas as pd

from sklearn import datasets #sklearn生成数据集都在这里

from matplotlib import pyplot as plt

#生成一个特征的回归数据集

x,y=datasets.make_regression(n_features=1,noise=15,random_state=2020)

plt.scatter(x,y)

plt.show() class one_variable_linear(): #初始化参数,k为斜率,b为截距,a为学习率,n为迭代次数 def __init__(self,k,b,a,n): self.k =k self.b=b self.a=a self.n = n #梯度下降法迭代训练模型参数 def fit(self,x,y): #计算总数据量 m=len(x) #循环n次 for i in range(self.n): b_grad=0 k_grad=0 #计算梯度的总和再求平均 for j in range(m): b_grad += (1/m)*((self.k*x[j]+self.b)-y[j]) k_grad += (1/m)*((self.k*x[j]+self.b)-y[j])*x[j] #更新k,b self.b=self.b-(self.a*b_grad) self.k=self.k-(self.a*k_grad) #每迭代10次,就输出一次图像 if i%10==0: print('迭代{0}'.format(i)+'次') plt.plot(x,y,'b.') plt.plot(x,self.k*x+self.b,'r') plt.show() self.params= {'k':self.k,'b':self.b} #输出系数 return self.params #预测函数 def predict(self,x): y_pred =self.k * x + self.b return y_pred

lr=one_variable_linear(k=1,b=1,a=0.1,n=60)

lr.fit(x,y)1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

旧代码得到的参数如上,

新代码得到的参数如下:

model = linear()

w = model.fit(x,y,a=0.1,epochs=50)

print(w)1

2

3

我的天,这是什么鬼,怎么和上面的差的这么多(其实是我故意的),明显这个是不正确的,模型完全没有收敛,问题在哪里?

我们细想一下,正常的梯度下降法,前面是带m的,而矩阵形式,我们直接约掉了m,相当于学习率就被放大了m倍,所以这里学习率a应该设置为a/m=0.001,这样a就相等了,迭代次数也相等,冥冥中感觉这次的系数应该是一样的才对。再跑一下代码:

w = model.fit(x,y,a=0.001,epochs=50)

print(w)1

2

3

哈哈,完全一样,破案了,这里也解释了,之前说的,为什么损失函数前面1/2m这个值,其实对模型的参数没有影响,

但是你的学习率要选择得对,不能可能无法收敛。

现在这个类就是Python线性回归代码的一般式了,设置合理的学习率和迭代次数,就会得到不错的结果。

2、标准方程法

下面来介绍第二种方法,标准方程法。

有了前面的铺垫,这里就很容易理解了,损失函数:

因为这是一个凸函数,因此一定有极小值。根据最小二乘法的原理,我们要对这个损失函数对θ向量求导取0。结果如下式:

这个推导过程中也可以看到,1/2m对最终的系数没有影响,可以直接被约掉。

编写标准方程法代码如下:

class normal(): def __init__(self): pass def fit(self,x,y): m=x.shape[0] X = np.concatenate((np.ones((m,1)),x),axis=1) xMat=np.mat(X) yMat =np.mat(y.reshape(-1,1)) xTx=xMat.T*xMat #xTx.I为xTx的逆矩阵 ws=xTx.I*xMat.T*yMat return ws model =normal()

model.fit(x,y)1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

求出来的参数为:

这里要注意:XTX的逆矩阵不是什么时候都可以求得出来的,以下情况求不到XTX的逆矩阵:

1、特征数据高度线性相关;

2、n >>m,即特征数量大于样本数量,此时为非满秩矩阵;

sklearn实现对比标准方程法

from sklearn.linear_model import LinearRegression

LR=LinearRegression()

LR.fit(x,y)

LR.intercept_,LR.coef_1

2

3

4

和编写的标准方程法得到的参数一模一样,这里回答了之前说过为什么梯度下降法得到的参数和sklearn里面得到的参数不一样的问题,也说明了sklearn中封装的是标准方程法,毕竟真的简单!

下篇介绍非线性回归,当数据表现为非线性时,该怎么处理。

文章来源: blog.csdn.net,作者:Dream-YH,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_44700798/article/details/110452229

多元线性回归算法python实现_手写算法-Python代码推广多元线性回归相关推荐

  1. python实现tomasulo算法_手写算法-python代码实现KNN

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 原理解析 KNN-全称K-Nearest Neighbor,最近邻算法,可以做分类任务,也可以做回归 ...

  2. 扫描线填充算法代码_手写算法并记住它:计数排序

    对于经典算法,你是否也遇到这样的情形:学时觉得很清楚,可过阵子就忘了? 本系列文章就尝试解决这个问题. 研读那些排序算法,细品它们的名字,其实都很贴切. 比如计数排序,所谓"计数" ...

  3. python文件调用python文件_自己写的python文件如何相互调用

    自己写的python文件如何相互调用?Python中的模块库十分常用,对于常用的模块可以自己动手自定义,但是如何进行调用呢? 模块相互调用 同级目录调用时的两种方法import module prin ...

  4. python 立体匹配_手写双目立体匹配 SGM 算法(下)

    上节的内容主要对 SGM 算法的匹配代价体 (Cost Volume) 进行了详细介绍,发现如果只寻找逐个像素匹配代价的最优解会使得视差图对噪声特别敏感.因此在能量方程中考虑使用该点像素的邻域视差数据 ...

  5. python识别数字程序_python实现识别手写数字 python图像识别算法

    写在前面 这一段的内容可以说是最难的一部分之一了,因为是识别图像,所以涉及到的算法会相比之前的来说比较困难,所以我尽量会讲得清楚一点. 而且因为在编写的过程中,把前面的一些逻辑也修改了一些,将其变得更 ...

  6. python机器学习手写算法系列——线性回归

    本系列另一篇文章<决策树> https://blog.csdn.net/juwikuang/article/details/89333344 本文源代码: https://github.c ...

  7. 手写算法-python代码实现Ridge(L2正则项)回归

    手写算法-python代码实现Ridge回归 Ridge简介 Ridge回归分析与python代码实现 方法一:梯度下降法求解Ridge回归参数 方法二:标准方程法实现Ridge回归 调用sklear ...

  8. python机器学习手写算法系列——逻辑回归

    从机器学习到逻辑回归 今天,我们只关注机器学习到线性回归这条线上的概念.别的以后再说.为了让大家听懂,我这次也不查维基百科了,直接按照自己的理解用大白话说,可能不是很严谨. 机器学习就是机器可以自己学 ...

  9. python机器学习手写算法系列——kmeans聚类

    从机器学习到kmeans 聚类是一种非监督学习,他和监督学习里的分类有相似之处,两者都是把样本分布到不同的组里去.区别在于,分类分析是有标签的,聚类是没有标签的.或者说,分类是有y的,聚类是没有y的, ...

最新文章

  1. 红帽linux终端快捷键,二、回忆redhat各种基本命令
  2. python中in的底层实现_python中print和input的底层实现
  3. [导入]防止你的日志页被人iframe
  4. async-await用法
  5. 【实战分享】漫谈 gRPC的选型
  6. 蚂蚁链发布新一代网络平台「FAIR」 区块链进入隐私计算原生时代
  7. SpringBoot 精通系列-构建一个RESTful Web 服务
  8. 基于zookeeper实现配置集中管理【转】
  9. vue添加网址连接需要强制数据绑定(a标签里面添加网址)
  10. Centos7下yum安装GlusterFS方法
  11. Easyui常用按钮图标汇总
  12. 虚拟机Centos系统安装
  13. Blazor Day in China来喽,还不来赶紧报名参与
  14. vivo计算机的隐藏功能教程,Vivo手机的5个隐藏功能,真的很实用,一定要打开
  15. windows下Python2.7 的 pyOpenGL模块安装
  16. oracle04052,案例学习Oracle错误:ORA-04052
  17. 淘宝天猫各平台APP端页面详情api接口调用
  18. 离散时间信号和系统的时域分析
  19. 北极熊扫描器4.0发布,无需过多介绍的国产安全工具
  20. 前端还在切图?学完这些css,再也不用切图了!

热门文章

  1. boost::lockfree::queue用法的测试程序
  2. boost::geometry::bg::model::multi_linestring用法的测试程序
  3. Boost:gzifstream和gzofstream的测试程序
  4. ITK:关闭二进制图像
  5. ITK:从图像区域中随机选择像素
  6. VTK:Medical之GenerateCubesFromLabels
  7. VTK:InfoVis之PassThrough
  8. VTK:图片之ImageMapper
  9. VTK:图片之Flip
  10. OpenCV多机校准Multi-camera Calibration