目录

  • python实现
    • 分步
    • 源代码(全部)
  • 测试集1(鸢尾花集)
  • 测试集2(红酒品类数据集)
  • 总结

python实现

分步

  • 划分数据子集(注意区分离散特征值和连续特征值)
#获取数据子集,分类与回归的做法相同
#将数据集根据划分特征切分为两类
def split_dataset(data_x,data_y,fea_axis,fea_value):'''input:data_x(ndarry):特征值data_y(ndarry):标签值fea_axis(int):进行划分的特征编号(列数)fea_value(int):进行划分的特征对应特征值output:data_x[equal_Idx],data_y[equal_Idx](ndarry):特征值等于(大于等于)目标特征值的样本与标签data_x[nequal_Idx],data_y[nequal_Idx](ndarry):特征值不等于(小于)目标特征的样本与标签'''if  isinstance(fea_value,float): #如果特征值为浮点数(连续特征值),那么进行连续值离散化equal_Idx = np.where(data_x[:,fea_axis]>=fea_value) #找出特征值大于等于fea_alue的样本序号nequal_Idx = np.where(data_x[:,fea_axis]<fea_value) #找出特征值小于fea_alue的样本序号else:equal_Idx = np.where(data_x[:,fea_axis]==fea_value) #找出特征值等于fea_alue的样本序号nequal_Idx = np.where(data_x[:,fea_axis]!=fea_value) #找出特征值不等于fea_alue的样本序号return data_x[equal_Idx],data_y[equal_Idx],data_x[nequal_Idx],data_y[nequal_Idx]
  • 求解基尼系数(在该数据集相下,随机抽取两个样本,标签不同的概率)
#使用决策树进行分类需要用到
#求解基尼系数,即两个样本不属于同一标签的概率(二分类问题)
def cal_gini(data_y):'''input:data_y(ndarry):标签值output:gini(float):基尼指数'''m = len(data_y)  #全部样本的标签数量labels = np.unique(data_y) #获得不同种类的标签(去重)gini = 1.0  #最后返回的基尼指数for label in labels:ans = data_y[np.where(data_y[:]==label)].size/m  #该标签的出现概率gini -= ans*ans  #累减计算基尼指数(两两不同的总概率)return gini
  • 最优特征选取以及特征值划分(遍历计算每个特征下每个特征值的基尼系数,取最小值(纯度最高)进行划分标准)
#分类方法实现最优特征的选取以及特征值划分
def classify_get_best_fea(data_x,data_y):'''input:data_x(ndarry):特征值data_y(ndarry):标签值output:best_fea(int):最优特征best_fea_val(int):最优特征值'''m,n = np.shape(data_x)  #m,n分别为样本数以及特征属性数#初始化best_fea = -1best_fea_val = -1min_fea_gini = np.inffor i in range(n):  #遍历所有特征(列)feas = np.unique(data_x[:,i])  #获得该特征下所有特征值#分别以每个特征值为中心进行划分求基尼系数,找到使基尼系数最小的划分for j in feas:equal_data_x,equal_data_y,nequal_data_x,nequal_data_y = split_dataset(data_x,data_y,i,j)fea_gini = 0.0#计算该划分下的基尼系数fea_gini = len(equal_data_y)/m*cal_gini(equal_data_y)+len(nequal_data_y)/m*cal_gini(nequal_data_y)#如果该划分方式的基尼系数更小(纯度更高),那么直接进行更新if fea_gini<min_fea_gini:min_fea_gini = fea_ginibest_fea = ibest_fea_val = jreturn best_fea,best_fea_val
  • 创建分类决策树(使用递归的方法构建决策树字典,注意处理特殊情况:只有一类标签的情况,无特征的情况,当基尼系数过低时也可以中断划分)
#创建分类方法的决策树
def classify_create_tree(data_x,data_y,fea_label):'''input:data_x(ndarry):特征值data_y(ndarry):标签值fea_label(list):特征属性列表output:my_tree(dict):生成的CART分类树'''labels = np.unique(data_y)#只有一个标签的情况if len(labels)==1:return data_y[0]#特征集为0的情况,采用多数投票的方法if data_x.shape[1]==0:best_fea,best_fea_num = 0,0for label in labels:num = data_y[np.where(data_y==label)].sizeif num>best_fea_num:best_fea = labelbest_fea_num = numreturn best_feabest_fea,best_fea_val = classify_get_best_fea(data_x,data_y)best_fea_label = fea_label[best_fea]print(u"此时最优索引为:"+str(best_fea_label))my_tree = {best_fea_label:{}}#获得划分结果equal_data_x,equal_data_y,nequal_data_x,nequal_data_y = split_dataset(data_x,data_y,best_fea,best_fea_val)#删除最优特征equal_data_x = np.delete(equal_data_x,best_fea,1)nequal_data_x = np.delete(nequal_data_x,best_fea,1)fea_label = np.delete(fea_label,best_fea,0)#递归生成CART分类树my_tree[best_fea_label]["{}_{}".format(1,best_fea_val)] = classify_create_tree(equal_data_x,equal_data_y,fea_label)my_tree[best_fea_label]["{}_{}".format(0,best_fea_val)] = classify_create_tree(nequal_data_x,nequal_data_y,fea_label)return my_tree

​ 决策树字典格式为{“划分属性”:{“含于该划分值中”,划分结果/继续分类},{“不含于该划分值中”,划分结果/继续分类}},注意在判断是否含于该划分值中,构建如“1_划分值”, “0 _划分值”这样的字符串,1表示包含,0表示不包含。如下如所示:

  • 测试函数

    #测试操作
    import re
    #预测一条测试数据结果
    def classify(inputTree,xlabel,testdata):'''input:inputTree(dict):CART分类决策树xlabel(list):特征属性列表testdata(darry):一条测试数据特征值output:classLabel(int):测试数据预测结果'''firstStr = list(inputTree.keys())[0]secondDict = inputTree[firstStr]featIndex = xlabel.index(firstStr)#根据key值得到索引classLabel = '0'#定义变量classLabel,默认值为0ans = re.findall(r'\d+\.\d+',list(secondDict.keys())[0])if isinstance(testdata[featIndex],float):if float(testdata[featIndex]) >= float(ans[0]):if type(secondDict['1_'+ans[0]]).__name__ == 'dict':#判断secondDict[key]是否是字典格式classLabel = classify(secondDict['1_'+ans[0]], xlabel, testdata)#如果是字典格式,进行递归else:classLabel = secondDict['1_'+ans[0]]else:if type(secondDict['0_'+ans[0]]).__name__ == 'dict':#判断secondDict[key]是否是字典格式classLabel = classify(secondDict['0_'+ans[0]], xlabel, testdata)#如果是字典格式,进行递归else:classLabel = secondDict['0_'+ans[0]]return int(classLabel)else:if float(testdata[featIndex]) == float(ans[0]):if type(secondDict['1_'+ans[0]]).__name__ == 'dict':#判断secondDict[key]是否是字典格式classLabel = classify(secondDict['1_'+ans[0]], xlabel, testdata)#如果是字典格式,进行递归else:classLabel = secondDict['1_'+ans[0]]else:if type(secondDict['0_'+ans[0]]).__name__ == 'dict':#判断secondDict[key]是否是字典格式classLabel = classify(secondDict['0_'+ans[0]], xlabel, testdata)#如果是字典格式,进行递归else:classLabel = secondDict['0_'+ans[0]]return int(classLabel)#预测所有测试数据结果
    def classifytest(inputTree, xlabel, testDataSet):'''input:inputTree(dict):训练好的决策树xlabel(list):特征值标签列表testDataSet(ndarray):测试数据集output:classLabelAll(list):测试集预测结果列表'''    classLabelAll = []#创建空列表for testVec in testDataSet:#遍历每条数据classLabelAll.append(classify(inputTree, xlabel, testVec))#将每条数据得到的特征标签添加到列表return  np.array(classLabelAll)
    

源代码(全部)

import numpy as np
import re
#获取数据子集,分类与回归的做法相同
#将数据集根据划分特征切分为两类
def split_dataset(data_x,data_y,fea_axis,fea_value):'''input:data_x(ndarry):特征值data_y(ndarry):标签值fea_axis(int):进行划分的特征编号(列数)fea_value(int):进行划分的特征对应特征值output:data_x[equal_Idx],data_y[equal_Idx](ndarry):特征值等于(大于等于)目标特征值的样本与标签data_x[nequal_Idx],data_y[nequal_Idx](ndarry):特征值不等于(小于)目标特征的样本与标签'''if  isinstance(fea_value,float): #如果特征值为浮点数(连续特征值),那么进行连续值离散化equal_Idx = np.where(data_x[:,fea_axis]>=fea_value) #找出特征值大于等于fea_alue的样本序号nequal_Idx = np.where(data_x[:,fea_axis]<fea_value) #找出特征值小于fea_alue的样本序号else:equal_Idx = np.where(data_x[:,fea_axis]==fea_value) #找出特征值等于fea_alue的样本序号nequal_Idx = np.where(data_x[:,fea_axis]!=fea_value) #找出特征值不等于fea_alue的样本序号return data_x[equal_Idx],data_y[equal_Idx],data_x[nequal_Idx],data_y[nequal_Idx]#使用决策树进行分类需要用到
#求解基尼指数,即两个样本不属于同一标签的概率(二分类问题)
def cal_gini(data_y):'''input:data_y(ndarry):标签值output:gini(float):基尼指数'''m = len(data_y)  #全部样本的标签数量labels = np.unique(data_y) #获得不同种类的标签(去重)gini = 1.0  #最后返回的基尼指数for label in labels:ans = data_y[np.where(data_y[:]==label)].size/m  #该标签的出现概率gini -= ans*ans  #累减计算基尼指数(两两不同的总概率)return gini#分类方法实现最优特征的选取以及特征值划分
def classify_get_best_fea(data_x,data_y):'''input:data_x(ndarry):特征值data_y(ndarry):标签值output:best_fea(int):最优特征best_fea_val(int):最优特征值'''m,n = np.shape(data_x)  #m,n分别为样本数以及特征属性数#初始化best_fea = -1best_fea_val = -1min_fea_gini = np.inffor i in range(n):  #遍历所有特征(列)feas = np.unique(data_x[:,i])  #获得该特征下所有特征值#分别以每个特征值为中心进行划分求基尼系数,找到使基尼系数最小的划分for j in feas:equal_data_x,equal_data_y,nequal_data_x,nequal_data_y = split_dataset(data_x,data_y,i,j)fea_gini = 0.0fea_gini = len(equal_data_y)/m*cal_gini(equal_data_y)+len(nequal_data_y)/m*cal_gini(nequal_data_y)#如果该划分方式的基尼系数更小(纯度更高),那么直接进行更新if fea_gini<min_fea_gini:min_fea_gini = fea_ginibest_fea = ibest_fea_val = jreturn best_fea,best_fea_val#创建分类方法的决策树
def classify_create_tree(data_x,data_y,fea_label):'''input:data_x(ndarry):特征值data_y(ndarry):标签值fea_label(list):特征属性列表output:my_tree(dict):生成的CART分类树'''labels = np.unique(data_y)#只有一个标签的情况if len(labels)==1:return data_y[0]#特征集为0的情况,采用多数投票的方法if data_x.shape[1]==0:best_fea,best_fea_num = 0,0for label in labels:num = data_y[np.where(data_y==label)].sizeif num>best_fea_num:best_fea = labelbest_fea_num = numreturn best_feabest_fea,best_fea_val = classify_get_best_fea(data_x,data_y)best_fea_label = fea_label[best_fea]print(u"此时最优索引为:"+str(best_fea_label))my_tree = {best_fea_label:{}}#获得划分结果equal_data_x,equal_data_y,nequal_data_x,nequal_data_y = split_dataset(data_x,data_y,best_fea,best_fea_val)#删除最优特征equal_data_x = np.delete(equal_data_x,best_fea,1)nequal_data_x = np.delete(nequal_data_x,best_fea,1)fea_label = np.delete(fea_label,best_fea,0)#递归生成CART分类树my_tree[best_fea_label]["{}_{}".format(1,best_fea_val)] = classify_create_tree(equal_data_x,equal_data_y,fea_label)my_tree[best_fea_label]["{}_{}".format(0,best_fea_val)] = classify_create_tree(nequal_data_x,nequal_data_y,fea_label)return my_tree#预测一条测试数据结果
def classify(inputTree,xlabel,testdata):'''input:inputTree(dict):CART分类决策树xlabel(list):特征属性列表testdata(darry):一条测试数据特征值output:classLabel(int):测试数据预测结果'''firstStr = list(inputTree.keys())[0]secondDict = inputTree[firstStr]featIndex = xlabel.index(firstStr)#根据key值得到索引classLabel = '0'#定义变量classLabel,默认值为0ans = re.findall(r'\d+\.\d+',list(secondDict.keys())[0])if isinstance(testdata[featIndex],float):if float(testdata[featIndex]) >= float(ans[0]):if type(secondDict['1_'+ans[0]]).__name__ == 'dict':#判断secondDict[key]是否是字典格式classLabel = classify(secondDict['1_'+ans[0]], xlabel, testdata)#如果是字典格式,进行递归else:classLabel = secondDict['1_'+ans[0]]else:if type(secondDict['0_'+ans[0]]).__name__ == 'dict':#判断secondDict[key]是否是字典格式classLabel = classify(secondDict['0_'+ans[0]], xlabel, testdata)#如果是字典格式,进行递归else:classLabel = secondDict['0_'+ans[0]]return int(classLabel)else:if float(testdata[featIndex]) == float(ans[0]):if type(secondDict['1_'+ans[0]]).__name__ == 'dict':#判断secondDict[key]是否是字典格式classLabel = classify(secondDict['1_'+ans[0]], xlabel, testdata)#如果是字典格式,进行递归else:classLabel = secondDict['1_'+ans[0]]else:if type(secondDict['0_'+ans[0]]).__name__ == 'dict':#判断secondDict[key]是否是字典格式classLabel = classify(secondDict['0_'+ans[0]], xlabel, testdata)#如果是字典格式,进行递归else:classLabel = secondDict['0_'+ans[0]]return int(classLabel)#预测所有测试数据结果
def classifytest(inputTree, xlabel, testDataSet):'''input:inputTree(dict):训练好的决策树xlabel(list):特征值标签列表testDataSet(ndarray):测试数据集output:classLabelAll(list):测试集预测结果列表'''    classLabelAll = []#创建空列表for testVec in testDataSet:#遍历每条数据classLabelAll.append(classify(inputTree, xlabel, testVec))#将每条数据得到的特征标签添加到列表return  np.array(classLabelAll)

测试集1(鸢尾花集)

全部属性以及部分标签如下:

导入以及训练CART分类树过程如下:

#测试数据集一(鸢尾花集)
import pandas
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder#导入数据集iris
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data"
names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width', 'class']
dataset = pandas.read_csv(url, names=names) #读取csv数据
dataset.head()
X = dataset.iloc[:,:-1].values
y = dataset.iloc[:,-1].values
#将标签分别改为0,1,2
for i in range(len(y)):if y[i]=='Iris-setosa':y[i]=0elif y[i]=='Iris-versicolor':y[i]=1elif y[i]=='Iris-virginica':y[i]=2#获得特征属性名称列表
fea_label = names[:-1]
#划分训练集与测试集,参数test_size设为0.3,random_state设为666
x_train,x_test,y_train,y_test = train_test_split(X,y,test_size = 0.3,random_state = 666)
#生成CART分类树
cartTree = classify_create_tree(x_train,y_train,fea_label)
print(cartTree)

生成结果如下:

选取测试数据进行测试,并计算相应的分类正确率:

classlist=classifytest(cartTree,names,x_test)
print("预测结果",classlist)
print("真实结果",y_test)
print("准确率为:%.4f"%np.mean(classlist==y_test))

结果如下:


测试集2(红酒品类数据集)

13个属性如下图所示:

导入以及训练CART分类树过程如下:

#测试数据集二
from sklearn.datasets import load_wine
wine = load_wine()
data = wine.data
target = wine.target
fea_names = list(wine.feature_names)# #划分训练集与测试集,参数test_size设为0.3,random_state设为666
x_train,x_test,y_train,y_test = train_test_split(data,target,test_size = 0.35,random_state = 666)
# #生成CART分类树
cartTree = classify_create_tree(x_train,y_train,fea_names)
print(cartTree)

生成结果如下:

选取测试数据进行测试,并计算相应的分类正确率:

classlist=classifytest(cartTree,fea_names,x_test)
print("预测结果",classlist)
print("真实结果",y_test)
print("准确率为:%.4f"%np.mean(classlist==y_test))

结果如下:


总结

(1)主要面对特征值离散或者连续的问题,离散值只需要判断是否相等就可以进行二分类,而连续值需要不断的选择不同的特征值进行划分,然后计算求得基尼系数,选取基尼系数最小的情况作为划分结果。

(2)因为可能存在连续的属性,也可能存在离散的属性,所以在划分子集的时候,对这些情况就需要考虑全面。不同的值对应不同的划分方法。同样对于测试集的预测,我们也需要更具不同的属性选择不同的预测方式。

实验三:CART分类决策树python实现(两个测试集)(一)|机器学习相关推荐

  1. 实验三:CART回归决策树python实现(两个测试集)(二)|机器学习

    目录 python实现 分步 源代码(全部) 测试集1(波士顿房价数据集) 测试集2(糖尿病数据集) 总结 python实现 分步 划分数据子集(左子树划分比指定值小的样本集合,右子树划分比指定值大的 ...

  2. CART分类决策树、回归树和模型树算法详解及Python实现

    机器学习经典算法详解及Python实现–CART分类决策树.回归树和模型树 摘要: Classification And Regression Tree(CART)是一种很重要的机器学习算法,既可以用 ...

  3. 经典算法详解--CART分类决策树、回归树和模型树

    Classification And Regression Tree(CART)是一种很重要的机器学习算法,既可以用于创建分类树(Classification Tree),也可以用于创建回归树(Reg ...

  4. CART分类决策树:kaggle泰坦尼克号存活率预测(不调库,手工推)

    一.数据来源 1.数据来源:kaggle-competitions 2.数据分析说明 该竞赛提供了两份文件,一份为训练集数据,另一份为测试集数据. 通过训练集数据训练模型,然后预测测试集里每一位乘客是 ...

  5. 机器学习十大算法之-CART分类决策树、回归树和模型树

    转载(http://blog.163.com/zhoulili1987619@126/blog/static/35308201201542731455261/) Classification And ...

  6. 人工智能实验三:分类算法实验

    一.实验目的 1.巩固4种基本的分类算法的算法思想:朴素贝叶斯算法,决策树算法,人工神经网络,支持向量机算法: 2.能够使用现有的分类器算法代码进行分类操作: 3.学习如何调节算法的参数以提高分类性能 ...

  7. python划分训练集和测试集_杨涛的Python机器学习3:单特征与多特征、训练集与测试集,杨桃...

    本人CSDN博客专栏:https://blog.csdn.net/yty_7 Github地址:https://github.com/yot777/ 单特征与多特征 在上一节标签和特征的示例中,我们使 ...

  8. Python批量获取VOC测试集的类别

    使用 Python 读取 XML 文件,获取所有类别. # coding=utf-8 # @Author: FSJohn # @Date: 2022.3.21 import xml.etree.Ele ...

  9. 虚拟创业云|BBC幼儿英语启蒙动画小鸟三号 3rd and Bird 全两季50集3-5岁

    虚拟创业云|非常推荐BBC 幼儿英语的小鸟三号,因为第一次观看,即使作为大人的我,也被他又没的水彩画画风所吸引,就别提小孩子了.而且配音也非常有特点,非常容易给孩子留下深刻的印象,你的孩子一定会追剧看 ...

最新文章

  1. 专题 13 IPC之信号量
  2. cannot resolve symbol
  3. 使用 rsync / scp 命令下载linux文件,显示网速和进度
  4. 网络编程中设计并发服务器,使用多进程 与 多线程 ,请问有什么区别?
  5. java lambda 表达式中的双冒号和箭头的用法 ::
  6. STL源码剖析 序列式容器 slist
  7. 存储引擎 boltdb 的设计奥秘?
  8. shell脚本if和switch语句编写案例
  9. Centos yum 安装JDK及配置环境变量
  10. java中max函数blog_感受 lambda 之美!
  11. matlab imf1,NGPM_v1.4y GA多目标优化的程序 带约束 里面有教程 matlab 272万源代码下载- www.pudn.com...
  12. nginx 负载均衡的五中不同配置方式
  13. WYSISYN编辑器 Prosemirror 入门
  14. Atitit.c# .net 3.5 4.0 4.5 5.0 6.0各个版本新特性战略规划总结
  15. android 动画库
  16. 漫画阅读器:DreamView for Mac
  17. Android中英文切换
  18. hdu 1598 find the most comfortable road 枚举+最小成生树 kruskal 解题报告
  19. matplotlib之直方图
  20. 刷脸支付星星之火可以燎原

热门文章

  1. win10浏览器闪退_win10 edge浏览器闪退打不开的恢复方法
  2. phpnow测试PHP源码,phpnow php探针环境检测代码
  3. 服务器搭建——ftp
  4. 我的世界java地狱更新_【我的世界】我得世界:1.16地狱大年夜更新_玩得好游戏攻略...
  5. WPF解决方案和项目结构
  6. An exceptionCaught() event was fired, and it reached at the tail of the pipeline.
  7. 2021年初oracle最新版本是多少_Oracle升级该怎么选版本
  8. java 23种设计模式 04 单例模式
  9. 电气专业c语言要学得非常好吗,电气自动化专业需要学C语言吗?
  10. 目标跟踪系列三:ECO: Efficient Convolution Operators for Tracking(2016年11月)