接上篇
    CART算法的全称是Classification And Regression Tree,采用的是Gini指数(选Gini指数最小的特征s)作为分裂标准,同时它也是包含后剪枝操作。ID3算法和C4.5算法虽然在对训练样本集的学习中可以尽可能多地挖掘信息,但其生成的决策树分支较大,规模较大。为了简化决策树的规模,提高生成决策树的效率,就出现了根据GINI系数来选择测试属性的决策树算法CART。

CART分类与回归树本质上是一样的,构建过程都是逐步分割特征空间,预测过程都是从根节点开始一层一层的判断直到叶节点给出预测结果。只不过分类树给出离散值,而回归树给出连续值(通常是叶节点包含样本的均值),另外分类树基于Gini指数选取分割点,而回归树基于平方误差选取分割点。

6.CART分类树

基尼指数,分类问题中,假设有K个类,样本点属于第k类的概率为pkp_{k}pk​,则概率分布的基尼指数定义为:
Gini(p)=1−∑k=1Kpk(1−pk)=1−∑k=1Kpk2Gini(p)=1-\sum_{k=1}^{K}p_k(1-p_k)=1-\sum_{k=1}^{K}p_k^2Gini(p)=1−∑k=1K​pk​(1−pk​)=1−∑k=1K​pk2​

如果样本集合D根据特征A是否取某一肯值aaa被分割成D1D_1D1​和D2D_2D2​两部分,即:
D1=(x,y)∈D∣A(x)=a,D2=D−D1D_1={(x,y)∈D|A(x)=a} , D_2=D-D_1D1​=(x,y)∈D∣A(x)=a,D2​=D−D1​

则在特征A的条件下,集合D的基尼指数定义为:
Gini(D,A)=∣D1∣∣D∣Gini(D1)+∣D2∣∣D∣Gini(D2)Gini(D,A)=\frac{|D_1|}{|D|}Gini(D_1) + \frac{|D_2|}{|D|}Gini(D_2)Gini(D,A)=∣D∣∣D1​∣​Gini(D1​)+∣D∣∣D2​∣​Gini(D2​)
基尼指数Gini(D)Gini(D)Gini(D)表示D的不确定性,基尼指数Gini(D,A)Gini(D,A)Gini(D,A)表示A=aA=aA=a分割后集合D的不确定性,基尼指数值越大,样本集合的不确定性就越大,与熵类似。

CART分类树算法逻辑,《统计学习方法》李航,P70-71页:

按传入数据最后一列y值求gini指数

# 计算传入数据的Gini指数
def calcGini(dataSet):#dataSet=dataSet[list(dataSet[:,0]=='青年')]# 获得y中分类标签的唯一值y_lables = np.unique(dataSet[: , -1])y_counts=len(dataSet) # y总数据条数y_p={}             # y中每一个分类的概率,字典初始化为空,y分类数是不定的,按字典存储更方便取值gini=1.0for y_lable in y_lables:y_p[y_lable]=len(dataSet[dataSet[:, -1]==y_lable])/y_counts  # y中每一个分类的概率(其实就是频率)gini-=y_p[y_lable]**2return gini

切分数据,每一列x找一个最优的特征进行划分

#划分数据集
def splitDataSet(dataSet, i, value,types=1):#dataSet[list(dataSet[:,0]!='青年')]if types==1: # 使用此列特征中的value进行划分数据subDataSet=dataSet[list(dataSet[:,i]==value)]  # 按照数据x第i列==value即可判断,不需要像《机器学习实战》书里写的那么复杂subDataSet = np.array(subDataSet)           # 强制转换为array类型elif types==2: # 使用此列特征中的不等于value的进行划分数据subDataSet=dataSet[list(dataSet[:,i]!=value)]  # 按照数据x第i列==value即可判断,不需要像《机器学习实战》书里写的那么复杂subDataSet = np.array(subDataSet)           # 强制转换为array类型return subDataSet ,len(subDataSet)

遍历所有x特征列中的所有特征,寻找最优划分特征

# 计算Gini指数,选择最好的特征划分数据集,即返回最佳特征下标及传入数据集各列的Gini指数
def chooseBestFeature(dataSet,types='Gini'):numTotal=dataSet.shape[0]              # 记录本数据集总条数numFeatures = len(dataSet[0]) - 1      # 最后一列为y,计算x特征列数bestFeature = -1                       # 初始化参数,记录最优特征列i,下标从0开始columnFeaGini={}                       # 初始化参数,记录每一列x的每一种特征的基尼 Gini(D,A)for i in range(numFeatures):           # 遍历所有x特征列# i=2prob = {}                          # 按x列计算各个分类的概率featList = list(dataSet[:,i])      # 取这一列x中所有数据,转换为list类型prob=dict(Counter(featList))       # 使用Counter函数计算这一列x各特征数量for value in prob.keys():          # 循环这一列的特征,计算H(D|A)# value='是'feaGini = 0.0bestFlag = 1.00001  # 对某一列x中,会出现x=是,y=是的特殊情况,这种情况下按“是”、“否”切分数据得到的Gini都一样,设置此参数将所有特征都乘以一个比1大一点点的值,但按某特征划分Gini为0时,设置为1subDataSet1,sublen1 = splitDataSet(dataSet, i, value, 1)  # 获取切分后的数据subDataSet2,sublen2 = splitDataSet(dataSet, i, value, 2)if (sublen1/numTotal) * calcGini(subDataSet1)==0: # 判断按此特征划分Gini值是否为0(全部为一类)bestFlag = 1 feaGini += (sublen1/numTotal) * calcGini(subDataSet1) + (sublen2/numTotal) * calcGini(subDataSet2)columnFeaGini['%d_%s'%(i,value)]=feaGini*bestFlagbestFeature=min(columnFeaGini,key=columnFeaGini.get) # 找到最小的Gini指数益对应的数据列return bestFeature,columnFeaGini

CART分类树创建主函数,递归调用产生整颗决策树

def createTree(dataSet,features,types='Gini'):"""输入:训练数据集D,特征集A,阈值ε输出:决策树T"""y_lables = np.unique(dataSet[: , -1])#1、如果数据集D中的所有实例都属于同一类label(Ck),则T为单节点树,并将类label(Ck)作为该结点的类标记,返回Tif len(set(y_lables)) == 1:return y_lables[0]#2、若特征集A=空,则T为单节点,并将数据集D中实例树最大的类label(Ck)作为该节点的类标记,返回Tif len(dataSet[0]) == 1:labelCount = {}labelCount=dict(Counter(y_lables))return max(labelCount,key=labelCount.get)#3、否则,按CART算法就计算特征集A中各特征对数据集D的Gini,选择Gini指数最小的特征bestFeature(Ag)进行划分bestFeature,columnFeaGini=chooseBestFeature(dataSet,types) bestFeatureLable = features[int(bestFeature.split('_')[0])]    #最佳特征decisionTree = {bestFeatureLable:{}}        #构建树,以Gini指数最小的特征bestFeature为子节点del(features[int(bestFeature.split('_')[0])])                  #该特征已最为子节点使用,则删除,以便接下来继续构建子树#使用beatFeature进行划分,划分产生2各节点,成树T,返回Ty_lables_split=dataSet[list(dataSet[:,int(bestFeature.split('_')[0])]==bestFeature.split('_')[1])][:,-1] # 获取按此划分后y数据列表y_lables_grp=dict(Counter(y_lables_split)) # 统计最优划分应该属于哪个i叶子节点“是”、“否”y_leaf=max(y_lables_grp,key=y_lables_grp.get) # 获得划分后出现概率最大的y分类decisionTree[bestFeatureLable][bestFeature.split('_')[1]]= y_leaf # 设定左枝叶子值#4、删除此最优划分数据x列,使用其他x列数据,递归地调用步1-3,得到子树Ti,返回TidataSetNew= np.delete(dataSet,int(bestFeature.split('_')[0]),axis=1) # 删除此最优划分x列,使用剩余的x列进行数据划分subFeatures = features[:]# 判断右枝类型,划分后的左右枝“是”、“否”是不一定的,所以这里进行判断y1=y_lables[0] # CART树y只能有2个分类y2=y_lables[1] if y_leaf==y1:decisionTree[bestFeatureLable][y2]= {}decisionTree[bestFeatureLable][y2] = createTree(dataSetNew, subFeatures,types)elif y_leaf==y2:decisionTree[bestFeatureLable][y1]= {}decisionTree[bestFeatureLable][y1] = createTree(dataSetNew, subFeatures,types)return decisionTree

cart决策树结果验证,计算结果与《统计学习方法》李航,P71页一致。

cart决策树及画图结果:

7.CART回归树

CART回归树样本空间细分成若干子空间,子空间内样本的输出y(连续值)的均值即为该子空间内的预测值。故对于输入X为一维时,预测结果可表示为阶梯函数。
评估方式采用平方误差:yi 属于某个数据集,c为该数据上输出向量y的均值。
err=∑(yi−c)err=\sum(y_i-c)err=∑(yi​−c)

CART回归树算法逻辑,《统计学习方法》李航,P69页:

最小二乘损失

def err(dataSet):#return sum((dataSet[:,-1]- dataSet[:,-1].mean())**2) # 最原始的写法return np.var(dataSet[:,-1])*dataSet.shape[0]  #均方差*数据总条数

划分数据集,按出入的数据列fea,数据值value将数据划分为两部分

def splitDataSet(dataSet, fea, value):dataSet1=dataSet[dataSet[:,fea]<=value]dataSet2=dataSet[dataSet[:,fea]>value]return dataSet1,dataSet2

#选择最好的特征划分数据集,min_sample每次划分后每部分最少的数据条数,epsilon误差下降阈值,值越小划分的决策树越深

def chooseBestFeature(dataSet,min_sample=4,epsilon=0.5):features=dataSet.shape[1]-1   # x特征列数量sErr=err(dataSet) # 整个数据集的损失minErr=np.infbestColumn = 0 # 划分最优列bestValue = 0  # 划分最优的值nowErr=0       # 当前平方误差if len(np.unique(dataSet[:,-1].T.tolist())) == 1: # 数据全是一类的情况下 返回return None, np.mean(dataSet[:,-1])for fea in range(0,features): # 按x特征列循环for row in range(0,dataSet.shape[0]): # 遍历每行数据,寻找最优划分dataSet1,dataSet2=splitDataSet(dataSet, fea,dataSet[row,fea]) # 获得切分后的数据if len(dataSet1) < min_sample or len(dataSet2) < min_sample:  # 按行遍历时总会有一些划分得到的集合不满足最小数据条数约束,跳过此类划分continuenowErr=err(dataSet1)+err(dataSet2) # 计算当前划分的平方误差#print('fea:',fea,'row:',row,'datavalue',dataSet[row,fea],'nowErr',nowErr)if nowErr<minErr: # 判断获得最优切分值minErr=nowErrbestColumn=feabestValue=dataSet[row,fea]#print('fea',fea,'minErr',minErr,'bestColumn',bestColumn,'bestValue',bestValue)if (sErr - minErr) < epsilon: # 当前误差下降较小时,返回return None, np.mean(dataSet[:,-1])# 当前最优划分集合dataSet1,dataSet2=splitDataSet(dataSet, bestColumn,bestValue)if len(dataSet1) < min_sample or len(dataSet2) < min_sample: # 如果划分的数据集很小,返回return None, np.mean(dataSet[:,-1])return bestColumn,bestValue

CART回归树控制主函数,递归调用产生整颗树

def createTree(dataSet):"""输入:训练数据集D,特征集A,阈值ε输出:决策树T"""bestColumn,bestValue=chooseBestFeature(dataSet)if bestColumn == None:  # 所有列均遍历完毕,返回return bestValueretTree = {}  # 决策树 retTree['spCol'] = bestColumn # 最优分割列retTree['spVal'] = bestValue  # 最优分割值lSet, rSet = splitDataSet(dataSet, bestColumn,bestValue) # 按当前最优分割列级值划分为左右2枝retTree['left'] = createTree(lSet)  # 迭代继续划分左枝retTree['right'] = createTree(rSet) # 迭代继续划分右枝return retTree

CART回归树输出结果:

CART分类树完整代码:

# -*- coding: utf-8 -*-
"""@Time    : 2018/11/16 09:58@Author  : hanzi5@Email   : hanzi5@yeah.net@File    : cart_classification.py@Software: PyCharm
"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
from collections import Countermatplotlib.rcParams['font.family']='SimHei'  # 用来正常显示中文
plt.rcParams['axes.unicode_minus']=False  # 用来正常显示负号decisionNode = dict(boxstyle="sawtooth", fc="0.8")
leafNode = dict(boxstyle="round4", fc="0.8")
arrow_args = dict(arrowstyle="<-")# 计算传入数据的Gini指数
def calcGini(dataSet):#dataSet=dataSet[list(dataSet[:,0]=='青年')]# 获得y中分类标签的唯一值y_lables = np.unique(dataSet[: , -1])y_counts=len(dataSet) # y总数据条数y_p={}             # y中每一个分类的概率,字典初始化为空,y分类数是不定的,按字典存储更方便取值gini=1.0for y_lable in y_lables:y_p[y_lable]=len(dataSet[dataSet[:, -1]==y_lable])/y_counts  # y中每一个分类的概率(其实就是频率)gini-=y_p[y_lable]**2return gini# 计算Gini指数的另一种写法
def getGini(dataSet):# 计算基尼指数c = Counter(dataSet[:,-1])ret=1 - sum([(val / dataSet[:,-1].shape[0]) ** 2 for val in c.values()])return ret#划分数据集
def splitDataSet(dataSet, i, value,types=1):#dataSet[list(dataSet[:,0]!='青年')]if types==1: # 使用此列特征中的value进行划分数据subDataSet=dataSet[list(dataSet[:,i]==value)]  # 按照数据x第i列==value即可判断,不需要像《机器学习实战》书里写的那么复杂subDataSet = np.array(subDataSet)           # 强制转换为array类型elif types==2: # 使用此列特征中的不等于value的进行划分数据subDataSet=dataSet[list(dataSet[:,i]!=value)]  # 按照数据x第i列==value即可判断,不需要像《机器学习实战》书里写的那么复杂subDataSet = np.array(subDataSet)           # 强制转换为array类型return subDataSet ,len(subDataSet)# 计算Gini指数,选择最好的特征划分数据集,即返回最佳特征下标及传入数据集各列的Gini指数
def chooseBestFeature(dataSet,types='Gini'):numTotal=dataSet.shape[0]              # 记录本数据集总条数numFeatures = len(dataSet[0]) - 1      # 最后一列为y,计算x特征列数bestFeature = -1                       # 初始化参数,记录最优特征列i,下标从0开始columnFeaGini={}                       # 初始化参数,记录每一列x的每一种特征的基尼 Gini(D,A)for i in range(numFeatures):           # 遍历所有x特征列# i=2prob = {}                          # 按x列计算各个分类的概率featList = list(dataSet[:,i])      # 取这一列x中所有数据,转换为list类型prob=dict(Counter(featList))       # 使用Counter函数计算这一列x各特征数量for value in prob.keys():          # 循环这一列的特征,计算H(D|A)# value='是'feaGini = 0.0bestFlag = 1.00001  # 对某一列x中,会出现x=是,y=是的特殊情况,这种情况下按“是”、“否”切分数据得到的Gini都一样,设置此参数将所有特征都乘以一个比1大一点点的值,但按某特征划分Gini为0时,设置为1subDataSet1,sublen1 = splitDataSet(dataSet, i, value, 1)  # 获取切分后的数据subDataSet2,sublen2 = splitDataSet(dataSet, i, value, 2)if (sublen1/numTotal) * calcGini(subDataSet1)==0: # 判断按此特征划分Gini值是否为0(全部为一类)bestFlag = 1 feaGini += (sublen1/numTotal) * calcGini(subDataSet1) + (sublen2/numTotal) * calcGini(subDataSet2)columnFeaGini['%d_%s'%(i,value)]=feaGini*bestFlagbestFeature=min(columnFeaGini,key=columnFeaGini.get) # 找到最小的Gini指数益对应的数据列return bestFeature,columnFeaGinidef createTree(dataSet,features,types='Gini'):"""输入:训练数据集D,特征集A,阈值ε输出:决策树T"""y_lables = np.unique(dataSet[: , -1])#1、如果数据集D中的所有实例都属于同一类label(Ck),则T为单节点树,并将类label(Ck)作为该结点的类标记,返回Tif len(set(y_lables)) == 1:return y_lables[0]#2、若特征集A=空,则T为单节点,并将数据集D中实例树最大的类label(Ck)作为该节点的类标记,返回Tif len(dataSet[0]) == 1:labelCount = {}labelCount=dict(Counter(y_lables))return max(labelCount,key=labelCount.get)#3、否则,按CART算法就计算特征集A中各特征对数据集D的Gini,选择Gini指数最小的特征bestFeature(Ag)进行划分bestFeature,columnFeaGini=chooseBestFeature(dataSet,types) bestFeatureLable = features[int(bestFeature.split('_')[0])]    #最佳特征decisionTree = {bestFeatureLable:{}}        #构建树,以Gini指数最小的特征bestFeature为子节点del(features[int(bestFeature.split('_')[0])])                  #该特征已最为子节点使用,则删除,以便接下来继续构建子树#使用beatFeature进行划分,划分产生2各节点,成树T,返回Ty_lables_split=dataSet[list(dataSet[:,int(bestFeature.split('_')[0])]==bestFeature.split('_')[1])][:,-1] # 获取按此划分后y数据列表y_lables_grp=dict(Counter(y_lables_split)) # 统计最优划分应该属于哪个i叶子节点“是”、“否”y_leaf=max(y_lables_grp,key=y_lables_grp.get) # 获得划分后出现概率最大的y分类decisionTree[bestFeatureLable][bestFeature.split('_')[1]]= y_leaf # 设定左枝叶子值#4、删除此最优划分数据x列,使用其他x列数据,递归地调用步1-3,得到子树Ti,返回TidataSetNew= np.delete(dataSet,int(bestFeature.split('_')[0]),axis=1) # 删除此最优划分x列,使用剩余的x列进行数据划分subFeatures = features[:]# 判断右枝类型,划分后的左右枝“是”、“否”是不一定的,所以这里进行判断y1=y_lables[0] # CART树y只能有2个分类y2=y_lables[1] if y_leaf==y1:decisionTree[bestFeatureLable][y2]= {}decisionTree[bestFeatureLable][y2] = createTree(dataSetNew, subFeatures,types)elif y_leaf==y2:decisionTree[bestFeatureLable][y1]= {}decisionTree[bestFeatureLable][y1] = createTree(dataSetNew, subFeatures,types)return decisionTree####以下是用来画图的完全复制的《机器学习实战》第三章的内容,不感兴趣的可以略过#############################################
def getNumLeafs(myTree):numLeafs = 0firstStr = list(myTree.keys())[0]secondDict = myTree[firstStr]for key in secondDict.keys():if type(secondDict[key]).__name__=='dict':#test to see if the nodes are dictonaires, if not they are leaf nodesnumLeafs += getNumLeafs(secondDict[key])else:   numLeafs +=1return numLeafsdef getTreeDepth(myTree):maxDepth = 0firstStr = list(myTree.keys())[0]#myTree.keys()[0]secondDict = myTree[firstStr]for key in secondDict.keys():if type(secondDict[key]).__name__=='dict':#test to see if the nodes are dictonaires, if not they are leaf nodesthisDepth = 1 + getTreeDepth(secondDict[key])else:   thisDepth = 1if thisDepth > maxDepth: maxDepth = thisDepthreturn maxDepthdef plotNode(nodeTxt, centerPt, parentPt, nodeType):createPlot.ax1.annotate(nodeTxt, xy=parentPt,  xycoords='axes fraction',xytext=centerPt, textcoords='axes fraction',va="center", ha="center", bbox=nodeType, arrowprops=arrow_args )def plotMidText(cntrPt, parentPt, txtString):xMid = (parentPt[0]-cntrPt[0])/2.0 + cntrPt[0]yMid = (parentPt[1]-cntrPt[1])/2.0 + cntrPt[1]createPlot.ax1.text(xMid, yMid, txtString, va="center", ha="center", rotation=30)def plotTree(myTree, parentPt, nodeTxt):#if the first key tells you what feat was split onnumLeafs = getNumLeafs(myTree)  #this determines the x width of this tree#depth = getTreeDepth(myTree)firstStr = list(myTree.keys())[0]#myTree.keys()[0]     #the text label for this node should be thiscntrPt = (plotTree.xOff + (1.0 + float(numLeafs))/2.0/plotTree.totalW, plotTree.yOff)plotMidText(cntrPt, parentPt, nodeTxt)plotNode(firstStr, cntrPt, parentPt, decisionNode)secondDict = myTree[firstStr]plotTree.yOff = plotTree.yOff - 1.0/plotTree.totalDfor key in secondDict.keys():if type(secondDict[key]).__name__=='dict':#test to see if the nodes are dictonaires, if not they are leaf nodes   plotTree(secondDict[key],cntrPt,str(key))        #recursionelse:   #it's a leaf node print the leaf nodeplotTree.xOff = plotTree.xOff + 1.0/plotTree.totalWplotNode(secondDict[key], (plotTree.xOff, plotTree.yOff), cntrPt, leafNode)plotMidText((plotTree.xOff, plotTree.yOff), cntrPt, str(key))plotTree.yOff = plotTree.yOff + 1.0/plotTree.totalD
#if you do get a dictonary you know it's a tree, and the first element will be another dictdef createPlot(myTree):fig = plt.figure(1, facecolor='white')fig.clf()axprops = dict(xticks=[], yticks=[])createPlot.ax1 = plt.subplot(111, frameon=False, **axprops)    #no ticks#createPlot.ax1 = plt.subplot(111, frameon=False) #ticks for demo puropses plotTree.totalW = float(getNumLeafs(myTree))plotTree.totalD = float(getTreeDepth(myTree))plotTree.xOff = -0.5/plotTree.totalW; plotTree.yOff = 1.0;plotTree(myTree, (0.5,1.0), '')plt.show()
####画图结束,不感兴趣的可以略过#############################################if __name__ == "__main__":  #读入数据,《统计学习方法》李航,P59,表5.1df_data=pd.read_csv('D:/python_data/loan_application.csv')features = list(df_data.columns[1:-1]) # x的表头dataSet=np.array(df_data.values[:,1:]) # 数据处理为numpy.array类型,其实pandas.Dataframe类型更方便计算# 结果验证,计算结果与《统计学习方法》李航,P71页一致。bestFeature,columnFeaGini=chooseBestFeature(dataSet,'Gini')print('\nbestFeature:',bestFeature,'\nGini(D,A):',columnFeaGini)dt_Gini = createTree(dataSet, features,'Gini')   #建立决策树,CART分类树print( 'CART分类树:\n',dt_Gini)# 画出决策树createPlot(dt_Gini)

CART回归树完整代码:

# -*- coding: utf-8 -*-
"""@Time    : 2018/11/19 14:45@Author  : hanzi5@Email   : hanzi5@yeah.net@File    : cart_reg.py@Software: PyCharm
"""import numpy as np
import pandas as pd
import matplotlib.pyplot as plt# 最小二乘损失
def err(dataSet):#return sum((dataSet[:,-1]- dataSet[:,-1].mean())**2) # 最原始的写法return np.var(dataSet[:,-1])*dataSet.shape[0]  #均方差*数据总条数#划分数据集,按出入的数据列fea,数据值value将数据划分为两部分
def splitDataSet(dataSet, fea, value):dataSet1=dataSet[dataSet[:,fea]<=value]dataSet2=dataSet[dataSet[:,fea]>value]return dataSet1,dataSet2# 选择最好的特征划分数据集,min_sample每次划分后每部分最少的数据条数,epsilon误差下降阈值,值越小划分的决策树越深
def chooseBestFeature(dataSet,min_sample=4,epsilon=0.5):features=dataSet.shape[1]-1   # x特征列数量sErr=err(dataSet) # 整个数据集的损失minErr=np.infbestColumn = 0 # 划分最优列bestValue = 0  # 划分最优的值nowErr=0       # 当前平方误差if len(np.unique(dataSet[:,-1].T.tolist())) == 1: # 数据全是一类的情况下 返回return None, np.mean(dataSet[:,-1])for fea in range(0,features): # 按x特征列循环for row in range(0,dataSet.shape[0]): # 遍历每行数据,寻找最优划分dataSet1,dataSet2=splitDataSet(dataSet, fea,dataSet[row,fea]) # 获得切分后的数据if len(dataSet1) < min_sample or len(dataSet2) < min_sample:  # 按行遍历时总会有一些划分得到的集合不满足最小数据条数约束,跳过此类划分continuenowErr=err(dataSet1)+err(dataSet2) # 计算当前划分的平方误差#print('fea:',fea,'row:',row,'datavalue',dataSet[row,fea],'nowErr',nowErr)if nowErr<minErr: # 判断获得最优切分值minErr=nowErrbestColumn=feabestValue=dataSet[row,fea]#print('fea',fea,'minErr',minErr,'bestColumn',bestColumn,'bestValue',bestValue)if (sErr - minErr) < epsilon: # 当前误差下降较小时,返回return None, np.mean(dataSet[:,-1])# 当前最优划分集合dataSet1,dataSet2=splitDataSet(dataSet, bestColumn,bestValue)if len(dataSet1) < min_sample or len(dataSet2) < min_sample: # 如果划分的数据集很小,返回return None, np.mean(dataSet[:,-1])return bestColumn,bestValuedef createTree(dataSet):"""输入:训练数据集D,特征集A,阈值ε输出:决策树T"""bestColumn,bestValue=chooseBestFeature(dataSet)if bestColumn == None:  # 所有列均遍历完毕,返回return bestValueretTree = {}  # 决策树 retTree['spCol'] = bestColumn # 最优分割列retTree['spVal'] = bestValue  # 最优分割值lSet, rSet = splitDataSet(dataSet, bestColumn,bestValue) # 按当前最优分割列级值划分为左右2枝retTree['left'] = createTree(lSet)  # 迭代继续划分左枝retTree['right'] = createTree(rSet) # 迭代继续划分右枝return retTreeif __name__ == '__main__':# 使用sin函数随机产生x,y数据X_data_raw = np.linspace(-3, 3, 50)np.random.shuffle(X_data_raw)  # 随机打乱数据y_data = np.sin(X_data_raw)    # 产生数据yx = np.transpose([X_data_raw]) # 将x进行转换y = y_data + 0.1 * np.random.randn(y_data.shape[0]) # 产生数据y,增加随机噪声dataSet=np.column_stack((x,y.reshape((-1,1))))      # 将x与y进行合并#    data=pd.read_table('D:/python_data/ex0.txt',header=None)
#    dataSet=data.valuesmytree=createTree(dataSet) print('mytree\n',mytree)

注意,以上实现的CART分类树与CART回归树均没有进行减枝操作。

参考资料:
1、Machine-Learning-With-Python
2、《机器学习实战》Peter Harrington著
3、《机器学习》西瓜书,周志华著
4、 斯坦福大学公开课 :机器学习课程
5、机器学习视频,邹博
6、《统计学习方法》李航
7、《机器学习实战》基于信息论的三种决策树算法(ID3,C4.5,CART)
8、分类回归——CART分类与回归以及Python实现

Python实现决策树2(CART分类树及CART回归树)相关推荐

  1. Python实现决策树(Decision Tree)分类

    关于决策树的简介可以参考: http://blog.csdn.net/fengbingchun/article/details/78880934 在  https://machinelearningm ...

  2. R语言笔记之树模型(回归树和决策树)

    回归树过程: 例:有10名学生,他们的身高分布如下: R1: 女生(7):156,167,165,163,160,170,160 R2: 男生(3):172,180,176 那么,落入R1的样本均值为 ...

  3. wpf展开树节点_回归树分析与sklearn决策树案例,来玩一会

    摘要: 决策树是非常基础的算法,其不仅能够进行分类还可以进行回归处理,也就是回归树.要想提高决策树的性能还需要做好剪枝的工作. 关键词: 回归树,剪枝 1 回归树 之前已经介绍过决策树的基本理论了:这 ...

  4. 树模型之回归树,模型树,树剪枝

    在前面决策树的介绍中,我们使用ID3算法来构建决策树:这里我们使用CART算法来构建回归树和模型树.ID3算法是每次选取当前最佳的特征来分割数据,并按照该特征的所有可能取值来区分.比如,如果一个特征有 ...

  5. 决策树之CART 算法(回归树,分类树)

    CART 算法,英文全称叫做 Classification And Regression Tree,中文叫做分类回归树. ID3 和 C4.5 算法可以生成二叉树或多叉树,而 CART 只支持二叉树. ...

  6. 决策树6:分类与回归树CART

    0x01 概念介绍 1.1 CART算法 CART算法:Classification And Regression Tree.顾名思义,CART算法既可以用于创建分类树(Classification ...

  7. 监督学习 | CART 分类回归树原理

    文章目录 CART 算法 1. CART 生成 1.1 回归树生成 最小二乘回归树生成算法 1.2 分类树生成 基尼指数 CART 生成算法 参考文献 相关文章: 机器学习 | 目录 监督学习 | I ...

  8. 基于CART分类方法的决策树(机器学习)

    目录 一.实验内容 二.实验过程 1.算法思想 2.算法原理 3.算法分析 三.源程序代码 四.运行结果及分析 五.实验总结 一.实验内容 熟知决策树的概念和基本算法思想. 理解信息增益的计算方法,比 ...

  9. 机器学习--CART分类回归树

    目录 文章目录 目录 前言 1.CART回归树简介 2.剪枝策略 3.模型树 4.线性回归 回归树 模型树比较 前言 虽然许多问题都可以用线性方法取得良好的结果,但现实中也有许多问题是非线性的,用线性 ...

  10. 分类与回归树(CART)相关知识

    文章目录 CART算法 CART回归树生成 CART分类树的生成 连续值处理: 离散值处理: CART 剪枝 CART算法 分类与回归树(CART)是应用广泛的算法,同样由特征选择.树的生成及剪枝组成 ...

最新文章

  1. Javascript String类的属性及方法
  2. STM32 的 JLink 调试时「Flash Timeout」和「Flash Download Failed」问题解决
  3. 关于django的模板
  4. 2045 数学:排列组合
  5. 这是一个关于软件开发的博客。
  6. ssis 角本组件更新数据_使用SSIS脚本组件作为数据源
  7. 基于tensorflow深度学习的中文的命名实体识别
  8. Twitter数据抓取的方法(三)
  9. 基于SpringMVC国际化资源配置方式
  10. L3G4200D + ADXL345 卡尔曼滤波
  11. 谷歌io大会2019_Google IO 2012的前5个精选
  12. Scalar类-颜色类
  13. ES6基本的语法(十六) lterator
  14. CMS和G1的对比分析
  15. 2013 国家自然科学基金中标项目软件工程
  16. 小白程序员怎么由量变到质变写出高质量代码
  17. Tomcat打破双亲委派模型
  18. Wordpress整站迁移
  19. Math类的常用方法,进一法,退一法,四舍五入法,绝对值,随机数 ,平方根 xy的次方
  20. 盘点今年大数据创业:实力派能熬过寒冬

热门文章

  1. 计算机网络 | IPv6 | 什么是IPv6
  2. js09 - Dev Tools Domination
  3. oracle常用sql语句查询语句,Oracle常用sql语句
  4. 2019年图灵奖Edwin E. Catmull和Patrick M. Hanrahan简介
  5. 准考证丢失后如何查询四六级成绩
  6. 李宏毅2022机器学习hw4
  7. hw叠加层开还是不开_停用hw叠加层有什么用
  8. Python爬虫实战一之使用Beautiful Soup抓取百度招聘信息并存储excel文件
  9. 关于BigDecimal.ROUND_HALF_EVEN银行家算法
  10. 荣耀A55高调上市只为孤独求败?