机器学习(三)决策树对连续值数据的预剪枝及后剪枝(Python代码)

这篇具有很好参考价值的文章主要介绍了机器学习(三)决策树对连续值数据的预剪枝及后剪枝(Python代码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


参考:
https://blog.csdn.net/ylhlly/article/details/93213633
https://zhuanlan.zhihu.com/p/267368825

一、前言

为什么要进行剪枝?

当我们的数据集样本量很大每个特征的取值很多时,生成决策树的代价就会很大。不仅如此,虽然一个完整的决策树对训练数据的预测非常准,但这会造成对训练数据的过拟合,造成模型的泛化性能(预测除训练集意外数据的能力)降低。因此,本节我们将引入剪枝的概念。

二、基本概念

1.剪枝

  剪枝就是将决策树下的某个子树的根节点作为叶结点,并且将该子树根节点以下的点全部删除。

  剪枝可以使决策树的节点数减少,减小决策树过拟合的可能,提高决策树的泛化性能

  剪枝分为预剪枝后剪枝

2.预剪枝

2.1 介绍

  预剪枝其实就是在生成决策树的过程中边生成决策树边剪枝

  预剪枝在构建决策树的过程中,计算以下两个精确度 :
  1、如果不划分样本集合此时模型在验证集上的精确度;
  2、如果划分样本集合此时模型在验证集上的精确度。

  如果划分后的精确度更高,说明此时划分样本集对整体的泛化性能的提高是有益的,那此时就选择划分样本

  如果划分后的精确度更低或不变,说明划分后此时泛化性能不变或变差,此时就不划分样本,将该节点作为叶结点

  注意:本次划分样本集后的泛化性能变差不代表在该划分方法的基础下继续进行划分样本集后的泛化性能差
  (本次虽然造成泛化性能变差,但有可能该次的样本划分对下一次的某个特征的划分有帮助)

2.2 优点

  在生成决策树的过程中剪枝,减少了很多划分样本集的过程,使得计算量较小

2.3 缺点

  如上面注意所说的一样,仅仅根据当前划分样本集造成泛化能力下降就将该节点作为叶结点、不再对该节点下的样本集进行划分,可能会造成最终的泛化能力变差,导致欠拟合

3.后剪枝

3.1 介绍

  后剪枝其实就是生成决策树后,自底向上循环每个子树进行剪枝

  后剪枝在构建决策树的过程中,自底向上遍历每个子树,计算以下两个精确度 :
  1、留下该子树的精确度;
  2、将该子树作为叶子节点的精确度。

  如果将该子树作为叶结点精确度更高,说明此时的操作对整体的泛化性能的提高是有益的,那此时就选择该操作。

  反之,则不对该子树进行操作

3.2 优点

  在生成完整的决策树以后再对决策树进行剪枝操作,由于后剪枝的条件是当剪枝后的精确度高于不剪枝的精确度,而当前的完整的决策树已经达到一个较高的精确度,剪枝后的决策树不会欠拟合

3.3缺点

  不仅要生成完整的决策树,还要对决策树当中的每个子树进行遍历,检测是否需要剪枝,使得计算量大大增加


三、数据集准备

本次数据集比上一篇博客中的数据集新增了7个数据。
数据集以集美大学为背景,数据集中的前四列代表从宿舍至该楼的时间,单位为分钟,最后一列为对应的交通方式,共有21个数据以csv文件方式存储,其中前14个作为训练集,后7个作为验证集。

禹州楼 建发楼 美玲楼 陆大楼 交通方式
4 3.5 3.5 5.5 电动车
8 7 6.8 11 步行
5 4 4 6 自行车
5.5 4.5 4.5 7 自行车
3 2.5 2.5 4 自行车
7 6 6 11 步行
5.2 4.7 4.6 6.2 自行车
4 3.8 3.8 5 电动车
8 7 7 12 步行
6 5.5 5.2 9 步行
5 4.3 4.2 6.3 电动车
7 6 6 12 步行
3.5 3.2 3.1 5 自行车
4.5 4.1 4.1 5.5 电动车
4.2 3.9 3.9 5.6 电动车
4.1 3.7 3.7 5.2 自行车
7.2 6.4 6.2 10.1 步行
6.7 6.1 5.9 9.8 步行
9 8 8 13 步行
4 3.7 3.8 5.8 自行车
3.5 3.2 3.1 4.8 电动车

四、代码实现

1.创建决策树

由于本数据的特征都为连续属性,采取二分法对数据集进行划分。

本篇文章的剪枝代码在上一篇的创建决策树的代码上进行修改。

本文只贴出与上一篇博客中有差异的代码,该段函数中包含不进行剪枝操作进行预剪枝以及进行后剪枝的代码。

创建决策树:

def createTree(trainDataset, testDataset, labels, method = None):
    '''
    method 为 [None, 'pre', 'post']中的一种
    None为不使用剪枝操作,
    'pre'为使用预剪枝操作,
    'post'为使用后剪枝操作,
    
    递归建树
    1.获取最佳特征索引bestIndex以及最佳划分点bestSplitValue
    2.根据bestIndex和bestSplitValue将训练集与测试集划分为左右两个子集subDataset1和subDataset2
    3.如选择预剪枝,则每次衡量划分子集前的精确度和划分子集后的精确度,如有提高才生成子树;
    4.如选择后剪枝,则先生成子树,再衡量去除每个子树是否带来精确度的提高,如有提高则去除子树;
    
    返回值:
    1.method为None或'pre'时,返回myTree
    2.method为'post'时,返回myTree与correct
    
    注意:
    这个correct是指由训练集划分出的子树对测试集进行预测,一共预测对多少个样本的个数。
    
    '''
    # 获取训练集与测试集当中的所有类别
    trainClassList = [example[-1] for example in trainDataset] 
    testClassList = [example[-1] for example in testDataset]
    
    # 若训练集中只有一个类时,有两种情况:
    # 1.如果当前采用后剪枝,则返回predict_class与correct
    # 2.如果不剪枝或采用预剪枝,则返回predict_class
    if trainClassList.count(trainClassList[0]) == len(trainClassList):
        
        # 当前子树预测类别
        predict_class = trainClassList[0]
        # 当前预测类别预测测试集对的个数
        correct = testClassList.count(predict_class)
        
        if method == 'post':
            return predict_class, correct
        else: 
            return predict_class
        
    # 若训练集最后只剩下类别,有两种情况:
    # 1.如果当前采用后剪枝,则返回predict_class与correct
    # 2.如果不剪枝或采用预剪枝,则返回predict_class
    if len(trainDataset[0]) == 1: 
        
        # 当前子树预测类别
        predict_class = majorityCnt(trainClassList)
        # 当前预测类别预测测试集对的个数
        correct = testClassList.count(predict_class)
        
        if method == 'post':
            return predict_class, correct
        else: 
            return predict_class
        
    # 找到当前情况下使训练集信息增益最大的特征的索引,以及最佳的划分点值
    bestIndex, bestSplitValue = chooseBestFeatureToSplit(trainDataset) 
    # 最优特征的名字
    bestFeature = labels[bestIndex]
    # 创建决策树 
    myTree = {bestFeature:{}}
    # 从labels中删除最优特征
    del(labels[bestIndex])
    
    # 使用最优特征索引与最佳参数划分出训练集与测试集的两个子集
    trainSubDataset1, trainSubDataset2 = splitDataset(trainDataset,bestIndex
                                                      ,bestSplitValue)
    testSubDataset1, testSubDataset2 = splitDataset(testDataset,bestIndex
                                                    ,bestSplitValue)
    # 获取训练集与测试集中子集1与子集2的所有类别
    trainSubClassList1 = [example[-1] for example in trainSubDataset1] 
    trainSubClassList2 = [example[-1] for example in trainSubDataset2] 
    testSubClassList1 = [example[-1] for example in testSubDataset1] 
    testSubClassList2 = [example[-1] for example in testSubDataset2] 
    if method == 'pre':
        
        # 划分子集前:
        # 预测类别为当前训练集中最多的类别
        predict_class_pre = majorityCnt(trainClassList)
        # 使用训练集中最多的类别预测当前未划分的测试集的准确度
        precision_pre = testClassList.count(predict_class_pre)/len(testClassList)
        
        # 划分子集后:
        # 子集1的预测类别为当前训练子集1中最多的类别,子集2同理
        predict_class_post1 = majorityCnt(trainSubClassList1)
        predict_class_post2 = majorityCnt(trainSubClassList2)
        # 使用这两个类别分别预测测试集的子集1与子集2的正确总数
        correct1 = testSubClassList1.count(predict_class_post1)
        correct2 = testSubClassList2.count(predict_class_post2)
        totalCorrect = correct1 + correct2
        # 划分子集后的准确率
        precision_post = totalCorrect / len(testClassList)
        
        # 如果划分子集后的准确率比划分前更高,则划分子集,否则返回当前样本中最多的类别
        if precision_post > precision_pre:
            myTree[bestFeature]["<="+str(bestSplitValue)] = createTree(trainSubDataset1,testSubDataset1, labels, method = 'pre')
            myTree[bestFeature][">"+str(bestSplitValue)] = createTree(trainSubDataset2,testSubDataset2, labels, method = 'pre')
        else:
            return predict_class_pre
    elif method == 'post':
        
        # 剪枝前:
        # 生成leftTree与rightTree并得到该子树预测测试集对的数量correct1与correct2
        leftTree, correct1 = createTree(trainSubDataset1,testSubDataset1, labels, 
                                        method = 'post')
        rightTree, correct2 = createTree(trainSubDataset2,testSubDataset2, labels, 
                                         method = 'post')
        totalCorrect = correct1 + correct2
        # 剪枝前的准确率
        precision_pre = totalCorrect / len(testClassList)
        
        # 剪枝后
        # 预测类别为当前训练集中最多的类别
        predict_class_post = majorityCnt(trainClassList)
        # 使用训练集中最多的类别预测剪枝后的测试集的准确度
        precision_post = testClassList.count(predict_class_post)/len(testClassList)
        
        # 如果剪枝后的精确度比剪枝前更高,则进行剪枝,
        # 返回剪枝后的预测类别predict_class_post与剪枝后预测对的个数correct_post;
        # 否则返回剪枝前的树myTree以及剪枝前预测正确的个数totalCorrect
        if precision_post > precision_pre:
            correct_post = testClassList.count(predict_class_pre)
            return predict_class_pre, correct_post
        else:
            myTree[bestFeature]["<="+str(bestSplitValue)] = leftTree
            myTree[bestFeature][">"+str(bestSplitValue)] = rightTree
            return myTree, totalCorrect
            
    elif method == None:
        myTree[bestFeature]["<="+str(bestSplitValue)] = createTree(trainSubDataset1,testSubDataset1, labels, method = None)
        myTree[bestFeature][">"+str(bestSplitValue)] = createTree(trainSubDataset2,testSubDataset2, labels, method = None)
    return myTree

2.决策树绘画

与上一节博客中的一样,此处就不贴出了。

3.完整代码链接

链接:https://pan.baidu.com/s/13ySeH9oeT0VXVKDYQruXQg?pwd=tnv9
提取码:tnv9

五、结果

使用剪枝前:
机器学习(三)决策树对连续值数据的预剪枝及后剪枝(Python代码)

使用预剪枝后:
机器学习(三)决策树对连续值数据的预剪枝及后剪枝(Python代码)
使用后剪枝后:
机器学习(三)决策树对连续值数据的预剪枝及后剪枝(Python代码)

结果分析:
关于预剪枝:
  原本划分数据集时使用了四个特征,预剪枝后只使用了一个特征
  这是因为预剪枝的特性只要当前划分子集之后没有带来精度的提高,就会停止划分当前的节点,将该节点作为叶结点。
  而该数据刚刚好使用了“禹州楼”这一特征进行划分出左右两个子集之后,左右两个子集分别再进行划分都没有再带来精度上的提升,故决策树停止生长

关于后剪枝:
  后剪枝对先前生成的决策树没有影响。
  这是因为后剪枝的特性只要当前剪枝之后没有带来精度的提高,就不进行剪枝。
  而该数据先前生成的决策树刚刚好每一个子树剪枝之后都不会带来精度上的提升,故决策树没有进行任何剪枝操作

不足:
  可以对比ID3算法其他决策树算法的区别,还可以对比决策树算法KNN算法的区别,但由于时间问题,目前没有时间做比较。文章来源地址https://www.toymoban.com/news/detail-421313.html


到了这里,关于机器学习(三)决策树对连续值数据的预剪枝及后剪枝(Python代码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用决策树对鸢尾花进行分类python

    鸢尾花数据集介绍 target介绍 1:绘制直方图 2.png)] 1:划分训练集和测试集 构建训练集和测试集,分别保存在X_train,y_train,X_test,y_test from sklearn.model_selection import train_test_split 2:训练和分类 from sklearn.tree import DecisionTreeClassifier DecisionTreeClassifier() DecisionTreeClassifier(criterion=‘entro

    2024年02月06日
    浏览(44)
  • (统计学习方法|李航)第五章决策树——四五节:决策树的剪枝,CART算法

    目录 一,决策数的剪枝 二,CART算法 1.CART生成 (1)回归树的生成 (2)分类树的生成          2.CART剪枝 (1)剪枝,形成一个子树序列 (2)在剪枝得到的子树序列T0,T1-----,Tn中通过交叉验证选取最优子树Ta   好的决策树不高不宽     柳建男的”后剪枝“挥手创作   如果

    2024年02月14日
    浏览(46)
  • 机器学习实战3-利用决策树算法根据天气数据集做出决策

    大家好,我是微学AI,今天给大家介绍一下机器学习实战3-利用决策树算法根据天气数据集做出决策,决策树是一种广泛使用的机器学习算法,用于分类和回归问题。它的基本思想是通过对数据进行分而治之,把复杂的问题转化为简单的决策序列。 一、决策树的介绍 对于决策

    2024年02月08日
    浏览(44)
  • 【机器学习 | 决策树】利用数据的潜力:用决策树解锁洞察力

    🤵‍♂️ 个人主页: @AI_magician 📡主页地址: 作者简介:CSDN内容合伙人,全栈领域优质创作者。 👨‍💻景愿:旨在于能和更多的热爱计算机的伙伴一起成长!!🐱‍🏍 🙋‍♂️声明:本人目前大学就读于大二,研究兴趣方向人工智能硬件(虽然硬件还没开始玩,但一直

    2024年02月14日
    浏览(70)
  • 【机器学习】决策树案例二:利用决策树进行鸢尾花数据集分类预测

    手动反爬虫,禁止转载: 原博地址 https://blog.csdn.net/lys_828/article/details/122045161(CSDN博主:Be_melting) 在进行逻辑回归分类的过程中已经有使用过iris数据集,这里直接加载数据,并进行字段名称的修改。 输出结果如下。 通过info()方法查看各个字段的基本详情,输出结果如下。

    2024年02月08日
    浏览(46)
  • 机器学习实验——使用决策树和随机森林对数据分类

    使用决策树算法和随机森林算法对income_classification.csv的收入水平进行分类。训练集和测试集的比例是7:3,选取适当的特征列,使得针对测试样本的分类准确率在80%以上,比较2种分类方法的准确率。 数据说明: 特征列: 分类标签列:income 1、读入数据并显示数据的维度和前

    2024年02月04日
    浏览(46)
  • python机器学习数据建模与分析——决策树详解及可视化案例

    你是否玩过二十个问题的游戏,游戏的规则很简单:参与游戏的一方在脑海里想某个事物,其他参与者向他提问题,只允许提20个问题,问题的答案也只能用对或错回答。问问题的人通过推断分解,逐步缩小待猜测事物的范围。决策树的工作原理与20个问题类似,用户输人一系

    2024年02月03日
    浏览(46)
  • 机器学习---预剪枝、后剪枝(REP、CCP、PEP、)

    1. 为什么要进行剪枝 横轴表示在决策树创建过程中树的结点总数,纵轴表示决策树的预测精度。 实线显示的是决策树 在训练集上的精度,虚线显示的则是在⼀个独⽴的测试集上测量出来的精度。 随着树的增⻓,在 训练样集上的精度是单调上升的, 然⽽在独⽴的测试样例上

    2024年02月09日
    浏览(36)
  • 机器学习-决策树-回归-CPU(中央处理单元)数据-python scikit-learn

    决策树是一种监督机器学习算法,用于回归和分类任务。树是可以处理复杂数据集的强大算法。 决策树特性: 不需要数值输入数据进行缩放。无论数值是多少,决策树都不在乎。 不同于其他复杂的学习算法,决策树的结果是可以解释的,决策树不是黑盒类型的模型。 虽然大

    2024年02月20日
    浏览(38)
  • 机器学习-决策树-分类-汽车数据集-fetch_openml python scikit-learn

    在这个使用决策树的分类任务中,将使用OpenML提供的汽车数据集来预测给定汽车信息的汽车可接受性。将使用Sklearn ’ fetch_openml \\\'函数加载它。 此次获取的数据的版本是2。在数据集的版本1中,目标类有4个类(unacc, acc, good, vgood),但在第二个版本中,大多数类是Positive§,而其

    2024年02月22日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包