机器学习基础 第二章 预测算法
来源:互联网 发布:linux jdk设置jvm内存 编辑:程序博客网 时间:2024/05/24 01:06
1 一元线性回归
1.1 为什么用回归
图1.1.1 Google的票房与搜索量的关系
图1.1显示的是Google发布的电影的搜索量与票房的关系。如何用历史的信息预测票房就是(线性)回归问题。
1.2 一元线性回归模型
1 数学描述
只要最小化式(1.2-2),就可以求出系数
2 矩阵表示
对于N各数据点,式(1.2-1)有N个等式,并用线性代数表示为
其中
此时
其中
所以式(1.2.2)又可以表示为
3 目标函数最小化
在高等数学中,使函数一阶导数为0,且二阶导数要大于0的点为函数的最小值点。式(1.2-5)所表示的是二次函数且开口向上,只要求一阶导数为0即可
【矩阵求导:
1 详细推导
2 详细推导
所以线性模型所对应的最优参数
一个简单的例子,代码见文件夹1_regression。
第一步:用synthic_data.py中的linearSamples方法生成数据
import numpy as npimport randomdef linearSamples(n = 20): a = 0.5 b = 1.0 r = [i + 2.0*random.random() for i in xrange(n)] return [range(0, len(r)), r]
第二步:用linear_regression.py中的lR方法,完成式(1.2-7),最终的结果为
def lR(x, y): x = np.matrix(x) if x.shape[0] == 1: x = x.transpose() y = np.matrix(y) if y.shape[0] == 1: y = y.transpose() one = np.ones((x.shape[0], 1)) x = np.hstack([one, x]) w = inv((x.transpose()).dot(x)).dot(np.transpose(x)).dot(y) return w
第三步:将第二步中计算的
def plotLM(w, x,y): xx = [i for i in np.arange(0.0,20.0,0.5)] yy = [w[0,0] + w[1,0] * i for i in xx] fig = plt.figure() ax = fig.add_subplot(111) ax.plot(x,y, '.') ax.plot(xx,yy) s = 'y = %s + %s * x' %(str(w[0,0])[0:7], str(w[1, 0])[0:7]) ax.annotate(s, xy=(12.5, 13.3), xycoords='data', xytext=(-180, 30), textcoords='offset points', bbox=dict(boxstyle="round", fc="0.8"), arrowprops=dict(arrowstyle="->", connectionstyle="angle,angleA=0,angleB=90,rad=10")) plt.xlabel('x') plt.ylabel('y') plt.legend(('training sampes','regression line')) plt.show()
图1.2.2 线性回归的例子
在图1.2.2中散点代表的是训练数据,训练数据是由程序随机生成,没有实际意义,直线是回归直线,并标出了直线方程,在运行程序时直线结果可能与图中的结果稍有不同,因为训练数据是随机生成的缘故。
2 最优化方法-梯度下降法
在第一节的第3部分介绍了,将损失函数表示成矩阵形式,然后求导方法,求出最优的
梯度下降法是最常用、也是最容易理解的最优化方法。学会了梯度下降法,其它基于梯度的改进方法:共轭梯度法、牛顿法、拟牛顿法等,就比较容易理解。
1 盲人是如何下山的
第一步:左踩一脚,右踩一脚,如果发现这两脚在在高度上没有差别,此时他所面对的应该是山顶或者山脚,反之盲人面对的应该是山脊。(计算偏导数)
第二步:上踩一脚,下踩一脚,脚低的那个方向就对着山脚。(计算偏导数)
第三步:四个脚中,高度最低的那个方向就是山脚,从当前位置向下夸一小步,向着山脚进发。(确定步长,学习率)
重复第一、二、三步,直到山脚。
2 梯度下降法
梯度法就和盲人下山类似,就两个步骤:首先确定下山方,然后再确定的方向上按照一定的步长下山。
下面介绍最优化问题。
单目标、无约束、多维最优化问题的数学描述:
其中,
梯度下降法算法流程如下:
1)给定初值
2)
【
其中,
3)若
4)令
3 基于梯度下降法的线性回归
下面用用梯度下降法,优化目标函数:式(1.2.2),并给出相应的代码解释
第一步:依然使用linearSamples生成数据,代码见前文
第二步:完成目标函数的定义,即式(1.2-2)
def obj(x, y, w): t = x.dot(w) - y t = np.multiply(t, t) sum_ = 0.5 * np.sum(t) return sum_
第三步:完成数值梯度的定义,按照梯度下降法中的第2)点介绍,完成代码编写
def gradient(fun, x, y, w, delta = 1e-6, *args): l = len(w) g = [] for i in range(0, l): delta_w = deepcopy(w) delta_w[i] = delta_w[i] + delta g.append(-(obj(x, y, delta_w) - obj(x, y, w))/delta) return g
第四步:gdLR方法将实现,梯度下降法中介绍的流程1),2),4),忽略了第三步,其中的学习率由手动调整。计算结束后返回最优的
def gdLR(fun, x, y, step = 0.0007,tol = 1e-6): #preprocess the data x = np.matrix(x) if x.shape[0] == 1: x = x.transpose() y = np.matrix(y) if y.shape[0] == 1: y = y.transpose() one = np.ones((x.shape[0], 1)) x = np.hstack([one, x]) w = [0.0, 0.0] w = np.matrix(w) if w.shape[0] == 1: w = w.transpose() l = len(w) k = 1 while(True): step1 = step / k #1)compute negative gradient g = gradient(fun, x, y, w) err = linalg.norm(g) print err if err < tol or k > 200: break #2)updata the parameters w = [w[i,0] + step * g[i] for i in range(0, l)] w = np.matrix(w).transpose() k = k + 1 return w
第五步:将闭形式的
def plotGdLM(cf_w,gd_w, x,y): xx = [i for i in np.arange(0.0,20.0,0.5)] cf_yy = [cf_w[0,0] + cf_w[1,0] * i for i in xx] gd_yy = [gd_w[0,0] + gd_w[1,0] * i for i in xx] fig = plt.figure() ax = fig.add_subplot(111) ax.plot(x,y, '.') ax.plot(xx,cf_yy,color = 'g', linewidth=3) s = 'y = %s + %s * x' %(str(cf_w[0,0])[0:7], str(cf_w[1, 0])[0:7]) ax.annotate(s, xy=(12.5, 13.3), xycoords='data', xytext=(-180, 30), textcoords='offset points', bbox=dict(boxstyle="round", fc='g', ec='g'), arrowprops=dict(arrowstyle="->",fc='g', ec='g', connectionstyle="angle,angleA=0,angleB=90,rad=10")) ax.plot(xx,gd_yy, color = 'r', linewidth=3) s = 'y = %s + %s * x' %(str(gd_w[0,0])[0:7], str(gd_w[1, 0])[0:7]) ax.annotate(s, xy=(8.5, 9.3), xycoords='data', xytext=(-180, 30), textcoords='offset points', bbox=dict(boxstyle="round", fc='r', ec='r'), arrowprops=dict(arrowstyle="->", fc='r', ec='r', connectionstyle="angle,angleA=0,angleB=90,rad=10")) plt.xlabel('x') plt.ylabel('y') plt.legend(('training sampes', 'closed-form regression','gradient descent regression'),loc='upper center') plt.show()
图2.1 解析解与梯度下降法解的对比图
3 基函数
3.1 多项式回归
如果有如图2.1的数据,依然采用式(1.2-1)的模型,则回归模型如图2.2。从图2.2中可以看出,用式(1.2-1)所表示的模型无法拟合这种带多个峰的数据。一个很直观的想法是增加式(1.2-1)中的项数,用多项式拟合这种多个峰的数据
式(3.1)写成矩阵形式为
按照1.2节中的方法,也可以得到
为了与式(1.2-7)加以区别,用
其中,
图3.1.1
图3.1.2 按照式(3.1-3),分别用3、5、10、12阶多项式拟合数据,结果如图2.3。图(d)中的拟合曲线的末端上翘与数据不吻合了。这是过拟合导致的。过拟合问题将会在下一节中介绍。
实现图3.1.3的代码如下:
第一步:生成
def nlSamples(n = 100): t = np.arange(0, 1.0, 1.0 / n) y = [ti + 0.3 * math.sin(2 * math.pi * ti)+random.random()*0.01 for ti in t] t = list(t) return [t, y]
第二步:按照式(3.1-3)计算模型的参数
def bFLR(x, y, rank = 2): x = np.matrix(x) if x.shape[0] == 1: x = x.transpose() y = np.matrix(y) if y.shape[0] == 1: y = y.transpose() one = np.ones((x.shape[0], 1)) tmp = np.zeros((x.shape[0], rank)) for i in xrange(rank): tmp[:,i] = np.power(x.A, i + 1).transpose() xx = np.hstack([one, tmp]) w = inv((xx.transpose()).dot(xx)).dot(np.transpose(xx)).dot(y) return w
第三步:用第三步中的参数
def plotBFLR(w, x, y, rank = 2): xx = [i for i in np.arange(0.0,1.0,1.0/20)] w = w.A.transpose() yy = [w.dot(xlist(i, rank))[0,0] for i in xx] fig = plt.figure() ax = fig.add_subplot(111) ax.plot(x,y, 'ro') ax.plot(xx,yy) plt.xlabel('x') plt.ylabel('y') plt.title(str(rank) + ' order regression') plt.legend(('training sampes','regression line'))plt.show()def xlist(i, rank): l = [np.power(i ,ii) for ii in xrange(rank+1)] l = np.array([l]).transpose() return l
图3.1.3 多项式拟合结果
3.2 回归模型中的基函数
式(3.1-1)更一般化的表示为
其中的
多项式回归中的
其它形式的常用基函数有:高斯基函数,逻辑蒂斯基函数,它们的表达式分别如下
高斯基函数:
其中,
其中
4 欠拟合与过拟合
4.1 欠拟合
忽略严格的数学定义,从一般的直观理解欠拟合,概念如下。
欠拟合:模型过于简单,无法捕获数据中所存在的规律,图3.1.2所示的情况就是欠拟合,因为采用的模型为
欠拟合的解决办法:增加模型的复杂度,如将一次多项式模型,增加到3阶或者更高阶。对比图3.1.2和图3.1.3即可发现其变化过程。
4.2 过拟合
同样也可以给出过拟合的概念如下。
过拟合:和欠拟合相对,指模型过于复杂,模型在训练数据上的训练误差很小,而在测试数据的测试误差很大,即泛化能力很差。图3.1.3中的(d)就是过拟合现象,12阶的多项式模型对于(d)中的数据复杂度太高了,其实用3阶多项式模型就能取得不错的效果。
过拟合的解决办法:
1)不改变模型,增加数据
当过拟合时,不改变模型,增加数据可以改善过拟合问题,图3.1.3中的(d)只有20个数据点,现在将数据点增加到2000个,依然用12阶的多现实拟合,结果下图
图4.2.1 增加数据点后的12阶回归模型
2)改变模型:正则化
依然对图3.1.3中的(d)的问题,如果没有足够的数据点,则可以减少模型中的特征,即将12阶模型降低为更低阶的模型,有一种方法称之为正则化,正则化方法通过在损失函数
按照前文介绍的方法,依然可以得到,正则化后的模型参数如下
其中,
按照式(4.2-2),实现的代码如下
def rTLR(x, y, lamda = 0.5,rank = 2): x = np.matrix(x) if x.shape[0] == 1: x = x.transpose() y = np.matrix(y) if y.shape[0] == 1: y = y.transpose() one = np.ones((x.shape[0], 1)) tmp = np.zeros((x.shape[0], rank)) for i in xrange(rank): tmp[:,i] = np.power(x.A, i + 1).transpose() xx = np.hstack([one, tmp]) dim = xx.shape[1] I = lamda * np.diag(np.ones(dim)) w = inv(I + (xx.transpose()).dot(xx)).dot(np.transpose(xx)).dot(y) return w
图4.2.2是不同正则化参数下的回归曲线,从中可以看出
图4.2.2 不同罚参数
5 多元线性回归
以上介绍的是一元回归,如果自变量的个数不止一个,就会要求使用多元回归,多元线性回归最简单的形式如下
其中
所以和一元回归类似,也可以引入基函数的概念,引入基函数后的表达如下
其中,
同理可以得到模型的参数
其中
下面看一个二元回归的例子。
有如图5.1所示的曲面,建立一个回归模型拟合这个曲面,由于这个曲面是个二次曲面,所以在选择基函数时可以选择到二次或者更高次,比如选择
按照式(5.4)代入式(5.3)可以求得模型参数
图5.1 二维曲面
下面看看用以上思路能否拟合出图5.1的曲面。
第一步:生成图5.1所示的数据,在x,y方向分别等距离采集数据点40个,Python代码如下:
第二步:用生成的数据点,按照式(5-3)求出参数
第三步:用第二步中计算的参数
图5.2 真实值和预测值得对比图
实际上线性回归模型的非线性拟合能力较差,对于图5.3的多峰值函数就无能为力,本来这里给出的例子想用图5.3,结果,解释采用20阶以上的多项式也拟合不出图5.3的样子,无奈采用图5.1,相对简单一些,不过神经网络可以对高度非线性数据进行拟合,详细的Python代码和参考文献可以见
http://blog.csdn.net/zc02051126/article/details/9337319
图5.3 Matlab中的peaks函数产生的曲面
6 应用实例-Google票房预测模型
- 机器学习基础 第二章 预测算法
- 基础机器学习算法
- 基础机器学习算法
- 机器学习基础算法
- 斯坦福 机器学习-第二章 生成学习算法
- 《机器学习实战》学习-第二章 k-近邻算法
- 机器学习基础 第三章 分类算法
- 机器学习第二章。
- 【机器学习】基础机器学习算法
- 机器学习未来预测
- 机器学习基础—Kaggle泰坦尼克预测(完整分析)
- 机器学习实战——第二章:K-近邻算法
- 《机器学习实战》读书笔记:第二章 k-近邻算法
- 【1】机器学习实战 第二章 k近邻算法
- 《机器学习实战》第二章 - k-近邻算法
- 机器学习实战+第二章_k-近邻算法
- 机器学习实战第二章K近邻算法照葫芦画瓢实践。
- 《机器学习实战》第二章 k-近邻算法
- (八)play之yabe项目【身份验证】
- CUDA8.0+Ubuntu14.04+Caffe安装过程之CUDA安装教程
- SDWebImage源码解读 之SDWebImagePrefetcher
- LeetCode 110. Balanced Binary Tree
- (九)play之yabe项目【发表博文】
- 机器学习基础 第二章 预测算法
- GMT时间和UTC时间,当前时间
- PART III 硬件层 Chapter 5 计算部件
- JavaScript 朝着群星前进的动态背景
- SDWebImage源码解读之 分类
- React Native之StyleSheet样式表
- faster rcnn在win10+cuda7.5下的matlab配置
- C语言实验——分数序列 (sdut oj)
- android-文件操作