决策树——CART和模型树

CART树

理解:      如果CART树处理离散型数据,叫做分类决策树,那么,引入基尼指数作为寻找最好的数据划分的依据,基尼指数越小,说明数据的“纯度越高”,随机森林的代码里边就运用到了基尼指数。如果CART树处理连续型数据时,叫做回归决策树,那么,引入了平方误差,首先,它使用二元切分来处理数据,得到两个子集,计算误差,找到最小误差,确定最佳切分的特征编号和特征值,然后进行建树。

构建回归树,需要给定某个误差计算方法,该函数会找到数据集上最佳的二元切分方式。另外,该函数还要确定什么时候停止划分,一旦停止划分会生成一个叶节点。这里引入reLeaf(),regErr()分别得到叶节点和总方差。叶节点的模型是目标变量的 均值,var()是均方差,所以需要乘以数据集的样本个数。

划分数据集时,如果找不到一个‘好’的二元切分,该函数返回None值并产生叶节点,叶节点的值也为None。

from numpy import *
#载入数据
def loadDataSet(fileName) : dataMat = []fr = open(fileName)for line in fr.readlines() :curLine = line.strip().split('\t')fltLine = list(map(float, curLine))#将后面的数据集映射为浮点型dataMat.append(fltLine)return dataMat#切分数据集为两个子集
# dataSet: 数据集合
# feature: 待切分的特征
# value: 该特征的某个值   
#nonzero():得到数组非零元素的位置(数组索引) 
def binSplitDataSet(dataSet, feature, value) :mat0 = dataSet[nonzero(dataSet[:,feature] > value)[0],:]mat1 = dataSet[nonzero(dataSet[:,feature] <= value)[0],:]return mat0, mat1# 负责生成叶节点,当chooseBestSplit()函数确定不再对数据进行切分时,
# 将调用该regLeaf()函数来得到叶节点的模型,在回归树中,该模型其实就是目标变量的均值
def regLeaf(dataSet) :return mean(dataSet[:, -1])# 误差估计函数,该函数在给定的数据上计算目标变量的平方误差,这里直接调用均方差函数var
# 因为这里需要返回的是总方差,所以要用均方差乘以数据集中样本的个数  
def regErr(dataSet) :return var(dataSet[:, -1]) * shape(dataSet)[0]# dataSet: 数据集合
# leafType: 给出建立叶节点的函数
# errType: 误差计算函数
# ops: 包含树构建所需其他参数的元组
def createTree(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)) :# 将数据集分成两个部分,若满足停止条件,chooseBestSplit将返回None和某类模型的值# 若构建的是回归树,该模型是个常数。若是模型树,其模型是一个线性方程。# 若不满足停止条件,chooseBestSplit()将创建一个新的Python字典,并将数据集分成两份,# 在这两份数据集上将分别继续递归调用createTree()函数feat, val = chooseBestSplit(dataSet, leafType, errType, ops)if feat == None : return valretTree = {}retTree['spInd'] = featretTree['spVal'] = vallSet, rSet = binSplitDataSet(dataSet, feat, val)retTree['left'] = createTree(lSet, leafType, errType, ops)retTree['right'] = createTree(rSet, leafType, errType, ops)return retTree# 回归树的切分函数,构建回归树的核心函数。目的:找出数据的最佳二元切分方式。如果找不到
# 一个“好”的二元切分,该函数返回None并同时调用createTree()方法来产生叶节点,叶节点的
# 值也将返回None。
# 如果找到一个“好”的切分方式,则返回特征编号和切分特征值。
# 最佳切分就是使得切分后能达到最低误差的切分。
def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)) :# tolS是容许的误差下降值# tolN是切分的最小样本数tolS = ops[0]; tolN = ops[1]# 如果剩余特征值的数目为1,那么就不再切分而返回if len(set(dataSet[:, -1].T.tolist()[0])) == 1 :return None, leafType(dataSet)# 当前数据集的大小m,n = shape(dataSet)# 当前数据集的误差S = errType(dataSet)bestS = inf; bestIndex = 0; bestValue = 0for featIndex in range(n-1) :
#        for splitVal in set(dataSet[:, featIndex]) :for splitVal in set(dataSet[:,featIndex].T.tolist()[0]):mat0, mat1 = binSplitDataSet(dataSet, featIndex, splitVal)if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN) : continuenewS = errType(mat0) + errType(mat1)if newS < bestS :bestIndex = featIndexbestValue = splitValbestS = newS# 如果切分数据集后效果提升不够大,那么就不应该进行切分操作而直接创建叶节点if (S - bestS) < tolS :return None, leafType(dataSet)mat0, mat1 = binSplitDataSet(dataSet, bestIndex, bestValue)# 检查切分后的子集大小,如果某个子集的大小小于用户定义的参数tolN,那么也不应切分。if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN) :return None, leafType(dataSet)# 如果前面的这些终止条件都不满足,那么就返回切分特征和特征值。return bestIndex, bestValue

通过降低决策树的复杂度来避免过拟合的过程叫剪枝,预剪枝和后剪枝的单个效果可能是不好的,一般来说,我们可以同时采用这两种剪枝方法。

模型树:

理解:模型树和回归树的区别就是回归树的叶节点是一个常数值,而模型树的叶节点是分段线性函数,分段线性模型就是我们对数据集的一部分数据以某个线性模型建模,而另一份数据以另一个线性模型建模。

#模型树
# 主要功能:将数据格式化成目标变量Y和自变量X。X、Y用于执行简单的线性规划。
def linearSolve(dataSet) :m,n = shape(dataSet) X = mat(ones((m,n))); Y = mat(ones((m,1)))X[:, 1:n] = dataSet[:, 0:n-1]; Y = dataSet[:, -1]xTx = X.T*X# 矩阵的逆不存在时会造成程序异常if linalg.det(xTx) == 0.0 :raise NameError('This matrix is singular, cannot do inverse, \n try increasing the second value of ops')ws = xTx.I * (X.T * Y)return ws, X, Y# 与regLeaf()类似,当数据不需要切分时,它负责生成叶节点的模型。
def modelLeaf(dataSet) :ws, X, Y = linearSolve(dataSet)return ws# 在给定的数据集上计算误差。与regErr()类似,会被chooseBestSplit()调用来找到最佳切分。
def modelErr(dataSet) :ws, X, Y = linearSolve(dataSet)yHat = X * wsreturn sum(power(Y-yHat, 2))# 为了和modeTreeEval()保持一致,保留两个输入参数
def regTreeEval(model, inDat) :return float(model)# 对输入数据进行格式化处理,在原数据矩阵上增加第0列,元素的值都是1
def modelTreeEval(model, inDat) :n = shape(inDat)[1]X = mat(ones((1, n+1)))X[:, 1:n+1] = inDatreturn float(X*model)def isTree(obj):  return (type(obj).__name__=='dict')
# 在给定树结构的情况下,对于单个数据点,该函数会给出一个预测值。
# modeEval是对叶节点进行预测的函数引用,指定树的类型,以便在叶节点上调用合适的模型。
# 此函数自顶向下遍历整棵树,直到命中叶节点为止,一旦到达叶节点,它就会在输入数据上
# 调用modelEval()函数,该函数的默认值为regTreeEval()
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)# 多次调用treeForeCast()函数,以向量形式返回预测值,在整个测试集进行预测非常有用
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

使用Tkinter工具构建图形用户界面:

from numpy import *
from tkinter import *
import regTrees as regTreesimport matplotlib
matplotlib.use('TkAgg')  #设置后端TkAgg
#将TkAgg和matplotlib链接起来
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure#
def reDraw(tolS, tolN) :reDraw.f.clf()   #清空之前的图像reDraw.a = reDraw.f.add_subplot(111)   #重新添加新图if chkBtnVar.get() :  #检查选框model tree是否被选中if tolN < 2 : tolN = 2myTree = regTrees.createTree(reDraw.rawDat, regTrees.modelLeaf, regTrees.modelErr, (tolS, tolN))yHat = regTrees.createForeCast(myTree, reDraw.testDat, regTrees.modelTreeEval)else :myTree = regTrees.createTree(reDraw.rawDat, ops=(tolS, tolN))yHat = regTrees.createForeCast(myTree, reDraw.testDat)# reDraw.rawDat[:,0].A,需要将矩阵转换成数组reDraw.a.scatter(reDraw.rawDat[:,0].A, reDraw.rawDat[:,1].A, s=5) # 绘制真实值reDraw.a.plot(reDraw.testDat, yHat, linewidth=2.0) # 绘制预测值reDraw.canvas.show()#
def getInputs() :#获取输入try : tolN = int(tolNentry.get())  #期望输入是整数except :  #清楚错误用默认值替换tolN = 10print ("enter Integer for tolN")tolNentry.delete(0, END)tolNentry.insert(0, '10')try : tolS = float(tolSentry.get())except :   #期望输入是浮点数tolS = 1.0print ("enter Float for tolS")tolSentry.delete(0, END)tolSentry.insert(0, '1.0')return tolN, tolS# 
def drawNewTree() :# 取得输入框的值tolN, tolS = getInputs()   # 从输入文本框中获取参数# 利用tolN,tolS,调用reDraw生成漂亮的图reDraw(tolS, tolN)  #绘制图#布局GUI
root = Tk()
# 创建画布
Label(root, text='Plot Place Holder').grid(row=0, columnspan=3)Label(root, text='tolN').grid(row=1, column=0)
tolNentry = Entry(root)
tolNentry.grid(row=1, column=1)
tolNentry.insert(0, '10')
Label(root, text='tolS').grid(row=2, column=0)
tolSentry = Entry(root)
tolSentry.grid(row=2, column=1)
tolSentry.insert(0, '1.0')
# 点击“ReDraw”按钮后,调用drawNewTree()函数
Button(root, text='ReDraw', command=drawNewTree).grid(row=1, column=2, rowspan=3)chkBtnVar = IntVar()
chkBtn = Checkbutton(root, text='Model Tree', variable=chkBtnVar)
chkBtn.grid(row=3, column=0, columnspan=2)reDraw.f = Figure(figsize=(5,4), dpi=100)
reDraw.canvas = FigureCanvasTkAgg(reDraw.f, master=root)
reDraw.canvas.show()
reDraw.canvas.get_tk_widget().grid(row=0, columnspan=3)reDraw.rawDat = mat(regTrees.loadDataSet('ex00.txt'))
reDraw.testDat = arange(min(reDraw.rawDat[:, 0]), max(reDraw.rawDat[:, 0]), 0.01)reDraw(1.0, 10)root.mainloop()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466868.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

宏比较值,坑的一B

昨晚上&#xff0c;我准备睡觉&#xff0c;连总给我发了一段代码#include "stdio.h"#define MAX_MACRO(a, b) ((a) > (b) ? (a) : (b)) int MAX_FUNC(int a, int b) {return ((a) > (b) ? (a) : (b)); }int main() {unsigned int a 1;int b -1;printf(&quo…

Linux下Samba服务器搭建

linux文件共享之samba服务器 ——ubuntu 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 关闭LINUX防火墙命令&#xff1a; #ufwdisable 然后就在windows下ping一下linux的IP&#xff0c;如果能ping通&#xff0c;就可以继续下面的内容&#xff0c;如果p…

日志分析linux命令

1、查看文件内容&#xff1a;cat 。-n显示行号。 2. more&#xff1a;全屏幕分页显示文件的内容。下一页&#xff1a;space键&#xff1b;上一页&#xff1a;B&#xff1b;停止&#xff1a;Q&#xff1b;显示下一行&#xff1a;Enter&#xff1b; 3. less&#xff1a;在文件最…

C#比较两时间大小

1。比较时间大小的实验 string st1"12:13"; string st2"14:14"; DateTime dt1Convert.ToDateTime(st1); DateTime dt2Convert.ToDateTime(st2); DateTime dt3DateTime.Now; if(DateTime.Compare(dt1,dt2)>0) msg.Textst1">…

搞懂C++为什么难学,看这篇就够了!

学C能干什么&#xff1f; 往细了说&#xff0c;后端、客户端、游戏引擎开发以及人工智能领域都需要它。往大了说&#xff0c;构成一个工程师核心能力的东西&#xff0c;都在C里。跟面向对象型的语言相比&#xff0c;C是一门非常考验技术想象力的编程语言&#xff0c;因此学习起…

2017 实习面试问题总结(阿里、头条、美团、cvte、乐视、华为)

2017 实习面试问题总结&#xff08;阿里、头条、美团、cvte、乐视、华为&#xff09; Java后台面试 常见问题转载于:https://www.cnblogs.com/straybirds/p/8319566.html

SAP BC417 课程中文自学笔记

BC417: BAPI Development for Accessing SAP Components开发自定义 BAPI 的方法http://files.cnblogs.com/qiangsheng/SAP_BC417.rarhttp://files.cnblogs.com/qiangsheng/SAP_BC417_appendix.rar

看图学源码之FutureTask

RunnableFuture 源码学习&#xff1a; 成员变量 任务的运行状态的转化 package java.util.concurrent; import java.util.concurrent.locks.LockSupport;/**可取消的异步计算。该类提供了Future的基本实现&#xff0c;包括启动和取消计算的方法&#xff0c;查询计算是否完成以…

单片机的引脚,你都清楚吗?

第1课&#xff1a;单片机简叙1.单片机可以做什么&#xff1f;目前单片机渗透到我们生活的各个领域&#xff0c;几乎很难找到哪个领域没有单片机的踪迹。小到电话&#xff0c;玩具&#xff0c;手机&#xff0c;各类刷卡机&#xff0c;电脑键盘&#xff0c;彩电&#xff0c;冰箱&…

Graphviz的安装及纠错

在Anaconda Prompt里边输入conda install graphviz 安装成功之后输入pip install graphviz 它会提示成功安装。 启动 Jupyter Notebook &#xff0c;在文件里边输入 import graphviz 测试&#xff0c;如果没有报错证明&#xff0c;模块安装成功&#xff0c;但是在运行程序…

基于ubuntu13.04搜狗输入法安装方法

基于ubuntu13.04搜狗输入法安装方法 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 sudo gedit etcaptsources.list 在打开的文件中加入以下两行&#xff1a; deb http ppa.launchpad.netfcitx-teamnightlyubuntu quantal main deb-src http ppa.lau…

给磁盘加个背景

给你的磁盘加上漂亮的背景先看下效果&#xff1a;具体方法&#xff1a;很简单的方法&#xff0c;新建一个文本文档输入以下内容&#xff1a;[ExtShellFolderViews]{BE098140-A513-11D0-A3A4-00C04FD706EC}{BE098140-A513-11D0-A3A4-00C04FD706EC}[{BE098140-A513-11D0-A3A4-00C…

/etc/fstab 参数详解及如何设置开机自动挂载

某些时候当Linux系统下划分了新的分区后&#xff0c;需要将这些分区设置为开机自动挂载&#xff0c;否则&#xff0c;Linux是无法使用新建的分区的。 /etc/fstab 文件负责配置Linux开机时自动挂载的分区。 Windows的文件结构是多个并列的树状结构&#xff0c;最顶部的是不同的磁…

sklearn——决策树

总结sklearn决策树的使用&#xff0c;方便以后查阅。1.分类决策树 &#xff08;基于CART树&#xff09; 原型&#xff1a;参数&#xff1a;2、回归分类树 原型&#xff1a;参数&#xff1a;3、export_graphviz 当训练完毕一颗决策树时&#xff0c;可以通过sklearn.tree.expor…

Linux下SVN服务器的搭建

Linux下SVN服务器的搭建 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 1、下载工具&#xff08;下载地址&#xff1a;&#xff09; subversion-1.6.1.tar.gz subversion-deps-1.6.1.tar.gz 2、解压两个包&#xff1a; a) tar -xzvf subvers…

记一次解决问题的掉坑过程

这两天在调试一个音频ADC 芯片&#xff0c;也是之前的项目&#xff0c;但是一直调不出来&#xff0c;我发现我总是在这样的问题上纠结很久&#xff0c;以前踩过的坑后面照样会踩&#xff0c;只不过踩完会迅速把脚拉出来继续前进&#xff0c;我经常听到有人说「做嵌入式真的太容…

体验了一下用word 2007发表博客

一个字&#xff1a;爽&#xff01;再也不同上传图片&#xff0c;在IE里排版了。

P2548 [AHOI2004]智能探险车

原题链接&#xff1a;https://www.luogu.org/problemnew/show/2548 讲道理这题水过了。。。 题意简述&#xff1a;给出n*m个字符串&#xff0c;要求检查是否在所有的n行字符串中&#xff0c;第m个字符串都相同&#xff0c;是则输出该字符串&#xff0c;否则输出“*” 没什么好说…

sklearn——AdaBoost应用

选自《python大战机器学习》

面试常见的C语言字符串操作

#字符串倒序输出实现逻辑&#xff0c;通过strlen获取字符串长度&#xff0c;然后通过 len/2 进行交叉赋值&#xff0c;这里需要注意&#xff0c;不需要考虑len是奇数还是偶数的问题。如果len是奇数&#xff0c;最后一个字符就不需要倒序&#xff0c;如果是偶数&#xff0c;最后…