首页 » 机器学习实战 » 机器学习实战全文在线阅读

《机器学习实战》9.6 示例:树回归与标准回归的比较

关灯直达底部

前面介绍了模型树、回归树和一般的回归方法,下面测试一下哪个模型最好。本节首先给出一些函数,它们可以在树构建好的情况下对给定的输入进行预测,之后利用这些函数来计算三种回归模型的测试误差。这些模型将在某个数据上进行测试,该数据涉及人的智力水平和自行车的速度的关系。

这里的数据是非线性的,不能简单地使用第8章的全局线性模型建模。当然这里也需要声明一下,此数据纯属虚构。

下面先给出在给定输入和树结构情况下进行预测的几个函数。打开regTrees.py并加入如下代码。

程序清单9-5 用树回归进行预测的代码

def regTreeEval(model, inDat):    return float(model)def modelTreeEval(model, inDat):    n = shape(inDat)[1]    X = mat(ones((1,n+1)))    X[:,1:n+1]=inDat    return float(X*model)def treeForeCast(tree, inData, modelEval=regTreeEval):    if not isTree(tree): return modelEval(tree, inData)    if inData[tree[/'spInd/']] > tree[/'spVal/']:        if isTree(tree[/'left/']):            return treeForeCast(tree[/'left/'], inData , modelEval)        else:            return modelEval(tree[/'left/'], inData)    else:        if isTree(tree[/'right/']):            return treeForeCast(tree[/'right/'], inData , modelEval)        else:            return modelEval(tree[/'right/'], inData)def createForeCast(tree, testData, modelEval=regTreeEval):    m=len(testData)    yHat = mat(zeros((m,1)))    for i in range(m):        yHat[i,0] = treeForeCast(tree, mat(testData[i]), modelEval)    return yHat    

对于输入的单个数据点或者行向量,函数treeForeCast会返回一个浮点值。在给定树结构的情况下,对于单个数据点,该函数会给出一个预测值。调用函数treeForeCast时需要指定树的类型,以便在叶节点上能够调用合适的模型 。参数modelEval是对叶节点数据进行预测的函数的引用。函数treeForeCast自顶向下遍历整棵树,直到命中叶节点为止。一旦到达叶节点,它就会在输入数据上调用modelEval函数,而该函数的默认值是regTreeEval

要对回归树叶节点进行预测,就调用函数regTreeEval;要对模型树节点进行预测时,就调用modelTreeEval函数。它们会对输入数据进行格式化处理,在原数据矩阵上增加第0列,然后计算并返回预测值。为了与函数modelTreeEval保持一致, 尽管regTreeEval只使用一个输入,但仍保留了两个输入参数。

最后一个函数是createForCast,它会多次调用treeForeCast函数。由于它能够以向量形式返回的一组预测值,因此该函数在对整个测试集进行预测时非常有用。下面很快会看到这一点。

接下来考虑图9-6所示的数据。该数据是我从多个骑自行车的人那里收集得到的。图中给出骑自行车的速度和人的智商之间的关系。下面将基于该数据集建立多个模型并在另一个测试集上进行测试。对应的训练集数据保存在文件bikeSpeedVsIq_train.txt中,而测试集数据保存在文件bikeSpeedVsIq_test.txt中。

图9-6 人们骑自行车的速度和他们智商之间的关系数据。该数据用于比较树回归模型和普通的线性回归模型

下面将为图9-6的数据构建三个模型。首先,将程序清单9-5中的代码保存为regTrees.py,然后在Python提示符下输入以下命令:

>>>reload(regTrees)  

接下来,利用该数据创建一棵回归树:

>>> trainMat=mat(regTrees.loadDataSet(/'bikeSpeedVsIq_train.txt/'))>>> testMat=mat(regTrees.loadDataSet(/'bikeSpeedVsIq_test.txt/'))>>> myTree=regTrees.createTree(trainMat, ops=(1,20))>>> yHat = regTrees.createForeCast(myTree, testMat[:,0])>>> corrcoef(yHat, testMat[:,1],rowvar=0)[0,1]0.96408523182221306  

同样地,再创建一棵模型树:

>>> myTree=regTrees.createTree(trainMat, regTrees.modelLeaf,    regTrees.modelErr,(1,20))>>> yHat = regTrees.createForeCast(myTree, testMat[:,0],    regTrees.modelTreeEval)>>> corrcoef(yHat, testMat[:,1],rowvar=0)[0,1]0.9760412191380623  

我们知道,R2值越接近1.0越好,所以从上面的结果可以看出,这里模型树的结果比回归树好。下面再看看标准的线性回归效果如何,这里无须导入第8章的任何代码,本章已实现过一个线性方程求解函数linearSolve

>>> ws,X,Y=regTrees.linearSolve(trainMat)>>> wsmatrix([[ 37.58916794],    [ 6.18978355]])   

为了得到测试集上所有的yHat预测值,在测试数据上循环执行:

>>> for i in range(shape(testMat)[0]):...     yHat[i]=testMat[i,0]*ws[1,0]+ws[0,0]...   

最后来看一下R2值:

>>> corrcoef(yHat, testMat[:,1],rowvar=0)[0,1]0.94346842356747584   

可以看到,该方法在R2值上的表现上不如上面两种树回归方法。所以,树回归方法在预测复杂数据时会比简单的线性模型更有效,相信读者对这个结论也不会感到意外。下面将展示如何对回归模型进行定性的比较。

下面使用Python提供的框架来构建图形用户界面(GUI),读者可以使用该GUI来探究不同的回归工具。