树回归CART(Classification And Regression Tree)(2)
2016-12-30 16:01
429 查看
前面,我们分析了树回归的切分函数。但是如果一棵树节点过多,表明该模型可能对数据“过拟合”。为了避免过拟合,经常通过“剪枝”技术来降低决策树的复杂度。在前面chooseBestSplit()函数中设置的提前终止条件,实际上就是在进行一种所谓的的“预剪枝”。相对应的“后剪枝”则是需要训练集和测试集的共同作用。
1 预剪枝
我们在树回归中: 树的构建算法对输入的参数tolS 和 tolN 非常敏感。而去手动的修改参数并非一个明智的选择,而事实上,我们大多时间甚至不知道我们需要的结果是什么,因此“后剪枝”技术就应运而生,即利用测试集来对数进行剪枝,不需要我们指定参数,是一种跟接近于机器学习理念的剪枝方法。
2 后剪枝
后剪枝需要把数据集分为训练集和测试集,首先制定参数,使得构建出的原始树足够大,然后在该树上进行剪枝,从上到下找到叶节点,用测试集来验证是否可以将这些叶节点合并(利用测试误差来判断)。
伪代码:
注
我们在刚开始对测试集检测是否为空,一旦非空,则对测试数据进行二元切分。切分的两个子集,被当作测试集来对相应的子树进行剪枝。
3 模型树
前面介绍的回归树的叶节点都是常数值,还有一种就是把叶节点设定为分段线性函数。
如图,显然分段线性模型可以更好的去建模。
我们在前面回归数的代码上进行修改来得到模型数的代码。
首先要利用树生成算法对数据进行切分,且每份切分数据都能很容易的被线性模型所表示。该算法的关键就是误差的计算。回顾前面的回归树,误差是:点与点之间的差值。在模型树中该误差计算方法不成立,因此可以先线性回归去拟合给定的数据集,然后计算真实目标值和预测值之间的误差,最后将这些误差值平方求和就得到最终的误差值
注
模型数的构建还是很简单的。创建模型树的时候需要将模型树函数作为creatTree()的参数即可。
对于数据:
构建的模型树:
数据在0.28处分段生成两个线性模型:
y=3.468+1.185x 和 y=0.00169+11.965x
1 预剪枝
我们在树回归中: 树的构建算法对输入的参数tolS 和 tolN 非常敏感。而去手动的修改参数并非一个明智的选择,而事实上,我们大多时间甚至不知道我们需要的结果是什么,因此“后剪枝”技术就应运而生,即利用测试集来对数进行剪枝,不需要我们指定参数,是一种跟接近于机器学习理念的剪枝方法。
2 后剪枝
后剪枝需要把数据集分为训练集和测试集,首先制定参数,使得构建出的原始树足够大,然后在该树上进行剪枝,从上到下找到叶节点,用测试集来验证是否可以将这些叶节点合并(利用测试误差来判断)。
伪代码:
基于已有的树切分测试数据: 如果存在任一子集是一颗树,则在该子集递归剪枝过程 计算将当前两个叶节点合并后的误差 计算不合并的误差 比较两个误差,如果误差降低,就降两个叶节点合并
# 后剪枝技术 prune.py def isTree(obj): return(type(obj).__name__ == 'dict') # 测试输入变量是否是一棵树。返回布尔类型值 def getMean(tree): '从上到下遍历树,直到叶节点,如果找到两个叶节点就计算平均值(塌陷处理)' if isTree(tree['right']): # 右子树非叶节点 tree['right'] = getMean(tree['right']) # 递归 if isTree(tree['left']): tree['left'] = getMean(tree['left']) # 递归 直到找到叶节点 return (tree['left']+tree['right'])/2.0 # 返回平均值 def prune(tree, testData): '剪枝核心 参数:代建制的树 和剪枝所用的测试集' # 首先确认测试集是否为空,为空,即没有测试集,则对数进行塌陷处理。一旦非空,则对测试数据进行切分。 if (np.shape(testaData)[0] == 0): return getMean(tree) # 进行塌陷处理(平均值) # 检查某个分支是子树还是叶节点,如果有是子树,则将调用prune函数对该子树进行剪枝 if isTree(tree['right']) or isTree(tree['left']): lSet, rSet = binSplitDataSet(testData, tree['spInd'], tree['spVal']) if isTree(tree['right']): tree['right'] = prune(tree['right'], rSet) if isTree(tree['left']): tree['left'] = prune(tree['left'], lSet) # 对左右两个分支完成剪枝后,还要检查它们是否还为子树。如果不再是子树,就可以合并 if not isTree(tree['left']) and not isTree(tree['right']): lSet, rSet = binSplitDataSet(testData, tree['spInd'], tree['spVal']) errorNoMerge = sum(np.power(lSet[:, -1]-tree['left'], 2)) + sum(np.power(rSet[:, -1]-tree['right'], 2)) # 计算没有合并的误差 treeMean = (tree['left'] + tree['right'])/2.0 errorMerge = sum(np.power(testData[:, -1]-treeMean, 2)) if errorMerge < errorNoMerge: print("Merging") return treeMean else: return tree else: # 左右两个分支完成剪枝后,如果还是子树,返回tree return tree
注
我们在刚开始对测试集检测是否为空,一旦非空,则对测试数据进行二元切分。切分的两个子集,被当作测试集来对相应的子树进行剪枝。
3 模型树
前面介绍的回归树的叶节点都是常数值,还有一种就是把叶节点设定为分段线性函数。
如图,显然分段线性模型可以更好的去建模。
我们在前面回归数的代码上进行修改来得到模型数的代码。
首先要利用树生成算法对数据进行切分,且每份切分数据都能很容易的被线性模型所表示。该算法的关键就是误差的计算。回顾前面的回归树,误差是:点与点之间的差值。在模型树中该误差计算方法不成立,因此可以先线性回归去拟合给定的数据集,然后计算真实目标值和预测值之间的误差,最后将这些误差值平方求和就得到最终的误差值
# 模型数的构建(误差计算) def linearSolve(dataSet): '对所给数据进行线性回归拟合' m, n = np.shape(dataSet) X = np.mat(np.ones((m, n))) # 待拟合样本 Y = np.mat(np.ones((m, 1))) # 预测值 X[:, 1:n] = dataSet[:, 0:n-1] # 第一列全部为1 Y = dataSet[:, -1] XTX = X.T * X if np.linalg.det(XTX) == 0: # 行列式为0, 矩阵不可逆 raise NameError('The Matrix cannot be inverse!') ws = XTX.I * (X.T * Y) return ws, X, Y def modelLeaf(dataSet): # 这个函数 与 树回归 的regLeaf函数功能一致 ws, X, Y = linearSolve(dataSet) return ws def modelError(dataSet): '计算误差' ws, X, Y = linearSolve(dataSet) yHat = X * ws return sum(np.power(Y - yHat, 2))
注
模型数的构建还是很简单的。创建模型树的时候需要将模型树函数作为creatTree()的参数即可。
对于数据:
构建的模型树:
数据在0.28处分段生成两个线性模型:
y=3.468+1.185x 和 y=0.00169+11.965x
相关文章推荐
- 分类回归树-classification and regression tree-CART
- 树回归CART(Classification And Regression Tree)(1)
- 分类与回归树(CART,Classification And Regression Tree)
- CART(Classification And Regression Tree)
- 【数据挖掘】决策树之CART (Classification and Regression Trees)分类与回归树
- 分类和回归树(CART, Classification and Regression Trees)
- 分类和回归树CART(Classification and Regresstion tree)
- CART(Classification And Regression Tree)算法原理详解
- 分类和回归 Classification and Regression
- 机器学习2——分类和逻辑回归Classification and logistic regression(牛顿法待研究)
- 机器学习算法笔记1_2:分类和逻辑回归(Classification and Logistic regression)
- Classification&Regression(分类&回归)
- Regression(1)------The difference between classification and regression
- CART分类与回归树与GBDT(Gradient Boost Decision Tree)
- 分类和逻辑回归(Classification and logistic regression)
- [机器学习笔记]二:Classification and logistic regression(分类和逻辑回归)
- 161206 - Ordinary least square, ridge regression and weighted least square 最小二乘,岭回归,加权最小二乘
- MLlib - Classification and Regression
- 分类和逻辑回归(Classification and logistic regression)
- Draw nicer Classification and Regression Trees with the rpart.plot package