监督学习中关于线性回归问题的系统讨论

前言

  本文将系统的介绍机器学习中监督学习的回归部分,系统的讲解如何利用回归理论知识来预测出一个分类的连续值。

  显然,与监督学习中的分类部分相比,它有很鲜明的特点:输出为连续值,而不仅仅是标称类型的分类结果。

基本线性回归解决方案 - 最小二乘法

  “给出一堆散点,求出其回归方程。" -> 对于这个问题,很多领域都碰到过,而其中最为经典普遍的做法通常是:

  1. 用式子表示出各个散点到回归线之间的距离之和:

  

  m 为散点数量,yi 为散点值,xi 为散点坐标,w 为回归系数向量。

  2. 对上式以向量 w 求导,求出导数值为 0 时的回归系数 (具体求导过程涉及到对向量求导的相关法则,略):

  

  这种方法就叫做最小二乘法。

最小二乘法的具体实现

  下面这个小程序从文本中读取散点,然后拟合出回归直线,并使用 matplotlib 展示出来 (注: 为了清楚直观,特征 0 没展示出来):

 1 #!/usr/bin/env python
 2 # -*- coding:UTF-8 -*-
 3
 4 ‘‘‘
 5 Created on 2015-01-04
 6
 7 @author: fangmeng
 8 ‘‘‘
 9
10 from numpy import *
11
12 def loadDataSet(fileName):
13     ‘载入测试数据‘
14
15     numFeat = len(open(fileName).readline().split(‘\t‘)) - 1
16     dataMat = []; labelMat = []
17     fr = open(fileName)
18     for line in fr.readlines():
19         lineArr =[]
20         curLine = line.strip().split(‘\t‘)
21         for i in range(numFeat):
22             lineArr.append(float(curLine[i]))
23         dataMat.append(lineArr)
24         labelMat.append(float(curLine[-1]))
25     return dataMat,labelMat
26
27 #===================================
28 # 输入:
29 #        xArr: 特征坐标矩阵
30 #        yArr: 特征值矩阵
31 # 输出:
32 #        w: 回归系数向量
33 #===================================
34 def standRegres(xArr,yArr):
35     ‘采用最小二乘法求拟合系数‘
36
37     xMat = mat(xArr);
38     yMat = mat(yArr).T
39     xTx = xMat.T*xMat
40     if linalg.det(xTx) == 0.0:
41         print "该矩阵无法求逆"
42         return
43     ws = xTx.I * (xMat.T*yMat)
44     return ws
45
46 def test():
47     ‘展示结果‘
48
49     # 采用最小二乘求出回归系数并预测出各特征点对应的特征值
50     xArr, yArr = loadDataSet(‘/home/fangmeng/ex0.txt‘)
51     ws = standRegres(xArr, yArr)
52     xMat = mat(xArr)
53     yMat = mat(yArr)
54     yHat = xMat * ws
55
56     import matplotlib.pyplot as plt
57
58     # 绘制所有样本点
59     fig = plt.figure()
60     ax = fig.add_subplot(111)
61     ax.scatter(xMat[:,1].flatten().A[0], yMat.T[:, 0].flatten().A[0])
62
63     # 绘制回归线
64     xCopy = xMat.copy()
65     xCopy.sort(0)
66     yHat = xCopy*ws
67     ax.plot(xCopy[:, 1], yHat)
68     plt.show()
69
70 if __name__ == ‘__main__‘:
71     test()

  测试结果:

  

  观察预测与真实的相关系数:

print corrcoef(yHat.T, yMat)

  测试结果:

  

  0.98+的相关系数,可见拟合的效果还是不错的。

局部加权线性回归

  基本的线性回归经常会碰到一些问题。

  比如由于线性回归本身导致的欠拟合问题。以最基本的一个特征的情况为例,如果散点图本身呈现一个非线性化的轮廓,而强行的将它拟合成一条直线:

  

  显然,两端的拟合是非常不科学的,偏离的很远。

  针对这个问题,局部加权线性回归应运而生。它能够得到类似下图这样更为科学的拟合线段:

  

  所谓局部,就是最大程度考虑待预测点附近的点,所谓加权,就是离待预测点越近,其参考系数(权重)就越大。

  因此,在原先的最小二乘法中加入一个用于衡量权重的对角矩阵W。这样,回归系数的求解式就变为:

  

  权重矩阵W又称为 "核",典型的高斯核的计算方法如下:

  

  下面是采用局部加权线性回归思想的回归系数求解函数:

 1 #===================================
 2 # 输入:
 3 #        testPoint: 测试点
 4 #        xArr: 特征坐标矩阵
 5 #        yArr: 特征值矩阵
 6 #        k: 高斯核权重衰减系数
 7 # 输出:
 8 #        testPoint * ws: 测试点集对应的结果
 9 #===================================
10 def lwlr(testPoint,xArr,yArr,k=1.0):
11     ‘对指定点进行局部加权线性回归‘
12
13     xMat = mat(xArr);
14     yMat = mat(yArr).T
15     m = shape(xMat)[0]
16
17     # 采用向量方式计算高斯核
18     weights = mat(eye((m)))
19     for j in range(m):
20         diffMat = testPoint - xMat[j,:]
21         weights[j,j] = exp(diffMat*diffMat.T/(-2.0*k**2))
22
23     xTx = xMat.T * (weights * xMat)
24     if linalg.det(xTx) == 0.0:
25         print "错误: 系数矩阵无法求逆"
26         return
27
28     ws = xTx.I * (xMat.T * (weights * yMat))
29     return testPoint * ws
30
31 #===================================
32 # 输入:
33 #        testArr: 测试点集
34 #        xArr: 特征坐标矩阵
35 #        yArr: 特征值矩阵
36 # 输出:
37 #        yHat: 测试点集对应的结果集
38 #===================================
39 def lwlrTest(testArr,xArr,yArr,k=1.0):
40     ‘对指定点集进行局部加权回归‘
41
42     m = shape(testArr)[0]
43     yHat = zeros(m)
44
45     # 求出所有测试点集的
46     for i in range(m):
47         yHat[i] = lwlr(testArr[i],xArr,yArr,k)
48     return yHat

  如下代码展示回归结果:

 1 def test():
 2     ‘展示结果‘
 3
 4     # 载入数据
 5     xArr, yArr = loadDataSet(‘/home/fangmeng/ex0.txt‘)
 6
 7     # 获取所有样本点的局部加权回归的预测值
 8     yHat = lwlrTest(xArr, xArr, yArr, 0.01)
 9
10     xMat = mat(xArr)
11     srtInd = xMat[:,1].argsort(0)
12     xSort = xMat[srtInd][:,0,:]
13     #print xMat[srtInd][:,0,:]
14
15     # 显示所有样本点和局部加权拟合线段
16     import matplotlib.pyplot as plt
17     fig = plt.figure()
18     ax = fig.add_subplot(111)
19     ax.plot(xSort[:,1], yHat[srtInd])
20     ax.scatter(xMat[:,1].flatten().A[0], mat(yArr).T.flatten().A[0], s=2, c=‘red‘)
21     plt.show()

  当k(衰减系数) = 1时,测试结果:

  

  k(衰减系数) = 0.003时,测试结果:

  

  k(衰减系数) = 0.01时,测试结果:

  

  观察可以发现,k = 1就是和基本线性回归一样了 - 欠拟合;而 k = 0.003 则是过拟合了;k = 0.01 刚好,是最优的选择。

岭回归

  假如碰到了这样的情况:散点个数小于特征数了。

  这种情况有啥问题呢 ---- (xTx)-1 必然会求解失败!解决办法可以采用岭回归技术。

  所谓岭回归,就是在回归系数求解式中的 xTx 之后加上 λI 使求逆部分可顺利求解,更改后的求解式如下:

  

  其中,I 是单位对角矩阵,看起来有点像山岭。这也是为什么这种回归方式叫做岭回归,哈哈!

  具体的实现代码本文就不具体给出了,但是有两个地方要特别注意一下:

  1. 需要对所有的数据进行标准化

  2. 根据不同的 λ 取到不同组的回归系数之后,还需要对不同组的权重进行择优。比较常用的有 lasso 方法(和岭回归的区别在于 w 和 λ 的约束关系)。

具体方案的制定

  提到了这么多种的回归方案,那么具体应该采用哪种好呢?

  首先,得根据问题的特性选择合适的方案。

  在同样适用的情况下,"偏差与方差折中" 是一个很好的选择经验。

  

  红点位置对应的方案便是最佳方案。

小结

  回归和分类一样,针对不同问题不同领域都有着不同算法。关键是要把握其整体思路,根据需要去进行选择。

  然而,本文所讲解的都是线性回归。线性回归始终有其弊端,因为很多实际问题本身是非线性的。

  即使是本文中介绍过的局部加权线性回归,想到每次测试都要拟合一次,也是挺蛋疼的。

  因此在下篇文章中,将会专门详细地介绍一种高级的非线性回归法 - 树回归。

 

时间: 2024-10-29 19:05:47

监督学习中关于线性回归问题的系统讨论的相关文章

如何在cocos2d-x中使用ECS(实体-组件-系统)架构方法开发一个游戏?

引言 在我的博客中,我曾经翻译了几篇关于ECS的文章.这些文章都是来自于Game Development网站.如果你对这个架构方式还不是很了解的话,欢迎阅读理解 组件-实体-系统和实现 组件-实体-系统. 我发现这个架构方式,是在浏览GameDev上的文章的时候了解到的.很久以前,就知道了有这么个架构方法,只是一直没有机会自己实践下.这一次,我就抽空,根据网上对ECS系统的讨论,采用了一种实现方法,来实现一个. 我很喜欢做游戏,所以同样的,还是用游戏实例来实践这个架构方法.我将会采用cocos2

在Hyper-V虚拟机中创建差异磁盘克隆系统

Hyper-V虚拟机差异磁盘克隆系统 1.  首先去掉模板的SID值,这里用2003来举例,在2003的安装盘中拷贝这个两个文件到桌面或者C盘 2.  执行其中的sysprep.exe文件,如图 等关机之后在把VHD磁盘拷贝到另外位置,这个拷贝的文件就是你差异磁盘的文件 3.  在Hyper-V服务器上面选择新建磁盘,在新建磁盘类型中选择差异 4.  在指定名称和位置这里写上你名称和位置 5.  给查差异磁盘指定父盘,父盘就是刚才关机之后拷贝的那个文件 然后选择下一步,点击完成,差异磁盘就算创建

5 个在 Linux 中管理文件类型和系统时间的有用命令

对于想学习 Linux 的初学者来说要适应使用命令行或者终端可能非常困难.由于终端比图形用户界面程序更能帮助用户控制 Linux 系统,我们必须习惯在终端中运行命令.因此为了有效记忆 Linux 不同的命令,你应该每天使用终端并明白怎样将命令和不同选项以及参数一同使用. 在 Linux 中管理文件类型和设置时间 请先查看我们 Linux 小技巧系列之前的文章: 5 个有趣的 Linux 命令行技巧 给新手的 10 个有用 Linux 命令行技巧 在这篇文章中,我们打算看看终端中 5 个和文件以及

docker中的容器互联-linking系统

docker中的容器互联-linking系统docker有一个linking 系统可以连接多个容器.它会创建一对父子关系,父容器可以看到所选择的子容器的信息.1)容器的命名系统linking系统依据容器的名称来执行.当我们创建容器的时候,系统会随机分配一个名字.当然我们也可以自己来命名容器,这样做有2个好处:• 当我们自己指定名称的时候,比较好记,比如一个web应用我们可以给它起名叫web• 当我们要连接其他容器时候,可以作为一个有用的参考点,比如连接web容器到db容器使用--name标记可以

WinCE平台的C#程序中调用MessageBeep发出一些系统自带的声音,而不用使用playsound

[DllImport("coredll.dll", EntryPoint = "MessageBeep")] public static extern bool MessageBeep(int iType); int i = 0x00000040; ClassPublicFunction.MessageBeep(i); 声音的类型 public enum BeepType {  SimpleBeep = -1,  IconAsterisk = 0x00000040,

Xamarin中VS无法连接Mac系统的解决办法

Xamarin中VS无法连接Mac系统的解决办法 按照以下步骤排查:(1)确认Mac系统中安装Xamarin.iOS开发必备的组件,如Mono.Xamarin.iOS.(2)将Windows和Mac下的Xamarin都升级到最新版.(3)在Mac下开启远程登录功能.(4)在Windows下,使用Putty验证Mac的帐号和密码是否有效.

中睿盛分销返利系统源码开发

<center><img src="http://drbd01.oss-cn-shanghai.aliyuncs.com/ABD75B69-7638-B142-2A6B-44550C393389.jpeg" width="500" height="350" /></center><p> </p><p> 在<道德经>五千言中,老子不仅给人们描绘了一个人与人之间&qu

“上下文关键字”KWIC(Key Word in Context,文本中的关键字)检索系统尝试

一.实验目的 1.理解不同体系结构风格的具体内涵. 2.学习体系结构风格的具体实践. 二.实验环境 硬件: (依据具体情况填写) 软件:Java或任何一种自己熟悉的语言 三.实验内容 "上下文关键字"KWIC(Key Word in Context,文本中的关键字)检索系统接受有序的行集合:每一行是单词的有序集合:每一个单词又是字母的有序集合.通过重复地删除航中第一个单词,并把它插入行尾,每一行可以被"循环地移动".KWIC检索系统以字母表的顺序输出一个所有行循环移

Mysql中设置默认时间为系统当前时间

Mysql中设置默认时间为系统当前时间 数据库设计时会遇到的一种情况:将系统当前时间设成默认值存储 数据库设计编码: CREATE TABLE `test` ( `name` varchar(50) NOT NULL, `createtime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 如果使用SQLyog 来设置时间字段的默