2016-06-19 23:47:06 zhang20072844 阅读数 4906
  • 轻轻松松学习决策树

    化难为易。用更简单的思路来理解决策树,用统一的视角来分析分类决策树和回归决策树。并同时理解决策树的本质局限。 环境搭建。多种决策树的Python scikit例子代码的解读。对决策树可视化结果的解读更是丝丝入扣。 介绍人工智能实践中,企业真实采用的产品设计模式,以及相应的技术细节。 讲解方式上很形象哦。

    161 人正在学习 去看看 易文星

决策树是一种基本的分类与回归方法。这里主要讨论用于分类的决策树。

优点:具有可读性,分类速度快;

决策树学习通常包括三个步骤:特征选择、决策树的生成和决策树的修剪;

决策树学习 的思想来源主要是ID3算法、C4.5算法以及CART算法;

1 理论学习

决策树模型:

分类决策树模型是一种描述对实例进行分类的树形结构。决策树有节点(node)和有向边(directed edge)组成。节点有两种类型:内部节点和叶节点。内部节点标识一个特征或属性,叶节点标识一个类;

用决策树分类,从根节点开始,对实例的某一特征进行测试,根据测试结果,将实例分配到其子节点;这时,每一个子节点对应该特征一个取值,如此递归低对实例进行测试并分配,直至达到叶子节点。最后实例被分到叶节点的类中。



决策树的if-then规则

可以将决策树看成一个if-then规则的集合;规则如下:将决策树的根节点到叶节点的每一条路径建立一条规则;路径上内部节点的特征对应着规则的条件,而叶节点的类对应着规则的结论。if-then规则集合有一个重要的性质:互斥并且完备;这就是每一个实例都被一条路径或者一条规则所覆盖,而且只被一条路径或者一条规则所覆盖。

决策树与条件概率分布:

决策树还表示给定特征条件下类的条件概率分布。这一条件概率分布定义在特征空间的一个划分上。将特征空间划分为互不相交的单元区域,并在每个单元定义一个类的概率分布就构成了一个条件概率分布。决策树的一条路径对应于划分中的一个单元。决策树所表示的条件概率有各个单元给定条件下的类的条件概率分布组成。假设X为标识特征的随机变量,Y为表示类的随机变量,那么这个条件概率分布可以表示为P(Y|X)。X取值给定划分下单元的集合,Y取值类的集合。

下图表示了特种空间的一个划分。大正方形表示特征空间。这个大正方形被若干个小矩形分割,每个小矩形表示一个单元。特征空间划分上的单元构成了一个集合,X取值为单元的集合。假设只有两类正类负类,Y=+1 -1;小矩形数字表示单元的类。第二个图表示给定条件下类的条件概率分布。P(Y=+1|X=c)>0.5时属于正类,实际上对应的就是矩形框的面积。

决策树的学习:

决策树的学习,假设给定训练数据集


其中为输入实例(特征向量),n为特征个数,为类的标记,N为样本容量.。学习的目标是根据给定的训练数据集构建一个决策树模型,使它能够对实例进行正确的分类。

决策树学习本质上试从训练数据集中归纳出一组分类规则。与训练数据集不相矛盾的决策树可能有多个,也可能一个也没有。我们需要的是一个与训练数据矛盾较小的决策树,同时具有很好的泛化能力。从另一个角度看,决策树学习是有训练数据集估计条件概率模型。基于特征空间划分的类的条件概率模型有无数个,我们选择的条件概率模型应该不仅对训练数据有很好的拟合,而且对未知数据也有很好的预测。

决策树学习的损失函数通常是正则化的极大似然函数。决策树学习的策略是一损失函数为目标函数的最小化。

决策树学习算法通常是一个递归低选择最优特征,并根据特征对数据进行分割,使得对应各个子数据集有一个最好的分类过程。首先构建根节点,将训练数据放到根节点,选择一个最优特征,按照这个特征将训练集分为各个子集,使各个子集有一个当前条件下最好的分类。如果已经能够被基本正确分类,那么构建叶子节点,并将这些子集分到所对应的叶节点中去;如果还有子集不能被正确分类,那么对子集继续选择最优特征,直到没有合适的特征为止。
决策树表示一个概率分布,深浅不同的决策树对应着不同复杂度的概率模型。决策树的生成对应于模型的局部选择,决策树的剪枝对应于模型的全局选择。决策树的生成只考虑局部最优,相对地,决策树的剪枝则考虑全局最优。

特征选择:

特征选择在于选取对训练数据具有分类能力的特征。这样可以提高决策树学习的效率。
如果利用一个特征进行分类的结果与随机分类的结果没有很大差别,则呈这个特征是没有分类能力的。经验上扔掉这样的特征对决策树学习的精度影响不大。通常特征选择的准则是信息增益或信息增益比。

例子:


希望通过所给的训练数据学习一个贷款申请的决策树,用以对未来的贷款申请进行分类,即当新的客户提出贷款申请时,根据申请人的特征利用决策树决定是否批准贷款申请。

下图是从上表学习到的两个可能的决策树,分别由两个不同特征的根节点构成。a表示根节点的特征是年龄,有3个取值,对应于不同的取值有不同的子节点。b表示的根节点的特征是有工作,有两个取值,对应于不同的取值有不同的节点。两个决策树都可以从此延续下去。问题是,究竟选择哪个特征更好些,这就要求确定选择特征的准则。直观上,如果一个特征具有更好的分类能力,或者说,按照这一特征将训练数据集分割成子集,是的各个子集在当前条件下有最好的分类,那么久应该选择这个特征。信息增益就能很好地表示这一直观的准则。


信息增益:

为了方便说明,先给出熵和条件熵的定义。
在信息论与概率统计中,熵是表示随机变量不确定性的度量。设X是一个取有限个值的离散随机变量,其概率分布为P(X=xi)=pi
则随机变量X的熵的定义为

熵只依赖于X的分布,而与X的取值无关,所以X的熵记做H(p)

熵越大,随机变量的不确定性就越大,从定义可以验证
0<=H(P)<=logn
熵H(P)随着概率p变化的曲线如下图:

设随机变量(X,Y),其联合概率分布为

条件熵H(Y|X)表示在已知随机变量X的条件下随机变量Y的不确定性。随机变量X给定的条件下随机变量Y的条件熵H(Y|X),定义为X给定条件下Y的条件概率分布的熵对X的数学期望



信息增益表示得知特征X的信息而使的类Y的信息不确定性减少的程度。


信息增益:
特征A对训练数据集D的信息增益g(D,A),定义为集合D的经验熵H(D)与特征A给定条件下D的经验条件熵H(D|A)之差,即
g(D,A)=H(D)-H(D|A)

H(D)表示数据集D的不确定性,H(D|A)表示在特征A条件下对数据集D进行分类的不确定性。那么他们的差,即信息增益,表示由于特征A而使得对数据集D的分类的不确定性减少的程度。显然,对于数据集D而言,信息增益依赖于特征,不同的特征往往具有不同的信息增益。信息增益大的特征具有更强的分类能力。







信息增益比:




决策树生成:

ID3算法
核心就是在决策树各个节点上应用信息增益准则选择特征,递归低构建决策树。具体方法:从根节点开始,对节点计算所有可能的特征信息增益,选择信息增益最大的特征作为节点的特征,由该特征的不同取值作为子节点;在对子节点递归调用以上方法,构建决策树;知道所有特征信息增益均很小或没有特征可以选择为止,最后得到一个决策树。

C4.5算法,和ID3类似,不同是使用信息增益比来选择最优特征


决策树的剪枝:


为了防止过拟合,同时考虑模型复杂度





2019-05-04 11:44:14 weixin_40187450 阅读数 70
  • 轻轻松松学习决策树

    化难为易。用更简单的思路来理解决策树,用统一的视角来分析分类决策树和回归决策树。并同时理解决策树的本质局限。 环境搭建。多种决策树的Python scikit例子代码的解读。对决策树可视化结果的解读更是丝丝入扣。 介绍人工智能实践中,企业真实采用的产品设计模式,以及相应的技术细节。 讲解方式上很形象哦。

    161 人正在学习 去看看 易文星

决策树算法的两个阶段

决策树算法的两个阶段

决策树基本术语(根节点、叶子节点、内部节点)

决策树基本术语(根节点、叶子节点、内部节点)

信息熵概念和直观理解

信息熵概念和直观理解

信息熵和基尼系数

熵:纯度\不纯度;不确定性
熵是用来度量不确定性,当熵越大,概率说X=xi的不确定性越大,反之越小;在机器学期中分类中说,熵越大即这个类别的不确定性更大,反之越小

基尼不纯度表示一个随机选中的样本在子集中被分错的可能性。
基尼不纯度为这个样本被选中的概率乘以它被分错的概率。
当一个节点中所有样本都是一个类时,基尼不纯度为零。

信息熵和基尼系数

决策树要考虑的问题(1):

ID3

ID3是基本的决策树构建算法,作为决策树经典的构建算法,其具有结构简单、清晰易懂的特点。
虽然ID3比较灵活方便,但是有以下几个缺点:
(1)采用信息增益进行分裂,分裂的精确度可能没有采用信息增益率进行分裂高
(2)不能处理连续型数据,只能通过离散化将连续性数据转化为离散型数据
(3)不能处理缺省值
(4)没有对决策树进行剪枝处理,很可能会出现过拟合的问题

C4.5和CART算法

1.连续值属性处理
将属性取值进行排序,按大于t和小于t分为两个子集,划分点t由最大化信息增益来确定,需要注意的是,对于连续属性,该属性可在决策树中多次使用。
2.缺省值属性处理
判断属性优劣(如计算信息增益)只考虑没有缺省值的样本,且相应地乘以除去缺省值所占的比例做权重,以保证缺省值不要过多;
对于含缺省值样本对于该属性的划分,则根据该属性各种取值的分布情况,以不同的概率划分到不同的结点(划分后样本带权)。
C4.5和CART算法1
C4.5和CART算法2
3. 三种划分属性选择指标:
(1) 信息增益Gain(D,a):
信息增益越大,纯度提升越高,可以用最高信息增益选择属性。
缺点:属性可取值越多,得到的信息熵越大,用其划分后信息增益越高,故此方法对属性可取值更多的属性有所偏好
(2) 增益率Gain_ratio(D,a):
信息增益除以属性的固有值(以属性a做随机变量,由集合中a属性各个取值所占的比例计算的信息熵),a可取数值越多,固定值越大,在一定程度上抑制了上述偏好
缺点:对可取数值较小的属性有偏好。故实际上,采用先找信息增益高于平均水平的属性,再从中找增益率高的
(3) 基尼指数Gini(D):
基尼指数表示一个随机选中的样本在子集中被分错的可能性。当一个节点中所有样本都是一个类时,基尼不纯度为零。

划分属性标准:
  1. 信息增益:ID3
    在这里插入图片描述
  2. 信息增益率:C4.5
    Gainratio(D,a)=Gain(D,a)/Ha(D)
    Ha(D)=在这里插入图片描述
  3. 基尼系数:CART
    基尼系数

决策树要考虑的问题(2)

预防过拟合的方法:剪枝
(1) 预剪枝:在构造决策树的同时进行剪枝。所有决策树的构建方法,都是在无法进一步降低熵的情况下才会停止创建分支的过程,为了避免过拟合,可以设定一个阈值,熵减小的数量小于这个阈值,即使还可以继续降低熵,也停止继续创建分支。
优点:分支较少,减小过拟合风险,也减少了训练时间开销和测试时间开销
缺点:带来了欠拟合的风险(当前划分虽不能提升泛化能力,但继续划分呢?)
(2) 后剪枝:生成完整的决策树后自底向上对非叶结点考察,若替换为叶结点能带来泛化性能提升,则替换。
优点:比预剪枝分支多,欠拟合风险小,泛化性能往往优于预剪枝
缺点:训练时间开销大得多
在这里插入图片描述

决策树常用算法比较

决策树常用算法比较

集成学习:通过随机森林提高准确率

决策树是建立在已知的历史数据及概率上的,一课决策树的预测可能会不太准确,提高准确率最好的方法是构建随机森林(Random Forest)。
所谓随机森林就是通过随机抽样的方式从历史数据表中生成多张抽样的历史表,对每个抽样的历史表生成一棵决策树。由于每次生成抽样表后数据都会放回到总表中,因此每一棵决策树之间都是独立的没有关联。将多颗决策树组成一个随机森林。当有一条新的数据产生时,让森林里的每一颗决策树分别进行判断,以投票最多的结果作为最终的判断结果。以此来提高正确的概率。

随机森林

决策树的优缺点

决策树算法的优点:

1)简单直观,生成的决策树很直观。
 2)既可以处理离散值也可以处理连续值。很多算法只是专注于离散值或者连续值。
 3)可以处理多维度输出的分类问题。
 4)相比于神经网络之类的黑盒分类模型,决策树在逻辑上可以得到很好的解释
 5)可以交叉验证的剪枝来选择模型,从而提高泛化能力。
 6)对于异常点的容错能力好,健壮性高。

决策树算法的缺点:

1)决策树算法容易过拟合:通过设置节点最少样本数量、不纯度/熵阈值、限制决策树深度来改进。
 2)决策树会因为样本发生一点点的改动,就会导致树结构的剧烈改变:通过随机森林等算法。
3)寻找最优的决策树是一个NP难题,通过启发式方法,容易陷入局部最优:通过随机森林算法等方法改善。
 4)有些比较复杂的关系,决策树很难学习,比如异或:通过神经网络等方法解决。
 5)如果某些特征的样本比例过大,生成决策树容易偏向于这些特征:可通过调节样本权重来改善。

决策树算法python库实现:

import numpy as np        # 导入numpy库
import matplotlib.pyplot as plt      # 导入matplotlib.pylab库
from sklearn.tree   import DecisionTreeRegressor #导入决策树库
1.数据预处理(初始化)
rng = np.random.RandomState(1)          #随机数产生器 
X = np.sort(5 * rng.rand(400, 1), axis=0)   #随机产生400个数的数据集X,并排序
y = np.sin(X).ravel()      
dtr= DecisionTreeRegressor(max_depth=5)     #决策树回归器(均方差mse/mae)
dtr= DecisionTreeClassifier(max_depth=5)       #决策树分类器(基尼系数或熵)

主要参数:
max_depth: 树最大深度,可选,缺省None,
min_samples_split : 分割内部节点所需最少样本数,可选,缺省2
min_samples_leaf : 成为叶子节点所需最少样本, 可选, 缺省1
max_features : 寻找最佳分割时考虑的特征数目, 可选, 缺省None: float/比例, ‘sqrt’/sqrt(n_features), ‘log2’/log2(n_features)
min_impurity_decrease : 如果节点分割导致不纯度减少超过此值,将进行分割,可选, 缺省0.0
presort : 预排序,加速寻找最佳分割,可选,缺省False, 大数据集降低训练过程, 小训练集或受限深度,可加快训练
random_state: 缺省None; 若int, 随机数产生器seed, 若RandomStates实例, 随机数产生器, 若None, np.random

2. 调用库函数计算:建立模型并计算
dtr.fit(X,y)       # 调用库函数决策树算法: 分类器y是整数或string;回归器y是浮点数
dtr.predict(X)   # 预测样本类别或回归值,返回shape(n_samples)或(n_samples,n_outputs)
dtr.decision_path(X)   #返回决策路径,返回shape = [n_samples, n_nodes]
dtr.score(X, y)      #返回预测结果的R^2(1-u/v). u=((y_true - y_pred) ** 2).sum() 
                                             v=((y_true - y_true.mean()) ** 2).sum()
dtr.apply(X)         # 返回每个样本预测为叶子的索引
dtr.n_features_    # 执行’fit’时的特征数
dtr.n_outputs_      # 执行’fit’时的输出数
dtr.tree_         # 树对象
3.计算并展示结果(分类结果)
# 计算据测模型,深度=5
dtr_2 = DecisionTreeRegressor(max_depth=5)
dtr_2.fit(X, y)

# 预测结果
X_test = np.arange(0.0, 5.0, 0.01)[:, np.newaxis]
y_2 = dtr_2.predict(X_test)

# 画出图形
plt.figure('决策树回归深度=5')
plt.scatter(X, y, s=20, c="blue", label="原数据")
plt.plot(X_test, y_2, color="red", label="深度=5", linewidth=2)
plt.xlabel("data")
plt.ylabel("target")
plt.title("深度=5,准确率%.2f"%(dtr_2.score(X,y)*100)+'%')
plt.legend()
plt.show()

决策树回归深度=2
决策树回归深度=5

2019-04-10 16:21:14 weixin_42562500 阅读数 307
  • 轻轻松松学习决策树

    化难为易。用更简单的思路来理解决策树,用统一的视角来分析分类决策树和回归决策树。并同时理解决策树的本质局限。 环境搭建。多种决策树的Python scikit例子代码的解读。对决策树可视化结果的解读更是丝丝入扣。 介绍人工智能实践中,企业真实采用的产品设计模式,以及相应的技术细节。 讲解方式上很形象哦。

    161 人正在学习 去看看 易文星

第二章决策树用matplotlib画图的理解

作为一个小白呢,确实对于我们来说第二章画图部分有很大的难度,个人也是花了很多时间在CSDN上反正是各种找,最后基本上弄明白了,就是想给同样是小白的人节约一点时间,但是深入理解的时间不能少哦。

决策树matplotlib画图代码

结果图

图片
第一棵树
第二棵树:

具体代码

# -*- coding: utf-8 -*-
"""
Created on Mon Apr  1 18:56:26 2019

@author: 风飘  小谭谭
"""

import matplotlib.pyplot as plt


#这里是对绘制是图形属性的一些定义
#boxstyle为文本框的类型,sawtooth是锯齿形,fc是边框线粗细  
decisionNode = dict(boxstyle = 'sawtooth',fc = '0.8') #定义decision节点的属性
leafNode = dict(boxstyle='round4',fc='0.8')           #定义leaf节点的属性  
arrow_args = dict(arrowstyle='<-')                    #定义箭头方向 与常规的方向相反   

#声明绘制一个节点的函数
'''
annotate是关于一个数据点的文本 相当于注释的作用 
nodeTxt:即为文本框或锯齿形里面的文本内容
centerPt:即为子节点的坐标
parentPt:即为父节点的坐标
nodeType:是判断节点还是叶子节点
'''
def 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 createPlot():
    fig = plt.figure(1,facecolor='white')  #新建绘画窗口  窗口名为figure1  背景颜色为白色
    fig.clf()           #清空绘图区
     #创建了属性ax1  functionname.attribute的形式是在定义函数的属性,且该属性必须初始化,否则不能进行其他操作。
    createPlot.ax1 = plt.subplot(111,frameon=False)        #创建11列新的绘图区 且图绘于第一个区域 frameon表示是否绘制坐标轴矩形 True代表绘制 False代表不绘制
    plotNode('a decision node',(0.5,0.1),(0.1,0.5),decisionNode)#调用画节点的函数
    plotNode('a leaf node',(0.8,0.1),(0.3,0.8),leafNode )
    plt.show()   #画图
'''
#--------鉴于python3与python2的不同  python3 dict_keys支持iterable,而不支持indexable
#故先将myTree.keys()返回得到的dict_keys对象转化为列表
#否则会报TypeError: 'dict_keys' object does not support indexing的错误

#获得叶节点的数目
#是一个累加的过程
def getNumLeafs(myTree):
    numLeafs = 0                #声明叶节点的个数

    #python3
    firstSides = list(myTree.keys())    #得到树所有键的列表
    firstStr = firstSides[0]            #取第一个键
    #pyton2:firstStr = myTree.keys()[0]
    secondDict = myTree[firstStr]       #得到第一个键所对应的的值

    for key in secondDict.keys():              #循环遍历secondDict的键
        if type(secondDict[key]).__name__ == 'dict': #判断该键对应的值是否是字典类型
            numLeafs += getNumLeafs(secondDict[key]) #若是则使用递归进行计算
        else:
            numLeafs += 1                           #不是则代表当前就是叶子节点,进行加1即可

    return numLeafs                                 #返回叶子结点数目


#获得叶节点的深度
#因为某一层不一定是最深的,所以引入thisDepth
#是一个求最值的过程
def getTreeDepth(myTree):
    maxDepth = 0                        #声明最大深度并赋值为0
    firstSides = list(myTree.keys())
    firstStr = firstSides[0]
    secondDict = myTree[firstStr]

    for key in secondDict:
        if type(secondDict[key]).__name__ == 'dict':
            thisDepth =1 + getTreeDepth(secondDict[key]) 
        else:
            thisDepth = 1
        if thisDepth > maxDepth:
            maxDepth = thisDepth

    return maxDepth

#预先存储树的信息
def retrieveTree(i):
    listOfTrees =[{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}},
                  {'no surfacing': {0: 'no', 1: {'flippers': {0: {'head': {0: 'no', 1: 'yes'}}, 1: 'no'}}}}
                  ]
    return listOfTrees[i]
#plotTree函数

#在父子节点间填充文本
'''
cntrPt:子节点位置坐标
parentPt:父节点位置坐标
txtString:文本信息即为图中的0,1
'''
def plotMidText(cntrPt,parentPt,txtString):
    xMid = (parentPt[0]-cntrPt[0])/2.0 + cntrPt[0]      #文本填充的x坐标
    yMid = (parentPt[1]-cntrPt[1])/2.0 + cntrPt[1]       #文本填充的y坐标
    createPlot.ax1.text(xMid,yMid,txtString)#在(xMid,yMid)位置填充txtString文本



#画树的函数
'''
myTree: 要进行绘制的树
parentPt:父节点位置坐标
nodeTxt:文本内容

plotTree.totalW: 整棵树的叶子节点数(常量)
plotTree.totalD : 整棵树的深度(常量)


'''
def plotTree(myTree,parentPt,nodeTxt):
    numLeafs = getNumLeafs(myTree)   #求得myTree的叶子的个数  注意这可不是我们之前所说的那颗最大的树 谁调用它谁是myTree
    depth = getTreeDepth(myTree)     #求得myTree的深度 
    #python3.6的原因,与书中有两行不一样
    #-----
    firstSides = list(myTree.keys())  #即为['no surfacing']
    firstStr = firstSides[0]        #得到第一个键 也就是第一个判断节点 即myTree的根节点即为'no surfacing'
    #-----

    cntrPt = (plotTree.xOff + (1.0 + float(numLeafs))/2/plotTree.totalW,plotTree.yOff) #计算子节点的坐标       
    plotMidText(cntrPt,parentPt,nodeTxt)  #对判断节点进行的绘制其与其父节点之间的文本信息   此处第一个节点与父节点重合(0.5,1.0)的设置 所以会没有效果 也恰好符合题意
    plotNode(firstStr,cntrPt,parentPt,decisionNode)     #绘制子节点
    secondDict = myTree[firstStr]                       #得到该节点以下的子树
    plotTree.yOff = plotTree.yOff - 1.0/plotTree.totalD #深度改变 纵坐标进行减一层

    #循环遍历各个子树的键值
    for key in secondDict.keys():
        if type(secondDict[key]).__name__ == 'dict': #如果该子树下边仍为一颗树(即字典类型)
            plotTree(secondDict[key],cntrPt,str(key))#进行递归绘制
        else:
            plotTree.xOff = plotTree.xOff + 1.0/plotTree.totalW
            plotNode(secondDict[key],(plotTree.xOff,plotTree.yOff),cntrPt,leafNode)#绘制叶子节点 (plotTree.xOff,plotTree.yOff)代表叶子节点(子节点)坐标,cntrPt代表判断节点父节点坐标
            plotMidText((plotTree.xOff,plotTree.yOff),cntrPt,str(key))#在父子节点之间填充文本信息

    plotTree.yOff = plotTree.yOff + 1.0/plotTree.totalD #循环结束  



#声明绘制图像函数,调用绘制节点函数
def createPlot(inTree):
    fig = plt.figure(1,facecolor='white')  #新建绘画窗口  窗口名为figure1  背景颜色为白色
    fig.clf()           #清空绘图区
    axprops = dict(xticks=[],yticks=[]) #定义横纵坐标轴
     #创建了属性ax1  functionname.attribute的形式是在定义函数的属性,且该属性必须初始化,否则不能进行其他操作。
    createPlot.ax1 = plt.subplot(111,frameon=False,**axprops)        #创建11列新的绘图区 且图绘于第一个区域 frameon表示不绘制坐标轴矩形 定义坐标轴为二维坐标轴
    plotTree.totalW = float(getNumLeafs(inTree))  #计算树的叶子数即为3
    plotTree.totalD = float(getTreeDepth(inTree)) #计算树的深度即为2

    plotTree.xOff = -0.5/plotTree.totalW    #赋值给绘制叶子节点的变量为-0.5/plotTree.totalW 
    plotTree.yOff = 1.0                     #赋值给绘制节点的初始值为1.0 

    plotTree(inTree,(0.5,1.0),'')              #调用函数plotTree 且开始父节点的位置为(0.5,1.0) 

    plt.show()   #画图

前面代码的注释的相对较为详细,其中对于难的代码的简单解释
1.cntrPt = (plotTree.xOff + (1.0 + float(numLeafs))/2/plotTree.totalW,plotTree.yOff)
其实plotTree.xOff第一次为-1/6,即为向右平移1/6,plotTree.yOff第一次为1,经过上面这个cntrPt = (plotTree.xOff + (1.0 + float(numLeafs))/2/plotTree.totalW,plotTree.yOff)
代码可得cntrPt =(-1/6+(1+3)*1/2 *1/3,1)即为(1/2,1)对照即可得出。
2.parentPt的坐标已经在代码 plotTree(inTree,(0.5,1.0),’’)中得出为(0.5,1.0)后面根据代码以此类推
整个过程相当于是已知决策树来画,就是指已经知道树节点和叶子节点的数目,根据它们的数目来划分整个画布,并且在x轴以1/叶子节点数目来表示每个叶子之间的x轴距离,为什么plotTree.xOff = -0.5/plotTree.totalW 其中的负号指向右平移,半个叶子节点的距离而叶子之间的距离计算也是以半个叶子节点的距离为单位,看第一个叶子结点的距离与第二个叶子节点的距离相差几个,即第二个就向右平移几个,在叶子节点中间的根节点,即在它们的中间。对于y轴,是根据循环的层数来决定,在同一个循环里即为同一层。

以上解释有一点混乱,建议结合图和代码一步一步把坐标算出来基本上就理解了。谢谢!

2017-06-09 17:01:09 qq_34896915 阅读数 634
  • 轻轻松松学习决策树

    化难为易。用更简单的思路来理解决策树,用统一的视角来分析分类决策树和回归决策树。并同时理解决策树的本质局限。 环境搭建。多种决策树的Python scikit例子代码的解读。对决策树可视化结果的解读更是丝丝入扣。 介绍人工智能实践中,企业真实采用的产品设计模式,以及相应的技术细节。 讲解方式上很形象哦。

    161 人正在学习 去看看 易文星
一、决策树阐述、特性、优缺点:
1.阐述、特性:
决策树是一种基本的分类和回归算法,主要包含三个部分:特征选择、决策树的生成和剪枝。
首先,决策树的构成是由和边,结点包括内部结点和外部结点,内部结点表示特征,外部结点表示类别。
其次,决策树学习本质是从训练数据中归纳出一组分类规则,使它与训练数据矛盾较小的同时具有较强的泛化能力。另一个数学角度:由训练数据集估计条件概率,是一种判别式模型。
损失函数是正则化的极大似然函数。学习的策略是损失函数最小化。(NP难问题,通常采用启发式算法,SMO就是一个启发式算法,包括特、生、剪三个步骤)
最后,决策树算法思想是递归的选择最有特征,根据最优特征对数据进行分割,这一过程对应着决策树的构建和特征空间的划分。
决策树有可能产生过拟合,所以需要剪枝,减去过于细分的结点。
2、优缺点
优点:构造简单、判别速度快; 对数据不需要任何加工; 对于unbalance 的数据效果好。
缺点:泛化能力差,容易过拟合; 对新增的样本,需要调整整棵树的结构。

二、特征选择:
特征选择的准则是:信息增益或信息增益比,选择使信息增益最大的特征分割。
1、信息增益:
熵:数据的不一致性,(随机变量的不确定性)。
条件熵:在特征集合给定的条件下,数据集合非一致性。
信息增益:熵 — 条件熵 表示:在得知特征的条件下,使得数据分类的不确定性减少的程度。所以,信息增益越大表示特征的划分能力越强。
2、信息增益比:
因为用信息增益作为划分数据集的特征,可能会偏向于:选择取值较多的特征,用信息增益比可以矫正。
信息增益比:信息增益 / 关于当前特征取值的熵。
三、决策树的生成:
1) ID3:
选择信息增益最大的特征。
核心:在决策树的各个节点上利用信息增益准则选择特征,递归的构建决策树。
具体方法:从根节点开始,对结点计算所有可能的特征的信息增益,选择信息增益最大的特征作为当前结点的特征,由该特征的不同取值建立子节点(划分数据),再对子节点递归的调用以上方法,构建决策树。直到所有特征的信息增益都很小或没有特征可以选择为止。
相当于用极大似然估计进行概率模型的选择。
缺点:只有树的生成,容易过拟合;
偏向于选择 取值较多的特征。
2)C4.5:
用信息增益比来选择特征。
对ID3的一个改进。
3)CART(classification and regression tree )算法:
用基尼指数选择特征。
优点:不用提前确定权衡银子a,而是在剪枝的同时找到最优的a值。
步骤:1、决策树生成:基于训练数据集生成决策树,决策树要越大越好。(就是递归的生成二叉决策树的过程,回归用平方误差最小的准则,对分类用基尼指数最小的准则。)
2、决策树剪枝:用验证数据集对已生成的决策树进行剪枝,并生成最优子树。用最小损失函 数作为剪枝的标准。
1、cart 决策树生成:
(1)最小二乘回归树生成算法:(在训练数据集所在的输入空间中,递归的对每个区域划分为两个子区域,并决定每个子区域的输出值,构建决策二叉树)
输入:训练数据集D; 输出:回归树;
1)根据平方误差最小化准则寻找当前数据集的最优切分变量和切分点;
2)用选定的切分变量和切分点对数据进行划分,并决定每个划分区域相应的输出值c_m;
3)继续对两个划分的区域进行上面的步骤,直到满足条件;
4)将输入空间划分为M的区域,生成决策树:f(x)=求和(c_m * I)
(2)分类树的生成:
输入:训练数据集D,终止条件; 输出:分类决策树;
1)对给定的训练数据集,计算现有特征对数据集的基尼指数,对每个特征属性值都将数据划分两部分;2)在所有可能的特征和划分点中,选择基尼指数最小的作为最优特征和最优切分点。
将数据切分为两个子节点。3)对两个子节点递归的调用上面方法,直到满足停止条件;4)生成。
2、cart剪枝:
(从生成算法产生的决策树底端开始不断剪枝,直到根节点。生成了一个子树序列;利用交叉验证法在独立的验证数据集上岁子树进行测试,找出最优子树(损失函数最小的))
四、决策树的剪枝:
提出:决策树的生成算法递归的产生决策树,直到不能继续下去为止,这样的算法往往对训练数据的分类很准确,但是对未知的测试数据分类却没有那么准确,容易产生过拟合。
目的:解决过拟合,方法:考虑决策树的复杂度,对已经生成决策树进行简化。(过拟合的原因:建立决策树的过程中,过多的考虑如何选择特征,能对训练数据分类的更加准确,从而构建出过于复杂的决策树。)
实现原理:通过极小化决策树整体的损失函数或代价函数。(决策树生成只考虑了通过提高信息增益对训练数据进行更好的拟合,而决策树剪枝通过优化损失函数还考虑了减少模型复杂度。
决策树生成学习局部的模型,而决策树剪枝学习整体的模型。
代价函数 : Ca(T)=C(T)+a|T| =模型与训练数据的预测误差 + a*模型复杂度(较大的a促使选择较简单的模型) (C(T)一般有两种衡量方法,一种是熵,一种是基尼指数。)
算法步骤:输入:生成算法生成的整棵树、参数a。 输出:修剪后的子树。
1)计算每个节点的经验熵;2)递归的从树的叶节点向上回缩;
3)计算叶节点回缩到父节点的树的损失函数,和没回缩时的树的损失函数。如果回缩后更小,则进行剪枝,将父节点作为新的叶子结点。4)重复,直到不能继续,得到损失函数最小的子树
五、随机森林:
通过两个随机、构建多个次优树:
1)样本随机:随机选择样本,通过有放回的抽样,重复的选择部分样本来构建树;
2)特征随机:构建树的过程中,每次考察部分特征,不对树进行剪枝;
优点:训练速度快,不易过拟合;提高了泛化性能。
缺点:新增样本数据,需要调整整棵树。
2019-12-22 22:16:01 weixin_45516016 阅读数 49
  • 轻轻松松学习决策树

    化难为易。用更简单的思路来理解决策树,用统一的视角来分析分类决策树和回归决策树。并同时理解决策树的本质局限。 环境搭建。多种决策树的Python scikit例子代码的解读。对决策树可视化结果的解读更是丝丝入扣。 介绍人工智能实践中,企业真实采用的产品设计模式,以及相应的技术细节。 讲解方式上很形象哦。

    161 人正在学习 去看看 易文星

机器学习基础 - 决策树算法

1. 本章的主要学习内容为

  • 决策树:决策树、信息熵与最优划分、基尼系数、CART
  • 实现:决策树实现

2. 初始决策树

决策树是一个非常有意思的模型,它的建模思路是尽可能模拟人做决策的过程。因此决策树几乎没有任何抽象,完全通过生成决策规则来解决分类和回归问题。因为它的运行机制能很直接地被翻译成人类语言,即使对建模领域完全不了解的非技术人员也能很好地理解它。因此在学术上被归为白盒模型(white box model)。

2.1 什么是决策树

决策树是一种常见的机器学习算法,它的思想十分朴素,类似于我们平时利用选择做决策的过程。它是类似流程图的结构,其中每个内部节点表示一个测试功能,即类似做出决策的过程(动作),每个叶节点都表示一个类标签,即在计算所有特征之后做出的决定(结果)。标签和分支表示导致这些类标签的功能的连接。从根到叶的路径表示分类规则。比如下面这个“相亲决策树”:
在这里插入图片描述
由此我们可以看到,决策树的思想还是非常直观的。
用决策树分类:从根节点开始,对实例的某一特征进行测试,根据测试结果将实例分配到其子节点,此时每个子节点对应着该特征的一个取值,如此递归的对实例进行测试并分配,直到到达叶节点,最后将实例分到叶节点的类中。

2.2 决策树的本质

决策树学习本质上是从训练数据集中归纳出一组分类规则。与训练数据集不相矛盾的决策树(即能对训练数据进行正确分类的决策树)可能是0个或多个。我们需要找到一个与训练数据矛盾较小的决策树,同时具有很好的泛化能力。
从另一个角度看,决策树学习是由训练数据集估计条件概率模型。基于特征空间划分的类的条件概率模型有无穷多个。我们选择的条件概率模型应该不仅对训练数据有很好地拟合,而且对未知数据有很好地预测。

2.3 决策树的损失函数

与其他模型相同,决策树学习用损失函数表示这一目标。决策树学习的损失函数通常是正则化的极大似然函数。决策树学习的策略是以损失函数为目标函数的最小化。

关于极大似然函数:极大似然法是属于数理统计范畴,旨在由果溯因。把“极大似然估计”拆成三个词:极大(最大的概率)、似然(看起来是这个样子的)、估计(就是这个样子的),连起来就是:大概率看起来是这样的,那就是这样。
比如扔一枚骰子(骰子每个面上只标记1或2),现在告诉你扔了n次骰子其中有k次朝上的是1;然后问你这个骰子标记为1的面所占的比例w是多少?极大似然法的思想就是估计当w取值为多少的时候,k次朝上的可能性最大。具体计算方法就是对表达式求最大值,得到参数值估计值:一般就是对这个表达式求一阶导=0(二阶导<0);
这就是极大似然估计方法的原理:用使概率达到最大的那个概率值w来估计真实参数w。决策树生成的过程可以理解成对决策树模型的参数估计(就是基于特征空间划分的类的概率模型),根据训练数据的特征分布,选择使得模型最契合当前样本分布空间时的条件概率模型。

当损失函数确定以后,学习问题就变为在损失函数意义下选择最优决策树的问题。因为从所有可能的决策树中选取最优决策树是NP完全问题,所以现实中决策树学习算法通常采用启发式方法,近似求解这一最优化问题。这样得到的决策树是次最优的。

2.4 决策树的构建

决策树通常有三个步骤:

  • 特征选择
  • 决策树的生成
  • 决策树的修剪

决策树学习的算法通常是一个递归地选择最优特征,并根据该特征对训练数据进行分割,使得对各个子数据集有一个最好的分类的过程。这一过程对应着对特征空间的划分,也对应着决策树的构建。
这一过程对应着对特征空间的划分,也对应着决策树的构建。

  1. 开始:构建根节点,将所有训练数据都放在根节点,选择一个最优特征,按照这一特征将训练数据集分割成子集,使得各个子集有一个在当前条件下最好的分类。
  2. 如果这些子集已经能够被基本正确分类,那么构建叶节点,并将这些子集分到所对应的叶子节点去。
  3. 如果还有子集不能够被正确的分类,那么就对这些子集选择新的最优特征,继续对其进行分割,构建相应的节点,如此递归进行,直至所有训练数据子集被基本正确的分类,或者没有合适的特征为止。
  4. 每个子集都被分到叶节点上,即都有了明确的类,这样就生成了一颗决策树。

以上方法就是决策树学习中的特征选择和决策树生成,这样生成的决策树可能对训练数据有很好的分类能力,但对未知的测试数据却未必有很好的分类能力,即可能发生过拟合现象。我们需要对已生成的树自下而上进行剪枝,将树变得更简单,从而使其具有更好的泛化能力。具体地,就是去掉过于细分的叶结点,使其回退到父结点,甚至更高的结点,然后将父结点或更高的结点改为新的叶结点,从而使得模型有较好的泛化能力。。
决策树生成和决策树剪枝是个相对的过程,决策树生成旨在得到对于当前子数据集最好的分类效果(局部最优),而决策树剪枝则是考虑全局最优,增强泛化能力。
在对此有一定了解之后,我们先看看,如何在sklearn中将决策树用起来。然后再学习其中的细节。

2.5 在sklearn中使用决策树

数据引入及可视化

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets

iris = datasets.load_iris()
X = iris.data[:,2:] # iris有四个特征,这里取后两个,形成一个坐标点
y = iris.target
# 绘图
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.scatter(X[y==2,0],X[y==2,1])
plt.show()

在这里插入图片描述
进行分类

from sklearn.tree import DecisionTreeClassifier
# 创建决策树对象,最大深度max_depth为2层,criterion评判标准为entropy(熵)
dt_clt = DecisionTreeClassifier(max_depth=2,criterion='entropy')
# 将训练数据送给模型
dt_clt.fit(X,y)

# 绘制决策边界
def plot_decision_boundary(model, axis): # model是模型,axis是范围
    x0, x1 = np.meshgrid(
        np.linspace(axis[0], axis[1],int((axis[1]-axis[0])*100)).reshape(-1,1),
        np.linspace(axis[2], axis[3],int((axis[3]-axis[2])*100)).reshape(-1,1),
    )
    X_new = np.c_[x0.ravel(), x1.ravel()]

    y_predict = model.predict(X_new)
    zz = y_predict.reshape(x0.shape)

    from matplotlib.colors import ListedColormap
    custom_cmap = ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
    
    plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)

# 数据可视化    
plot_decision_boundary(dt_clt, axis=[0.5,7.5,0,3])
plt.scatter(X[y==0,0],X[y==0,1])
plt.scatter(X[y==1,0],X[y==1,1])
plt.scatter(X[y==2,0],X[y==2,1])
plt.show()

在这里插入图片描述
对于上图的数据可视化结果,我们可以直观地看到。y=1.75这条直线为一条决策边界,y大于1.75属于A类;y小于1.75的区域,被y=0.8划分,y<1.75||y>0.8属于B类;y<0.8属于C类。
决策树是一个非参数的决策算法,决策树可以解决分类问题,且天然支持多分类问题。决策树也可以解决回归问题,按照树的路径追踪到叶子结点,最终叶子节点对应一个数值,且回归问题的结果是一个具体的数值,就可以落在叶子结点的所有样本的平均值,作为回归的预测结果。
并且决策树具有非常好的可解释性。
那么提出一个问题:在构建决策树,进行特征选择划分时,究竟选择哪个特征更好些?
这就要求确定选择特征的准则。直观上,如果一个特征具有更好的分类能力,或者说,按照这一特征将训练数据集分割成子集,使得各个子集在当前条件下有最好的分类,那么就更应该选择这个特征。比如身高、长相、收入等。在找到特征维度之后,还要确定划分阈值,如收入定在多少,作为划分标准比较合适?
因此,首先找到一个维度,然后在维度上找到一个阈值。然后以这个维度的这个阈值为依据进行划分。核心问题是:
每个节点在哪个维度做划分?选好了维度,如何确定阈值呢?

3. 特征选择中的相关概念

特征选择,就是决策树的构造过程。
为了找到最优的划分特征,我们需要先了解一些信息论的知识。

  • 信息熵(information entropy)
  • 条件熵(conditional entropy)
  • 信息增益(information gain)
  • 信息增益率(information gain ratio)
  • 基尼指数(Gini index)

3.1 信息熵

熵是热力学中的概念,表示混乱程度。熵越大,热力系统中粒子无规则的运动越剧烈;熵越小,粒子越趋近于静止的状态。
引申到信息论和概率统计中,信息熵表示随机变量的不确定度。对于一组数据来说,越随机、不确定性越高,信息熵越大;不确定性越低,信息熵越小。为了计算熵,我们需要计算所有类别所有可能值所包含的信息期望值,著名的香农公式:
在这里插入图片描述

3.2 条件熵

设有随机变量(X, Y)。条件熵H(Y|X)表示在已知随机变量X的条件下随机变量Y的不确定性。
在这里插入图片描述
注意,与信息熵不同的是,条件熵是数学期望,而不是变量的不确定性。

3.3 信息增益

在划分数据集前后信息发生的变化称为信息增益,获得信息增益最高的特征就是最好的选择。
信息增益就是:
以某特征划分数据集前后的熵的差值
在这里插入图片描述
通过对信息增益的进一步理解,我们发现:对于待划分的数据集D,其经验熵H(D)是不变的,但是划分之后得到的条件熵H(D|A)是变化的(特征A的选择不同)。
条件熵H(D|A)越小,说明使用此特征划分得到的子集的不确定性越小(也就是纯度越高),因为得到的信息增益就越大。说明在决策树构建的过程中我们总是希望集合往最快到达纯度更高的子集合方向发展,因此我们总是选择使得信息增益最大的特征来划分当前数据集D。
信息增益偏向取值较多的特征。
原因:当特征的取值较多时,根据此特征划分更容易得到纯度更高的子集,因此划分之后的熵更低,由于划分前的熵是一定的,因此信息增益更大,因此信息增益比较偏向取值较多的特征。

3.4 信息增益率的定义

特征A对训练数据集D的信息增益比定义为:其信息增益g(D,A)与训练数据集D关于特征A的值的熵HA(D)之比,即:
在这里插入图片描述
信息增益比本质:是在信息增益的基础之上乘上一个惩罚参数。特征个数较多时,惩罚参数较小;特征个数较少时,惩罚参数较大。
信息增益比 = 惩罚参数 * 信息增益
所谓惩罚参数,是数据集D以特征A作为随机变量的熵的倒数,即:将特征A取值相同的样本划分到同一个子集中(之前所说数据集的熵是依据类别进行划分的)。
信息增益比的缺点是:偏向取值较少的特征。原因:当特征取值较少时HA(D)的值较小,因此其倒数较大,因而信息增益比较大。因而偏向取值较少的特征。
基于以上特点,在使用增益信息比时,并不是直接选择信息增益率最大的特征,而是现在候选特征中找出信息增益高于平均水平的特征,然后在这些特征中再选择信息增益率最高的特征。

3.5 基尼系数

基尼系数(Gini),也被称为基尼不纯度,表示在样本集合中一个随机选中的样本被分错的概率。
Gini系数越小表示集合中被选中的样本被分错的概率越小,也就是说集合的纯度越高,反之,基尼指数集合越不纯。
即:基尼指数(基尼不纯度)= 样本被选中的概率 * 样本被分错的概率
有如下公式:
在这里插入图片描述
对上述公式进行说明:
表示选中的样本属于k类别的概率,则这个样本被分错的概率是(1-pk)
因为样本集合中有k个类别,一个随机选中的样本可以属于这k个类别中的任意一个,因而累加所有的k个类别。
当二分类时,G=2p(1-p)
在这里插入图片描述

4. 剪枝

当训练数据量大、特征数量较多时构建的决策树可能很庞大,这样的决策树用来分类是否好?答案是否定的。
决策树是依据训练集进行构建的,为了尽可能正确地分类训练样本,结点划分过程将不断重复,有时会造成决策树分支过多。这就可能会把训练样本学的“太好”了,以至于把训练集自身的一些特点当作所有数据都具有的一般性质而导致过拟合。因此可主动去掉一些分支来降低过拟合风险。
决策树非常容易产生过拟合,实际所有非参数学习算法,都非常容易产生过拟合。
因此,对于决策树的构建还需要最后一步,即决策树的修剪。两个目的:降低复杂度,解决过拟合。
决策树的修剪,也就是剪枝操作,主要分为两种:

  • 预剪枝(Pre-Pruning)
  • 后剪枝(Post-Pruning)

接下来我们将详细地介绍这两种剪枝方法。

预剪枝是指在决策树生成过程中,对每个节点在划分前先进行估计,若当前节点的划分不能带来决策树泛化性能的提升,则停止划分并将当前节点标记为叶节点。
那么所谓的“决策树泛化性能”如何来判定呢?这就可以使用性能评估中的留出法,即预留一部分数据用作“验证集”以进行性能评估。
后剪枝是先从训练集生成一颗完整的决策树,然后自底向上地对非叶节点进行考察,若将该节点对应的子树完全替换为叶节点能带来决策树繁花性的提升,则将该子树替换为叶节点。
对比预剪枝和后剪枝,能够发现,后剪枝决策树通常比预剪枝决策树保留了更多的分支,一般情形下,后剪枝决策树的欠拟合风险小,泛华性能往往也要优于预剪枝决策树。但后剪枝过程是在构建完全决策树之后进行的,并且要自底向上的对树中的所有非叶结点进行逐一考察,因此其训练时间开销要比未剪枝决策树和预剪枝决策树都大得多。

4.1 Sklearn 实现

sklearn.tree:提供了决策树模型,用于解决分类和回归问题。

class sklearn.tree.DecisionTreeClassifier(criterion=’gini’, splitter=’best’, max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, class_weight=None, presort=False)[source]

参数说明如下:
criterion:特征选择标准,可选参数,默认是gini,可以设置为entropy。gini是基尼不纯度,是将来自集合的某种结果随机应用于某一数据项的预期误差率,是一种基于统计的思想。entropy是香农熵,也就是上篇文章讲过的内容,是一种基于信息论的思想。Sklearn把gini设为默认参数,应该也是做了相应的斟酌的,精度也许更高些?ID3算法使用的是entropy,CART算法使用的则是gini。
splitter:特征划分点选择标准,可选参数,默认是best,可以设置为random。每个结点的选择策略。best参数是根据算法选择最佳的切分特征,例如gini、entropy。random随机的在部分划分点中找局部最优的划分点。默认的”best”适合样本量不大的时候,而如果样本数据量非常大,此时决策树构建推荐”random”。
max_features:划分时考虑的最大特征数,可选参数,默认是None。寻找最佳切分时考虑的最大特征数(n_features为总共的特征数),有如下6种情况:
如果max_features是整型的数,则考虑max_features个特征;
如果max_features是浮点型的数,则考虑int(max_features * n_features)个特征;
如果max_features设为auto,那么max_features = sqrt(n_features);
如果max_features设为sqrt,那么max_featrues = sqrt(n_features),跟auto一样;
如果max_features设为log2,那么max_features = log2(n_features);
如果max_features设为None,那么max_features = n_features,也就是所有特征都用。一般来说,如果样本特征数不多,比如小于50,我们用默认的”None”就可以了,如果特征数非常多,我们可以灵活使用刚才描述的其他取值来控制划分时考虑的最大特征数,以控制决策树的生成时间。
max_depth:决策树最大深,可选参数,默认是None。这个参数是这是树的层数的。层数的概念就是,比如在贷款的例子中,决策树的层数是2层。如果这个参数设置为None,那么决策树在建立子树的时候不会限制子树的深度。一般来说,数据少或者特征少的时候可以不管这个值。或者如果设置了min_samples_slipt参数,那么直到少于min_smaples_split个样本为止。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。常用的可以取值10-100之间。
min_samples_split:内部节点再划分所需最小样本数,可选参数,默认是2。这个值限制了子树继续划分的条件。如果min_samples_split为整数,那么在切分内部结点的时候,min_samples_split作为最小的样本数,也就是说,如果样本已经少于min_samples_split个样本,则停止继续切分。如果min_samples_split为浮点数,那么min_samples_split就是一个百分比,ceil(min_samples_split * n_samples),数是向上取整的。如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。
min_weight_fraction_leaf:叶子节点最小的样本权重和,可选参数,默认是0。这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。
max_leaf_nodes:最大叶子节点数,可选参数,默认是None。通过限制最大叶子节点数,可以防止过拟合。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征分成多的话,可以加以限制,具体的值可以通过交叉验证得到。
class_weight:类别权重,可选参数,默认是None,也可以字典、字典列表、balanced。指定样本各类别的的权重,主要是为了防止训练集某些类别的样本过多,导致训练的决策树过于偏向这些类别。类别的权重可以通过{class_label:weight}这样的格式给出,这里可以自己指定各个样本的权重,或者用balanced,如果使用balanced,则算法会自己计算权重,样本量少的类别所对应的样本权重会高。当然,如果你的样本类别分布没有明显的偏倚,则可以不管这个参数,选择默认的None。
random_state:可选参数,默认是None。随机数种子。如果是证书,那么random_state会作为随机数生成器的随机数种子。随机数种子,如果没有设置随机数,随机出来的数与当前系统时间有关,每个时刻都是不同的。如果设置了随机数种子,那么相同随机数种子,不同时刻产生的随机数也是相同的。如果是RandomState instance,那么random_state是随机数生成器。如果为None,则随机数生成器使用np.random。
min_impurity_split:节点划分最小不纯度,可选参数,默认是1e-7。这是个阈值,这个值限制了决策树的增长,如果某节点的不纯度(基尼系数,信息增益,均方差,绝对差)小于这个阈值,则该节点不再生成子节点。即为叶子节点 。
presort:数据是否预排序,可选参数,默认为False,这个值是布尔值,默认是False不排序。一般来说,如果样本量少或者限制了一个深度很小的决策树,设置为true可以让划分点选择更加快,决策树建立的更加快。如果样本量太大的话,反而没有什么好处。问题是样本量少的时候,我速度本来就不慢。所以这个值一般懒得理它就可以了。
除了这些参数要注意以外,其他在调参时的注意点有:
当样本数量少但是样本特征非常多的时候,决策树很容易过拟合,一般来说,样本数比特征数多一些会比较容易建立健壮的模型如果样本数量少但是样本特征非常多,在拟合决策树模型前,推荐先做维度规约,比如主成分分析(PCA),特征选择(Losso)或者独立成分分析(ICA)。这样特征的维度会大大减小。再来拟合决策树模型效果会好。
推荐多用决策树的可视化,同时先限制决策树的深度,这样可以先观察下生成的决策树里数据的初步拟合情况,然后再决定是否要增加深度。
在训练模型时,注意观察样本的类别情况(主要指分类树),如果类别分布非常不均匀,就要考虑用class_weight来限制模型过于偏向样本多的类别。
决策树的数组使用的是numpy的float32类型,如果训练数据不是这样的格式,算法会先做copy再运行。
如果输入的样本矩阵是稀疏的,推荐在拟合前调用csc_matrix稀疏化,在预测前调用csr_matrix稀疏化。

5. 分类与回归树CART

待续

没有更多推荐了,返回首页