前面说了那么多,一直围绕着分类问题讨论,下面我们开始学习回归树吧,

cart生成有两个关键点

  • 如何评价最优二分结果
  • 什么时候停止和如何确定叶子节点的值

cart分类树采用gini系数来对二分结果进行评价,叶子节点的值使用多数表决,那么回归树呢?我们直接看之前的一个数据集(天气与是否出去玩,是否出去玩改成出去玩的时间)

sunny    hot    high    FALSE    25
sunny hot high TRUE 30
overcast hot high FALSE 46
rainy mild high FALSE 45
rainy cool normal FALSE 52
rainy cool normal TRUE 23
overcast cool normal TRUE 43
sunny mild high FALSE 35
sunny cool normal FALSE 38
rainy mild normal FALSE 46
sunny mild normal TRUE 48
overcast mild high TRUE 52
overcast hot normal FALSE 44
rainy mild high TRUE 30

如果用分类树来做,结果就是这样的,一个结果值一个节点

回归树切分数据集和分类树是一样的,那么我们如何评价一个数据集划分的好坏呢?分类树是用gini系数衡量数据集的类别的混乱程度,同样,我们也可以衡量数据集的回归值的混乱程度,比较经典的是方差和标准差,由于我们需要得到和回归值接近的值作为叶子节点的值,我们这里使用标准差吧

n是回归值的个数,u是平均值,x是每个回归值,S是标准差(standard deviation)

第二个问题:什么时候停止和如何确定叶子节点的值?

分类树是特征用完或者类别都一样;对于回归问题回归值都一样的概率比较小,由于我们过程中不减少特征,所以最后肯定是一个样本一个分支。

有人说当分支的S小于总体的5%,分支就可以结束,然后节点的值取平均值

我们看下这样有效果不?左边是没有停止原始的回归树,右边是加上结束条件的回归树,感觉效果还可以,这样回归树就完成了

对比回归树和分类树的实现,发现基本是就仅仅是一个函数的区别,到这里明白为什么叫分类回归树了吗?

就是同样的代码,只需要改变一个函数,就可以实现分类或者回归的功能的了。

下面附上回归树的完整代码

# regression_tree.py
# coding:utf8
from itertools import *
from numpy import *
import operator,math
def calStDev(dataSet):
classList = [float(example[-1]) for example in dataSet]
n=len(classList)
u=sum(classList)/n
total=0
for x in classList:
total+=(x-u)*(x-u)
S = math.sqrt(total)
return S,u def splitDataSet(dataSet, axis, values):
retDataSet = []
if len(values) < 2:
for featVec in dataSet:
if featVec[axis] == values[0]:#如果特征值只有一个,不抽取当选特征
reducedFeatVec = featVec[:axis]
reducedFeatVec.extend(featVec[axis+1:])
retDataSet.append(reducedFeatVec)
else:
for featVec in dataSet:
for value in values:
if featVec[axis] == value:#如果特征值多于一个,选取当前特征
retDataSet.append(featVec) return retDataSet
# 传入的是一个特征值的列表,返回特征值二分的结果
def featuresplit(features):
count = len(features)#特征值的个数
if count < 2:
# print features
# print "please check sample's features,only one feature value"
return ((features[0],),)
# 由于需要返回二分结果,所以每个分支至少需要一个特征值,所以要从所有的特征组合中选取1个以上的组合
# itertools的combinations 函数可以返回一个列表选多少个元素的组合结果,例如combinations(list,2)返回的列表元素选2个的组合
# 我们需要选择1-(count-1)的组合
featureIndex = range(count)
featureIndex.pop(0)
combinationsList = []
resList=[]
# 遍历所有的组合
for i in featureIndex:
temp_combination = list(combinations(features, len(features[0:i])))
combinationsList.extend(temp_combination)
combiLen = len(combinationsList)
# 每次组合的顺序都是一致的,并且也是对称的,所以我们取首尾组合集合
# zip函数提供了两个列表对应位置组合的功能
resList = zip(combinationsList[0:combiLen/2], combinationsList[combiLen-1:combiLen/2-1:-1])
return resList
# 返回最好的特征以及二分特征值
def chooseBestFeatureToSplit(dataSet):
numFeatures = len(dataSet[0]) - 1 #
bestStDev = inf; bestFeature = -1;bestBinarySplit=()
for i in range(numFeatures): #遍历特征
featList = [example[i] for example in dataSet]#得到特征列
uniqueVals = list(set(featList)) #从特征列获取该特征的特征值的set集合
# 三个特征值的二分结果:
# [(('young',), ('old', 'middle')), (('old',), ('young', 'middle')), (('middle',), ('young', 'old'))]
for split in featuresplit(uniqueVals):
StDev = 0.0
if len(split)==1:
continue
(left,right)=split
# print split,
# 对于每一个可能的二分结果计算gini增益
# 左增益
left_subDataSet = splitDataSet(dataSet, i, left)
left_prob = len(left_subDataSet)/float(len(dataSet))
S,u = calStDev(left_subDataSet)
StDev += left_prob * S
# 右增益
right_subDataSet = splitDataSet(dataSet, i, right)
right_prob = len(right_subDataSet)/float(len(dataSet))
S,u = calStDev(right_subDataSet)
StDev += right_prob * S
# print StDev
if (StDev < bestStDev): #比较是否是最好的结果
bestStDev = StDev #记录最好的结果和最好的特征
bestFeature = i
bestBinarySplit=(left,right)
return bestFeature,bestBinarySplit,bestStDev def majorityCnt(classList):
classCount={}
for vote in classList:
if vote not in classCount.keys(): classCount[vote] = 0
classCount[vote] += 1
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0] def createTree(dataSet,labels,originalS):
classList = [example[-1] for example in dataSet]
# print dataSet
if classList.count(classList[0]) == len(classList):
return classList[0]#所有的类别都一样,就不用再划分了
if len(dataSet) == 1: #如果没有继续可以划分的特征,就多数表决决定分支的类别
return majorityCnt(classList)
bestFeat,bestBinarySplit,bestStDev = chooseBestFeatureToSplit(dataSet)
if bestStDev < 0.05*originalS:
return 1.0*sum(classList)/len(classList)
# print bestFeat,bestBinarySplit,labels
bestFeatLabel = labels[bestFeat]
if bestFeat==-1:
return majorityCnt(classList)
myTree = {bestFeatLabel:{}}
featValues = [example[bestFeat] for example in dataSet]
uniqueVals = list(set(featValues))
for value in bestBinarySplit:
subLabels = labels[:] # #拷贝防止其他地方修改
if len(value)<2:
del(subLabels[bestFeat])
myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels,originalS)
return myTree filename="regression_sample"
dataSet=[];labels=[];
with open(filename) as f:
for line in f:
fields=line.strip("\n").split("\t")
t=fields[0:-1]
t.append(int(fields[-1]))
dataSet.append(t)
labels=["outlook","temperature","humidity","windy"]
# print dataSet
originalS,u=calStDev(dataSet)
# print originalS,u
tree= createTree(dataSet,labels,originalS)
print tree

cart中回归树的原理和实现的更多相关文章

  1. 回归树的原理及Python实现

    大名鼎鼎的 GBDT 算法就是用回归树组合而成的.本文就回归树的基本原理进行讲解,并手把手.肩并肩地带您实现这一算法. 1. 原理篇 1.1 最简单的模型 如果预测某个连续变量的大小,最简单的模型之一 ...

  2. 连续值的CART(分类回归树)原理和实现

    上一篇我们学习和实现了CART(分类回归树),不过主要是针对离散值的分类实现,下面我们来看下连续值的cart分类树如何实现 思考连续值和离散值的不同之处: 二分子树的时候不同:离散值需要求出最优的两个 ...

  3. 机器学习技法-决策树和CART分类回归树构建算法

    课程地址:https://class.coursera.org/ntumltwo-002/lecture 重要!重要!重要~ 一.决策树(Decision Tree).口袋(Bagging),自适应增 ...

  4. CART(分类回归树)原理和实现

    前面我们了解了决策树和adaboost的决策树墩的原理和实现,在adaboost我们看到,用简单的决策树墩的效果也很不错,但是对于更多特征的样本来说,可能需要很多数量的决策树墩 或许我们可以考虑使用更 ...

  5. CART分类与回归树与GBDT(Gradient Boost Decision Tree)

    一.CART分类与回归树 资料转载: http://dataunion.org/5771.html        Classification And Regression Tree(CART)是决策 ...

  6. 决策树的剪枝,分类回归树CART

    决策树的剪枝 决策树为什么要剪枝?原因就是避免决策树“过拟合”样本.前面的算法生成的决策树非常的详细而庞大,每个属性都被详细地加以考虑,决策树的树叶节点所覆盖的训练样本都是“纯”的.因此用这个决策树来 ...

  7. 机器学习之分类回归树(python实现CART)

    之前有文章介绍过决策树(ID3).简单回顾一下:ID3每次选取最佳特征来分割数据,这个最佳特征的判断原则是通过信息增益来实现的.按照某种特征切分数据后,该特征在以后切分数据集时就不再使用,因此存在切分 ...

  8. 分类-回归树模型(CART)在R语言中的实现

    分类-回归树模型(CART)在R语言中的实现 CART模型 ,即Classification And Regression Trees.它和一般回归分析类似,是用来对变量进行解释和预测的工具,也是数据 ...

  9. CART(分类回归树)

    1.简单介绍 线性回归方法可以有效的拟合所有样本点(局部加权线性回归除外).当数据拥有众多特征并且特征之间关系十分复杂时,构建全局模型的想法一个是困难一个是笨拙.此外,实际中很多问题为非线性的,例如常 ...

随机推荐

  1. android如何播放和录制音频

    视频录制功能正在走来,在Androidsdk中有与之相关的类:android.media.MediaRecorder.当然,因为模拟器上没有提供必要的硬件设施,所以在学习过程中并不能实现.Media能 ...

  2. VMware Workstation安装RedHat Linux 9

    RedHatLinux是目前世界上使用最多的Linux操作系统.因为它具备最好的图形界面无论是安装.配置还是使用都十分方便.下面我将介绍使用VMware Workstation安装RedHat Lin ...

  3. SK-Learn使用NMF(非负矩阵分解)和LDA(隐含狄利克雷分布)进行话题抽取

    英文链接:http://scikit-learn.org/stable/auto_examples/applications/topics_extraction_with_nmf_lda.html 这 ...

  4. 常用的sql脚本 游标遍历操作

    Declare @id int DECLARE cursor_data CURSOR FOR --这里是取得数据源 OPEN cursor_data FETCH FROM cursor_data IN ...

  5. C# WinForm 技巧八:界面开发之“WeifenLuo.WinFormsUI.Docking+OutLookBar” 使用

    概述      最近几天一直在关注WinFrom方面的文章主要还是园子里伍华聪的博客,在看看我们自己写的项目差不忍赌啊,有想着提炼一下项目的公共部分,公共部分有分为 界面,类库两方面,今天主要是把界面 ...

  6. 解决企业In-House安装APP需HTTPS支持的问题(转载)

    同事写的一篇文章,感觉不错,转过来. 解决企业In-House安装APP需HTTPS支持的问题 问题背景: 能否通过应用服务器发布企业应用: 解决iOS7.1后,发布地址必须为HTTPS服务器. 写作 ...

  7. Vim 练级攻略

    以下的文章翻译自<Learn Vim Progressively>,我认为这是给新手最好的VIM的升级教程了,没有列举全部的命令,仅仅是列举了那些最实用的命令. 很不错. -------- ...

  8. Jdbc如何从PostgreSql读取海量数据?PostgreSql源代码分析纪录

    前言: 最近做数据同步,需要从PostgreSql获取数据,发现一旦数据比较多,那么读取的速度非常慢,并且内存占用特别多&GC不掉. 代码样例: 为了方便讲解,下面写了事例代码,从b2c_or ...

  9. Android开发在路上:少去踩坑,多走捷径

    转自:http://djt.qq.com/article/view/1193   最近一朋友提了几个Android问题让我帮忙写个小分享,我觉得对新人还是挺有帮助的,所以有了这个小分享. 1.目前, ...

  10. using-ef-code-first-with-an-existing-database

    http://weblogs.asp.net/scottgu/using-ef-code-first-with-an-existing-database http://weblogs.asp.net/ ...