决策树 prepruning_数据挖掘入门系列教程(三点五)之决策树

2023-11-03

本来还是想像以前一样,继续学习《 Python数据挖掘入门与实践 》的第三章“决策树”,但是这本书上来就直接给我怼了一大串代码,对于决策树基本上没有什么介绍,可直接把我给弄懵逼了,主要我只听过决策树还没有认真的了解过它。

这一章节主要是对决策树做一个介绍,在下一个章节,将使用决策树来进行预测分类。

决策树(Decision Tree)介绍

Decision Tree是一类较为常见的机器学习的方法。它既可以作为分类算法,也可以作为回归算法。

如何来介绍决策树,这里举一个例子:在大学,你找女朋友的时候,心目中顺序应该是这样的(仅仅是举一个例子):

  • Q:性别要求?
  • A:不是女的不要。
  • Q:年龄要求?
  • A:大于我3岁的不要
  • Q:专业要求?
  • A:非CS不要
  • ……

为了更好的表示上面的这一些问题,我们可以将其画成一张树状图如下所示:

上面的这棵树就是我们找女朋友的决策过程,圆角矩形代表了判断条件,椭圆形代表了决策结果。通过性别,年龄,专业这几个属性,最终我们得出了最终的决策。而这棵树也就被称之为决策树。

大家通过上图会发现有3个东西:

  • 根节点:包含样本的全集
  • 内部节点:对应特征属性测试
  • 叶节点:代表决策的结果

在一棵决策树中,包含了一个根节点,多个内部节点(判断条件) 和若干个叶子节点。先说叶子节点,在决策树中,叶子节点对应了决策结果,决策结果可以有多种类型(图中是yes和no,也可以为1,2,3)。内部节点和根节点对应的都是属性测试,只不过先后顺序不同。

总的来说,决策树体现的是一种“分而治之”的思想,

那么这里就有一个问题,谁来当根节点?谁又来当中间的节点?先后顺序又是怎样的?(这里先不说算法流程,从简单开始说起,然后再说算法流程)

结点的选择

首先我们需要明白根节点和中间节点是不同的,一个是统领全局的开始包含所有的样本。一个是负责局部的决策,并且随着决策树的不断的进行决策,所包含的样本逐渐属于同一个类别,即节点的“纯度”越来越高。

那么,我们如何来寻找合适根节点(也就是属性)呢?靠感觉?靠感觉当然不行,我们需要一个具体的数值来决定,很幸运,香农帮助我们做到了。

“信息熵”(information entropy):可以度量样本集合中的“纯度”。 在信息世界,熵越高,表示蕴含越多的信息,熵越低,则信息越少。 而根节点需要包含所以的样本,则根结点的熵最大

信息熵(Information Entropy)

设样本集合为

,第
类样本所占比例为
,则集合
的信息熵为:

现在,我们已经知道一个集合

中的信息熵是多少,那么我们如何来进行划分呢?首先,我们需要明确一个划分的标准(也就是目标),我们当然希望划分之后,划分之后的集合的熵越来越小,也就是划分后的集合越来越纯,这里我们引入信息增益这个概念。

信息增益(information gain)

下面是西瓜书中对信息增益的定义:

假设离散属性
个可能的取值
,若以属性
对样本进行划分,则有V个分支,其中第
个分支包含了
中在属性
上取值为
的样本,记为
。我们可以计算出
的信息熵,然后考虑到不同分支结点的样本数不同,给分支结点赋予权重
,样本数愈多,则影响力越大,则可以计算出属性
对样本集
进行划分的“信息增益”:

一般来说,信息增益越大,则代表划分后的集合越“纯”,也就是说使用

属性来划分的效果最好,那么我们就可以使用
属性来进行划分。
ID3算法就是使用信息增益来作为标准划分属性的。

决策树生成算法流程

下面是来自《西瓜书》的决策树生成算法流程:

决策树生成是一个递归的过程,在下面3中情况中,递归会返回:

  • 当前结点包含的样本全属于同一类别,无需划分
  • 当前属性集为空,或是所有样本在所有属性上取值相同,无法划分
  • 当前结点包含的样本集合为空,不能划分

算法可能不是那么的形象好理解,下面将以实际的例子来展示。

在最上面上面的找女朋友的例子并不是特别的好,属性太少。这里以西瓜书中的 来进行举例。这个属性还是挺多的。

在上图中,属性的集合是{色泽,根蒂,敲声,纹理,脐部,触感}(目前不考虑编号这个属性),分类的集合是{是,否},一共有17个样本。

首先让我们来及计算集合

的熵值。在集合
中,好瓜(是)占
,坏瓜(否)占
,所以集合
的熵为:

以色泽作为划分标准,可以得到3个子集:

我们可以获得

的信息熵:

因此色泽的信息增益为:


同理可以得到:
通过计算可以得到,纹理的信息增益最大,因此他被选为划分的属性如下图:

然后以纹理是“清晰为例”,该集合

,可用的属性集合为{ 色泽,根蒂,敲声,脐部, 触感}。因此,基于$D^1$又可以计算出各个属性的信息增益:

因此我们可以在“根蒂”,“触感”,“脐部”中任意选择其中一个作为划分属性。最终得到以下的决策树:

通过上面的这些步骤,我们就得到了一颗关于西瓜的好坏的决策树。ID3算法就是用信息增益作为划分标准。

上面的例子来自西瓜书,以及计算的结果也来自西瓜书。

增益率(Gain Ratio)

在这里有一个问题,

越大,就一定能够作为划分标准吗?假如它是一个无用的属性呢?比如上图中
编号这个属性,如果在上面我们选择编号作为根节点,那么第一次划分就能够得到17个集合,每一个集合只有1个样本,
必定能够达到最大值。但是我们知道,编号这个属性在这里是毫无作用的。如果将这个问题进行泛化,如果一个属性在
分类中起到的作用给很小(也就是它对分类的影响很小),那么我们应该怎么考虑呢?

这里我们可以使用增益率来作为划分的标准,定义如下

称之为属性
固有值(intrinsic value),属性
的可能取值越多(划分的
的集合越多),
就会越大。若像编号一样进行划分(每一个划分的集合中只有一个样本),随着编号的增多,
的取值如下图:

其中著名的C4.5算法就是使用增益率来划分属性。

除了这种解决方案,还有一种解决方法,基尼指数作为划分标准,CART决策树使用这种方法。

基尼指数(Gini Index)

前面我们使用信息熵来表示集合的纯度,这里我们使用基尼值来表示:

设样本集合为

,第
类样本所占比例为

反映了从数据集中随机抽取两个样本,其类别标记不一致的概率。因此,
越大,则数据集越复杂,纯度越低。

同样,属性

的基尼指数定义为:

因此,在我们选择合适的属性进行划分的时候,选择划分后基尼指数较小的属性作为划分标准即可。

这个时候我们再来看一看这幅图,应该就看的懂了吧。

剪枝(pruning)处理

首先,我们先说一下剪枝的目的——防止“过拟合”。在决策树的学习过程中,为了保证正确性,会不断的进行划分,这样可能会导致对于训练样本能够达到一个很好的准确性,但是对于测试集可能就不是很好了,这样的模型不具备泛化性。下面来举一个例子:

我们有如下的数据集:

坐标轴的上的每一个点代表一个样本,有

两种属性,其中,蓝色的点代表类0,橙色的点代表类1。

当我们使用决策树进行训练后,模型对于数据的识别区域如下,在粉红色区域,其认为里面的点为类0,蓝色的区域为类1:

大家可能发现一个问题,那就是这个区域划分的太“细致”了。因为数据是有噪音(noise)的,这样划分明显是不合理的。这里大家可以看一看决策树的图片:

那么如何来缓解这种问题呢?其中有一种方法就是去掉一些分支(剪枝)来降低过拟合的风险。

剪枝有两种方案:

  • 预剪枝(prepruning)
  • 后剪枝(post-pruning)

预剪枝

预剪枝是指在决策树生成过程中,对每个结点在划分前先进行估计,若当前结点的划分不能带来决策树泛化性能提升,则停止划分并将当前结点标记为叶结点。

用通俗的话来说,就是如果进行划分能够带来更好的结果就进行划分,否则不进行划分。首先,我们定义一个训练集和一个验证集如下:(西瓜书中间的例子)

上面一部分是训练集,下面一部分是测试集。然后让我们来对**训练集(记住是训练集)**进行划分,划分的规则与上面的一样。

下面的这幅图是未剪枝的情况。

那么,剪枝是如何进行的呢?

首先,我们先判断“脐部”,如果我们不对“脐部”进行划分,也就是说这棵决策树是这样的:

只有一个好瓜的判断结果(根据上面的算法流程图,node节点直接就是叶子节点,其类别由样本中最多的决定【这里既可以是好瓜也可以是坏瓜,因为数量一样】)

这样下来,也就是说无论你什么瓜过来我都判断它是好瓜。使用验证集进行验证,验证的精准度为:

。如果进行划分呢?

下图便是进行划分的情况,其中被红色圆圈框出来的部分表示验证正确。

如果只划分“脐部”这个属性,我们可以通过其来划分好瓜和坏瓜,通过验证机去测试,我们可以得到划分后的准确性为:

,所以选择划分。

下面便是进行前剪枝后的划分结果,使用验证集进行验证,精度为

尽管该方案可以降低过拟合的风险,并在一定程度上能够降低算法的复杂度,但也会带来欠拟合的风险。因为会出现另外一种情况:有可能当前划分不能提升泛化能力,但是在此基础上的后续的划分也许可以导致性能显著提高。

后剪枝

后剪枝则是先从训练集生成一棵完整的决策树,然后自底向上地对非叶结点进行考察,若将该结点对应的子树替换为叶结点能带来决策树泛化性能提升,则将该子树替换为叶结点.

后剪枝和前剪枝的不同在于后剪枝是在生成决策树后再进行剪枝。顺序是由下到上

我们继续来看这幅图:

通过验证集,我们易得到该决策树的识别率为

让我们重新看一下数据吧,数据集和验证集如下:

现在让我们来进行剪枝吧!!首先先看节点⑥,节点6中包含编号为

的训练样本,因此我们将节点⑥变成叶节点并标记为“好瓜(坏瓜也ok)”。如下所示:

在这种情况下,验证集中序号为

验证正确,精度调高到
,因此可以进行剪枝。

考虑结点⑤,包含编号为

,将其变成叶节点(标记为“好瓜”),使用验证集去验证,其精度仍为
,没有提高,进行考虑。同理可得到下面的这副图片:

最终,该决策树的精度为

比较预剪枝和后剪枝,后剪枝保留的分支更多,同时后剪枝的欠拟合的风险很小,泛化性能往往优于预剪枝决策树,但是显而易见,训练的时间要比预剪枝大得多。

随机森林(Random Forest | RF)

什么是随机森林呢?随机森林是一个包含多个决策树的分类器,由很多决策树构成,不同的决策树之间没有关联。当我们进行分类任务时,森林中的每一棵决策树都会分别对样本进行判断和分类,每个决策树会得到一个自己的分类结果,决策树的分类结果中哪一个分类最多,那么随机森林就会把这个结果当做最终的结果。 (emm,少树服从多树)。好像很简单的样子,但是这里有一个问题,那就是随机森林中有多个决策树,那么,我们如何用已有的数据集去构建这么多的决策树呢?

首先我们要明白,决策树是不同的,那么训练决策树所需要的数据也不同。那么具体该如何选择呢?既然是随机森林,那么它肯定是随机的!!它的随机有两层含义:

  • 样本随机:Bagging算法
  • 属性随机

样本随机

样本随机使用的是Bagging算法(Bootstrap aggregating,引导聚集算法)又称之为装袋算法。算法的流程如下:

给定一个训练集大小为

的训练集
,Bagging算法从中间随机的、有
放回的选出
个大小为
的子集
作为新的训练集。

ps:通过以上这种取样得到的集合

中间可能会有重复的元素(因为是
有放回的抽取元素)

属性随机

若样本有

个属性时,随机从这
个属性中选取出
个属性(
无放回),满足条件

ps:在这种情况下,

个属性中是没有重复的属性的。

随机森林的优缺点

通过上面的样本随机和属性随机,我们就可以构建出很多棵不同的决策树了,然后组成一个森林,里面住着熊大和熊二,在一起快乐的生活。

优缺点的整理来自这里,基本上所有的文章都是这个说法,不同的在于文字的多少罢了!

优点

  1. 它可以出来很高维度(特征很多)的数据,并且不用降维,无需做特征选择
  2. 它可以判断特征的重要程度
  3. 可以判断出不同特征之间的相互影响
  4. 不容易过拟合
  5. 训练速度比较快,容易做成并行方法
  6. 实现起来比较简单
  7. 对于不平衡的数据集来说,它可以平衡误差。
  8. 如果有很大一部分的特征遗失,仍可以维持准确度。

缺点

  1. 随机森林已经被证明在某些噪音较大的分类或回归问题上会过拟合。
  2. 对于有不同取值的属性的数据,取值划分较多的属性会对随机森林产生更大的影响,所以随机森林在这种数据上产出的属性权值是不可信的

总结

决策树的概念就暂时介绍到这里了,尽管内容有点多,但是还是挺好理解的,很类似于人类的思考方式。在下一篇的博客中,将使用scikit-learn工具包,基于决策树来对数据进行分类。决策树还有很多知识和算法,但是至少我们得掌握基本的概念。

参考

  1. 《西瓜书》决策树——第四章
  2. 维基百科:随机森林 Bagging算法
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

决策树 prepruning_数据挖掘入门系列教程(三点五)之决策树 的相关文章

  • 二维数组和数组指针

    二维数组 int arr 3 4 每个元素arr 0 arr 1 arr 2 等价于一维数组名 所以也是子数组的首地址 3个一维数组分别有4个元素 二维数组名arr是首地址 可以理解为指向第一个子数组的数组指针 如int p 4 arr 所
  • 【CTR模型】TensorFlow2.0 的 xDeepFM 实现与实战(附代码+数据)

    CTR 系列文章 广告点击率 CTR 预测经典模型 GBDT LR 理解与实践 附数据 代码 CTR经典模型串讲 FM FFM 双线性 FFM 相关推导与理解 CTR深度学习模型之 DeepFM 模型解读 CTR模型 TensorFlow2
  • 特斯拉传记--摘要

    参考 https baike baidu com item E5 B0 BC E5 8F A4 E6 8B 89 C2 B7 E7 89 B9 E6 96 AF E6 8B 89 4481228 fr aladdin 尼古拉 特斯拉 Nik
  • python flask自定义404错误页面

    在用浏览器访问url的时候 如果url不正确会报404错误 默认的404错误太枯燥了 这里我讲述一下如何将404错误页面修改为好看的404页面 1 首先 创建一个我们希望当出现404错误时展示的html页面 这里我随便写一个页面内容不多定义
  • Linux_centos7_文件与目录管理_指令与文件搜寻_(4)_(bird_bro)

    kingarthur localhost pwd home kingarthur Desktop Documents Downloads Music Pictures Public README README 1 README 2 READ
  • 漫话拥塞控制:BBRv3 来啦

    周一 2023 07 31 临近午夜刚准备睡觉 收到 bbr dev 一封邮件 贴出 IETF CCWG 大会链接 IETF117 CCWG 20230725 2200 以及 bbr3 幻灯片 BBRv3 Algorithm Bug Fix
  • android开发三大框架!Android架构师教你如何突破瓶颈,Android篇

    安卓开发大军浩浩荡荡 经过近十年的发展 Android技术优化日异月新 如今Android 11 0 已经发布 Android系统性能也已经非常流畅 可以在体验上完全媲美iOS 但是 到了各大厂商手里 改源码 自定义系统 使得Android
  • c语言 静态函数和普通函数的区别是什么,类函数和普通函数区别 成员函数和普通函数的所有区别...

    1 成员函数和普通函数的所有区别 区别很大 1 成员函数是面向对象的概念 所谓的成员函数 是指一个函数作为类的成员 公有成员 私有成员或者保护成员 2 普通函数一般有两种传递方式 按类型传递和按值传递 也就是传指针和传返回值两种情况 成员函
  • linux----使用rm -rf 删除大文件后磁盘空间并未释放的解决办法

    原文链接 linux 使用rm rf 删除大文件后磁盘空间并未释放的解决办法 1 问题 当发现linux系统中存在大文件 磁盘空间快满了后 一般会使用rm rf xxx 将大文件删除 但是删除后通过df h 发现磁盘空间并未释放 2 解决办
  • React中实现流程图(第三方库)

    React简单实现可拖拽流程图 下载第三方库 react flow yarn add react flow 准备两个文件 1 index tsx 组件入口 2 mock js 测试数据 index tsx文件代码 index js impo
  • Java 根据经纬度 角度 距离求另一个点坐标

    度换成弧度 param Float d 度 return Float 弧度 private static double rad double d return d Math PI 180 0 弧度换成度 param Float x 弧度 r
  • file_include(攻防世界)

    使用php filter 发现不行 猜测应该被过滤了 继续尝试 发现read base64 encode等关键字符被过滤了 了解到php中有两种转换器 发现string被过滤 只能使用convert了 convert 过滤器支持conver
  • Android异常:android.os.NetworkOnMainThreadException

    Android 4 1项目 使用新浪微博分享时报 android os NetworkOnMainThreadException 网上搜索后知道是因为版本问题 在4 0之后在主线程里面执行Http请求都会报这个错 也许是怕Http请求时间太
  • ReferenceError: fetch is not defined

    在使用fetch时 报错fetch is not find 根据https stackoverflow com questions 48433783 referenceerror fetch is not defined的回答 通过安装 使
  • 开源介绍

    一 什么是开源 开源 Open Source 开放源码 被非赢利软件组织 美国的Open Source Initiative协会 注册为认证标记 并对其进行了正式的定义 用于描述那些源码可以被公众使用的软件 并且此软件的使用 修改和发行也不
  • HDU - 1024 Max Sum Plus Plus(区间dp)

    区间dp 题意 在n个数里选出连续的m组数使其和最大 思路 dp i j 表示分i个组时前j个数的最大值 所以有递推方程dp i j max dp i 1 k w j dp i j 1 w j 其中k取1 2 3 j 1 把第j个数当做新的
  • 目标检测(三)损失函数

    目标检测 三 损失函数 开始 一 匹配策略 二 损失函数 三 Hard negative mining 总结 开始 内容参考 Datawhale Task03 化劲儿 损失函数设计 一 匹配策略 我们要想让其预测类别和目标框信息 我们先要知
  • 如何使用multipart/form-data格式上传文件

    有时 在网络编程过程中需要向服务器上传文件 Multipart form data是上传文件的一种方式 Multipart form data其实就是浏览器用表单上传文件的方式 最常见的情境是 在写邮件时 向邮件后添加附件 附件通常使用表单
  • Django安装操作教程

    一 环境准备 确保已安装好python和pycharm工具 二 django安装并配置环境变量 方法一 cmd中命令安装 pip install i https pypi douban com simple django 或 指定相应的dj

随机推荐

  • tr字符使用

    当我们把文件从Windows传到Linux环境时候 常常在每一行的末尾 会出现一些 M的字符 而这些字符会影响文件的正常读写和执行 要去掉这些 M 字符 有很多种办法 比如直接dox2unix 也可以使用一些命令去处理 比如 删除Windo
  • 406. Queue Reconstruction by Height

    class Solution public vector
  • c++学习笔记二十——派生类的构造函数,复制构造函数和析构函数

    在讲派生类的构造和析构函数时候我们先介绍类的兼容性 类的兼容性 类的兼容性是指在需要基类对象的任何地方都可以使用派生类来替代 通过继承 派生类得到了除了基类构造函数 复制函数中的所有成员 这样公有派生类实际具备了基类所有的功能 凡是基类所能
  • 基于 BEM 规范实现简单的全局 scss

    该文章是在学习 小满vue3 课程的随堂记录 示例均采用
  • One PUNCH Man——变量显著性检验

    文章目录 显著性检验简介 t检验 单侧检验与双侧检验 区别在于是否知道标准 确定P值和做出推断结论 T检验例子 栗子no 1 栗子No 2 F检验 判断一个变量是否显著 我们一般采用T检验和F检验的方式 显著性检验简介 假设检验也叫显著性检
  • STM32单片机颜色识别分拣系统颜色名称显示2路舵机分拣

    实践制作DIY GC0120 颜色识别分拣系统 一 功能说明 基于STM32单片机设计 颜色识别分拣系统 功能介绍 硬件组成 STM32F103C系列最小系统单片机 颜色识别模块 2路舵机 2个按键 LCD1602显示器 1 可以识别颜色
  • Python 字符串

    原始字符串 print r n t n t 续行符 name woshi abc print name name woshi abc print name woshiabc 三引号 可直接跨行书写 用于注释文档 字符串拼接 str1 str
  • lintcode 1692. 组队打怪

    你现在有n个英雄 每个英雄的战斗力为atk1 你要用这些英雄去对付n个怪物 每个怪物的战斗力为atk2 在一场战斗中 你需要安排每个英雄分别与一个怪兽战斗 如果英雄战斗力高于怪兽 那个怪兽就会被击杀 问最多能击杀几个怪兽 给定atk1 6
  • excel二进制移位运算_Excel揭秘13:在Excel中实现位运算

    我们知道 计算机使用的是二进制计数法 也就是说 在计算机中的所有信息都是使用二进制来存储和处理的 下表列出了我们熟悉的十进制数及与其相对应的二进制数 位运算规则 在位运算中 按位与 运算 AND运算 分别按位比较两个相应的数字 0或1 当且
  • centos7搭建svn服务器

    一 安装svn服务器 root svnserver yum y install subversion 查看svn 安装位置 可以用以下命令 root svnserver rpm ql subversion etc subversion et
  • Java中String类的使用

    目录 1 MS String 类中两种对象实例化的区别 1 1 直接赋值 1 2 构造方法 2 字符 字节与字符串 2 1 字符与字符串转换 2 2 字节与字符串转换 3 字符串常见操作 3 1 字符串比较 3 2 字符串查找 3 3 字符
  • HS BDC 【HDU - 3472】【混合半欧拉图构建欧拉图+最大流】

    题目链接 有N个字符 如果字符可以首尾相同字符相接组成一条链的话 那么就是说明是well done的 不然 就不是 所以考虑成一条边 我们把每个字符串考虑成有向边 又有些字符串是可以反转的 实际上可以把它当成是无向边来考虑 现在 就是要知道
  • idea 生成项目结构图

    Terminal中输入tree D mybatis plus generator demo gt tree 文件夹 PATH 列表 卷序列号为 ECE0 24D1 D idea inspectionProfiles libraries mv
  • Java如何将一个对象的所有字段值赋值给另一个对象?

    我们开发的时候可能需要进行对象值的复用 下面给大家介绍一个方法 就是使用BeanUtils public static void main String args throws Exception Student student new S
  • MySQL 经典练习 50 题(完美解答版)

    一 创建数据库和表 数据库 学生表 student 课程表 course 教师表 teacher 成绩表 score 表关系 创建数据库和表 创建数据库 drop database if exists mysql test cascade
  • 51单片机EEPROM(I²C总线通信)AT24C02数据存储

    一 存储器介绍 补充 1 易失性存储器 RAM 存储速度特别快但掉电丢失 SRAM 运行速度最快 用于电脑CPU 高速缓存 单片机中的SRAM 定义一个变量就会存在SRAM中 使用触发器做的 存储容量小 成本高 DRAM 运行速度仅次于SR
  • Linux的GPIO子系统解析 ( 一 ) 之 gpiolib.c

    文章目录 Linux的GPIO子系统解析 一 之 gpiolib c 绪论 关于GPIO子系统库文件的gpiolib c解析 drivers gpio gpiolib c gpio desc结构体 gpio chip结构体 gpio ens
  • ModbusSlave安装及使用指南正式版带序列码

    ModbusSlave是一个从站设备仿真软件 它用于接收主设备的命令包 并回送数据包 可用于测试和调试Modbus主站设备 便于观察Modbus通信过程中的各种报文 ModbusSlave支持ModbusRTU ASCII TCP IP等协
  • 基于Xposed hook 实时监测微信消息的三种策略

    本文以微信版本6 7 3为例进行分析有hook 大部分做微信机器人的话 首先要实时抓取微信的消息 在这里展示三种方式对微信的消息进行hook 1 基于UI层拉取加载进行监听 2 基于微信dao层调用的保存进行监听 3 基于数据库的插入保存进
  • 决策树 prepruning_数据挖掘入门系列教程(三点五)之决策树

    本来还是想像以前一样 继续学习 Python数据挖掘入门与实践 的第三章 决策树 但是这本书上来就直接给我怼了一大串代码 对于决策树基本上没有什么介绍 可直接把我给弄懵逼了 主要我只听过决策树还没有认真的了解过它 这一章节主要是对决策树做一