决策树 Decision Tree

决策树 Decision Tree

一、学习决策树

1、决策树模型

2、学习算法

二、 特征选择

1、香农熵

2、信息增益

3、划分数据集

三、决策树的生成

1、ID3算法

2、C4.5算法

四、决策树的拟合度优化

1、欠拟合和过拟合

2、决策树剪枝

五、CART算法

六、sklearn实现决策树

七、分类模型的评估指标

1、二分类决策树中的样本不不均衡问题

2、混淆矩阵

八、决策树算法评价

一、学习决策树

1、决策树模型

决策树(Decision Tree)是一种实现分治策略略的层次数据结构。它是一种有效的非参数学习方法,并可以用于分类和回归。我们主要讨论分类的决策树。

树模型是有监督学习类算法中应用广泛的一类模型,同时可应用于分类问题和回归问题,其中用于解决分类问题的树模型常被称为分类树,而用于解决回归类问题的树模型被称作回归树。树模型通过递归式切割的方法来寻找最佳分类标准,进而最终形成规则。

分类决策树模型表示一种基于特征对实例例进行分类的树形结构(包括二叉树和多叉树)。

决策树由结点(node)和有向边(directed edge)组成,树中包含三种结点:
根结点(root node):包含样本全集。没有⼊入边,但有零条或多条出边;
内部结点(internal node):对应于属性测试条件,恰有一条⼊入边,和两条或多条出边;
叶结点(leaf node)或终结点(terminal node):对应于决策结果,恰有一条入边,但没有出
边。
决策树 Decision Tree_第1张图片

2、学习算法

假设 X是表示特征的随机变量量, Y是表示类的随机变量量,则条件概率分布可表示为P(Y|X)。 取值X给定划分条件下的区域的集合, Y取值于类的集合。各叶结点(区域)上的条件概率往往会偏向某一个类,即属于某一类的概率较大。决策树在分类时会将该结点的实例强行分到条件概率大的那一类去。

决策树学习本质上是从训练数据集中归纳出一组分类规则,也称为 “树归纳”。对于给定的训练数据集,存在许多对它无错编码的树。而为了简单起见,我们感兴趣的是从中选出 “最小” 的树,这里的树的大小用树的结点数和决策节点的复杂性度量。从另一个角度看,决策树学习是由训练数据集估计条件概率模型。基于特征空间划分的类的条件概率模型有无数个,我们选择的模型应该是不仅能对训练数据有很好的拟合,而且对未知数据也有很好的预测。

树的学习算法是 “贪心算法”,从包含全部训练数据的根开始,每一步都选择最佳划分。依赖于所选择的属性是数值属性还是离散属性,每次将数据划分为两个或 n个子集,然后使用对应的子集递归地进行划分,知道所有训练数据子集被基本正确分类,或者没有合适的特征为止,此时,创建一个树叶结点并标记它,这就生成了一颗决策树。
综上,决策树学习算法包含特征选择、决策树的生成与决策树的剪枝。由于决策树表示一个条件概率分布,所以深浅不同的决策树对应着不同复杂度的概率模型。其中决策树的生成只考虑局部最优,相对地,决策树的剪枝则考虑全局最优。

二、 特征选择

1、香农熵

决策树学习的关键在如何选择最优划分属性。一般而言,随着划分过程不断进行,我们希望决策树的分支结点所包含的样本尽可能属于同一类别, 即结点的 “纯度” (purity)越来越高。在分类树中,划分的优劣用不纯度量(impurity-measure)定量分析。

在信息论与概率统计中,熵是表示随机变量不确定性的度量。这里我们使用的熵,也叫作香农熵,这个名字来源于信息论之父 克劳德·香农。熵函数是一个标准的凸函数。熵越高,信息的不纯度就越高,则混合的数据就越多。

1)熵
∅ ( p , 1 − p ) = − p l o g 2 p − ( 1 − p ) l o g 2 ( 1 − p ) \varnothing (p,1-p)=-plog_2p-(1-p)log_2(1-p) (p,1p)=plog2p(1p)log2(1p)
2)基尼指数(Gini index)
∅ ( p , 1 − p ) = 1 − ∑ i = 1 m p i 2 \varnothing (p,1-p)=1-\sum_{i=1}^{m}p_i^2 (p,1p)=1i=1mpi2
3)误分类误差(Classification error)
∅ ( p , 1 − p ) = 1 − m a x ( p , 1 − p ) \varnothing (p,1-p)=1-max(p,1-p) (p,1p)=1max(p,1p)
2、信息增益

全局最优树没有办法简单高效的获得,因此此处我们仍然要以局部最优化方法来指导建模过程,并通过优化条件的设置,最终在每一步都是局部最优的条件下逐步至尽可能全局最优的结果。而在信息熵指数的指导下,决策树生成过程的局部最优条件也非常好理解:即在选取属性测试条件(attribute test condition)对某结点(数据集)进行切分的时候,尽可能选取使得该结点对应的子节点信息熵最小的特征进行切分。换而言之,就是要求父节点信息熵和子节点总信息熵之差要最大。
I ( c h i n d ) = ∑ v = 1 v ∣ D v ∣ ∣ D ∣ E n t ( D v ) I(chind)=\sum_{v=1}^{v}\frac{\left | D^v \right |}{\left | D \right |}Ent(D^v) I(chind)=v=1vDDvEnt(Dv)
而父节点和子节点的不纯度下降数可由下述公式进行计算:
Δ = E n t ( D ) − I ( c h i n d ) \Delta =Ent(D)-I(chind) Δ=Ent(D)I(chind)
Ent(D)是一个不变的值,所以最大化增益等价于最小化分支结点的不纯性度量的加权平均值。最后,当选择熵作为公式的不纯性度量时,熵的差就是所谓的 “信息增益”。

3、划分数据集

分类算法除了需要测量信息熵,还需要划分数据集。在知道如何得到熵之后,我们就可以按照获取最大信息增益的方法来判断是否正确地划分了数据集。我们将对每个特征划分数据集的结果计算一次信息熵,以便判断按照哪个特征划分数据集是最好的划分方式。

划分数据集的最大准则是选择最大信息增益,也就是信息下降最快的方向。

最大信息熵的所选的特征是分类后熵值最小的特征。分类后熵值最小的特征恰恰是分类结果一致的特征,而分类结果一致的特征必须是两类样本差异最大的特征。

def bestSplit(dataSet):
    baseEnt = calEnt(dataSet)                                # 计算原始熵
    bestGain = 0                                             # 初始化信息增益
    axis = -1                                                # 初始化最佳切分列,标签列
    for i in range(dataSet.shape[1]-1):                      # 对特征的每一列进行循环
        levels= dataSet.iloc[:,i].value_counts().index       # 提取出当前列的所有取值
        ents = 0                                             # 初始化子节点的信息熵
        for j in levels:                                     # 对当前列的每一个取值进行循环
            childSet = dataSet[dataSet.iloc[:,i]==j]         # 某一个子节点的dataframe
            ent = calEnt(childSet)                           # 计算某一个子节点的信息熵
            ents += (childSet.shape[0]/dataSet.shape[0])*ent # 计算当前列的信息熵
            print(f'第{i}列的信息熵为{ents}')
        infoGain = baseEnt-ents                              # 计算当前列的信息增益
        print(f'第{i}列的信息增益为{infoGain}')
        if (infoGain > bestGain):
            bestGain = infoGain                              # 选择最大信息增益
            axis = i                                         # 最大信息增益所在列的索引
    return axis
返回结果:0列的信息熵为0.55097750043269370列的信息熵为0.55097750043269370列的信息增益为0.41997309402197491列的信息熵为0.81列的信息熵为0.81列的信息增益为0.17095059445466854
0    

三、决策树的生成

1、ID3算法

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

def createTree(dataSet):
    featlist = list(dataSet.columns)                        # 提取出数据集所有的列
    classlist = dataSet.iloc[:,-1].value_counts()           # 获取最后一列类标签
    # 判断最多标签数目是否等于数据集行数,或者数据集是否只有一列
    if classlist[0]==dataSet.shape[0] or dataSet.shape[1] == 1:
        return classlist.index[0]                           # 如果是,返回类标签
    axis = bestSplit(dataSet)                               # 确定出当前最佳切分列的索引
    bestfeat = featlist[axis]                               # 获取该索引对应的特征
    myTree = {
     bestfeat:{
     }}                                  # 采用字典嵌套的方式存储树信息
    del featlist[axis]                                      # 删除当前特征
    valuelist = set(dataSet.iloc[:,axis])                   # 提取最佳切分列所有属性值
    for value in valuelist:                                 # 对每一个属性值递归建树
        myTree[bestfeat][value] = createTree(mySplit(dataSet,axis,value))
    return myTree
mytree = createTree(data)
返回结果:第0列的信息增益为0.9182958340544896

ID3算法局限主要源于局部最优化条件,即信息增益的计算方法,其局限性主要有以下几点:

①分支度越高(分类水平越多)的离散变量往往子结点的总信息熵更小,ID3是按照某一列进行切分,有一些列的分类可能不会对结果有足够好的指示。极端情况下取ID作为切分字段,每个分类的纯度都是100%,因此这样的分类⽅方式是没有效益的。
②不能直接处理连续型变量,若要使用ID3处理连续型变量,则首先需要对连续变量进行离散化。
③对缺失值较为敏感,使用ID3之前需要提前对缺失值进行处理。
④没有剪枝的设置,容易导致过拟合,即在训练集上表现很好,测试集上表现很差。

2、C4.5算法

以信息增益作为划分训练数据集的特征,存在偏向于选择取值较多的特征的问题,使用信息增益比
(information gain ratio)可以对这一问题进行校正。信息增益比定义为其信息增益与训练数据集关于某一特征的值的熵之比

值得注意的是,增益率准则对可取值数目较少的属性有所偏好,因此,C4.5算法并不是直接选择增益率最大的候选划分属性,而是使用了了一种启发式:先从候选划分属性中找出信息增益高于平均水平的属性,再从中选择增益率最高的。

连续变量处理手段

在C4.5中,同样还增加了了针对连续变量的处理手段。如果输入特征字段是连续型变量,则算法首先会对
这一列数进行从小到大的排序,然后选取相邻的两个数的中间数作为切分数据集的备选点,若一个连续变量有N个值,则在C4.5的处理过程中将产生N-1个备选切分点,并且每个切分点都代表着一种二叉树的切分方案。

四、决策树的拟合度优化

1、欠拟合和过拟合

我们应该从训练样本中尽可能学到适用于所有潜在样本的"普遍规律",我们认为假设空间存在这种"真"模型,那么所选择的模型应该逼近真模型。拟合度可简单理解为模型对于数据集背后客观规律的掌握程度,模型对于给定数据集如果拟合度较差,则对规律的捕捉不完全,用作分类和预测时可能准确率不高,换句话说,当模型把训练样本学得"太好"了的时候,很可能已经把训练样本自身的一些特点当作了所有潜在样本的普遍性质,这时候所选的模型的复杂度往往会比真模型更高,这样就会导致泛化性能下降。这种现象称为过拟合(overfitting)。可以说,模型选择旨在避免过拟合并提高模型的预测能力。与过拟合相对的是欠拟合(underfitting),是指模型学习能力低下,导致对训练样本的一般性质尚未学好。

2、决策树剪枝

所谓剪枝是指在决策树中去除部分叶结点。剪枝(Pruning)主要是用来防止过拟合,对于一般的数据
集如果总是追求 ”纯的“ 叶结点,或者观测数较小的叶结点,很容易使得树过于庞杂,尤其是存在可以反
复使用的连续变量的时候,此时就需要主动去掉一些分支来降低过拟合的风险。

预剪枝:在决策树生成的过程中,对每个结点在划分前先进行估计,如果当前的结点划分不能带来决策树泛化性能(预测性能)的提升,则停止划分并且将当前结点标记为叶结点。
后剪枝:先训练生成一颗完整的树,自底向上对非叶结点进行考察,如果将该结点对应的子树替换为叶结点能带来决策树泛化能力的提升,则将该子树替换为叶结点。

常用的是后剪枝的方法。

五、CART算法

CART是分类回归树

分裂过程是一个二叉递归划分过程
CART预测变量 的类型既可以是连续型变量也可以是分类型变量
数据应以其原始形式处理,不需要离散化
用于数值型预测时,并没有使用回归,而是基于到达叶结点的案例的平均值做出预测

1、分裂规则

二叉递归划分:条件成立向左,反之向右
对于连续变量:条件是属性小于等于最优分裂点
对于分类变量:条件是属性属于若干类
二叉分裂的优点:相比多路分裂导致数据碎片化的速度慢,允许在一个属性上重复分裂,即可以在一个属性上产生足够多的的分裂。两路分裂带来的树预测性能提升足以弥补其相应的树易读性损失。

对于属性不同的被预测变量分裂准则不不同:
分类树:Gini准则。与之前的信息增益很类似,Gini系数度量一个结点的不纯度。
回归树:一种常见的分割标准是标准偏差减少(Standard Deviation Reduction, SDR),类似于
最小均方误差LS(least squares,预测错误的平方和)准则。

2、利用测试集进行剪枝

简单讨论CART算法剪枝过程,该过程也是测试集用于修正模型的最佳体现。例如,有如下在训练集中
训练得到的树模型,黑色数字表示训练集上的分类情况,红色数字表示模型作⽤用于验证集上的分类情
况。

决策树 Decision Tree_第2张图片

则CART算法利利⽤用验证集剪枝的过程如下:
①判断每个叶节点在验证集上的错误率,节点4的错误率e(4)=1/3,节点5的错误率e(5)=1,节点6的错误率e(6)=1,节点7的错误率e(7)=4/9;

②计算子节点总加权平均错误率并和父节点进行比较,加权方法就是乘以该节点样本量占父节点样本总量的百分比(测试集),如 e(4)x3/4+e(5)x1/4=2/4,而父节点,节点2的错误率为e(2)=1/4,因此子节点错误率更高,考虑剪枝。同样可计算节点6和节点7的加权平均错误率为e(6)x1/10+e(7)x9/10=5/10,,而节点3的错误率e(3)=4/10,因此考虑剪枝;

可以看出,CART算法剪枝过程更易于理解也更便于操作,同时我们也能看到对于建立模型的算法而言,测试集不仅能够对模型准确率进行评估,同时还能起到修正优化模型的作用。

3、测试集和验证集

对于大多数模型而言,测试集实际上的作用就是用来修正模型,为了提高修正的准确率,我们也可采用交叉验证的方法,反复判别模型修改条件(如是否要剪枝),并设置模型修改触发条件(如多数验证情况需要修改则对其进⾏修改),从而提高模型优化的可靠性。而除了了训练集和测试集之外,我们还常常会划分一个验证集,验证集数据不参与建模也不参与模型修改和优化,只用于测试最终优化后模型效力。而训练集、测试集和验证集的划分通常遵照6:2:2的比例进行划分,当然也可根据实际需求适当调整划分比例,但无论如何,测试集和验证集数据数量都不宜过多也不宜过少,该二者数据集数据均不参与建模,若占比太多,则会对模型构建过程造成较大影响(欠拟合),而若划分数据过少,训练集数据量较大,则又有可能造成过拟合,数据集的划分也是影响拟合度的重要因素。若要求解最优划分比例,则可按照KNN和K-Means确定k值的思路来解决,即通过绘制学习曲线的方法来判断最佳例,该方法我们会在后续进行尝试。

六、sklearn实现决策树

1、重要参数

①criterion

Criterion这个参数是用来决定不不纯度的计算方法。默认为基尼系数,sklearn提供了了两种选择:
输⼊“entropy”,使用信息熵(Entropy)
输入 “gini”,使用基尼系数(Gini Impurity)

比起基尼系数,信息熵对不纯度更加敏感,对不纯度的惩罚最强。但是在实际使用中,信息熵和基尼系数的效果基本相同。信息熵的计算比基尼系数缓慢⼀一些,因为基尼系数的计算不不涉及对数。另外,因为信息熵对不纯度更加敏感,所以信息熵作为指标时,决策树的⽣长会更加 ”精细”,因此对于高纬数据或者噪声很多的数据,信息熵很容易过拟合,基尼系数在这种情况下效果往往比较好。当模型拟合程度不足的时候,即当模型在训练集和测试集上都表现不太好的时候,使用信息熵。当然,这些不是绝对的。通常就使用基尼系数据维度很大,噪音很大时使用基尼系数;维度低,数据比较清晰的时候,信息熵和基尼系数没区别;当决策树的拟合程度不够的时候,使用信息熵两个都试试,不好就换另外一个。

②random_state & spliter

random_state用来设置分支中的随机模式的参数,默认None,在高维度时随机性会表现更明显,低维度的数据(比如鸢尾花数据集),随机性几乎不会显现。

splitter也是用来控制决策树中的随机选项的,有两种输入值,输入”best",决策树在分支时虽然随机,但是还是会优先选择更重要的特征进行分支(重要性可以通过属性feature_importances_查看),输入“random",决策树在分支时会更加随机,树会因为含有更多的不必要信息而更深更大,并因这些不必要信息而降低对训练集的拟合。这也是防止过拟合的一种方式。当你预测到你的模型会过拟合,用这两个参数来帮助你降低树建成之后过拟合的可能性。当然,树一旦建成,我们依然是使用剪枝参数来防止过拟合。

③剪枝参数

决策树是天生过拟合的模型,为了让决策树有更好的泛化性,我们要对决策树进行剪枝。剪枝策略对决策树的影响巨大,正确的剪枝策略是优化决策树算法的核心。sklearn为我们提供了了不同的剪枝策略:

max_depth:最大树深度

min_samples_leaf :最小叶节点样本量

min_samples_split:最小样本分隔节点

max_features:限制分支时考虑的特征个数

min_impurity_decrease:限制信息增益的大小

2、重要属性和接口

一个属性:feature_importances_,能够查看各个特征对模型的重要性,

四个接口:fit和score接口

apply中输入测试集返回每个测试样本所在的叶子节点的索引,

predict输入测试集返回每个测试样本的标签,

所有接口中要求输入Xtrain和Xtest的部分,输入的特征矩阵必须⾄至少是一个二维矩阵。 sklearn不接受任何一维矩阵作为特征矩阵被输入。如果你的数据的确只有一个特征,那必须用reshape(-1,1)来给矩阵增维。

import graphviz  # 画决策树库
import pandas as pd
from sklearn import tree
from sklearn.datasets import load_wine  # 红酒数据库
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt
#探索数据集
wine = load_wine()
wine.data.shape
wine.target
# 划分训练集和测试集
Xtrain, Xtest, Ytrain, Ytest =train_test_split(wine.data,wine.target,test_size=0.3)
Xtrain.shape
Xtest.shape

#建立模型
clf = DecisionTreeClassifier(random_state=30,splitter='random')
clf = clf.fit(Xtrain,Ytrain)
clf.score(Xtest,Ytest)
# 画决策树
plt.rcParams['font.sans-serif']=['Simhei'] #显示中文
plt.rcParams['axes.unicode_minus']=False   #显示负号
dot_data = tree.export_graphviz(clf,feature_names=feature_name,
                               class_names=['琴酒','雪莉','贝尔摩德'],
                               filled=True,rounded=True)
graph = graphviz.Source(dot_data)
graph

4、如何确定最优的剪枝参数

score=[]
for i in range(10):
    clf = DecisionTreeClassifier(max_depth=i+1,
                                criterion='gini',
                                random_state=30)
    clf = clf.fit(Xtrain,Ytrain)
    score.append(clf.score(Xtest,Ytest))
    
plt.plot(range(1,11),score,c='red',label='max depth')
plt.legend()
plt.show()

决策树 Decision Tree_第3张图片

从图中我们可以看出,让max depth 达到3左右时,我们的score基本保持不变了,我们就可以认为最优剪枝参数为3。

七、分类模型的评估指标

1、二分类决策树中的样本不均衡问题

对于分类问题,永远都逃不过的一个痛点就是样本不均衡问题。分类模型天生会倾向于多数的类,让多数类更容易被判断正确,少数类被牺牲掉。有时候就不是我们想要的,比如我们现在要对潜在犯罪者和普通人进行分类,潜在犯罪者占总人口的比例是相当低的,也许只有2%左右,98%的人都是普通人,而我们的目标是要捕获出潜在犯罪者。

在决策树中,存在着调节样本均衡的参数:class_weight和接口fit中可以设定的sample_weight。
参数class_weight默认None,即认为标签的比例是1:1,当样本不均衡的时候,我们可以使用形如{“标签的值1”:权重1,“标签的值2”:权重2}的字典来输入真实的样本标签比例,来让算法意识到样本是不平衡的。或者使用”balanced“模式,直接使用n_samples/(n_classes * np.bincount(y))作为权重,可以比较好地修正我们的样本不均衡情况。

有了权重之后,样本量就不再是单纯地记录数目,而是受输入的权重影响了了,因此这时候剪枝,就需要搭配min_ weight_fraction_leaf这个基于权重的剪枝参数来使用。另请注意,基于权重的剪枝参数(例如min_weight_ fraction_leaf)将比不知道样本权重的标准(比如min_samples_leaf)更少偏向主导类。如果样本是加权的,则使用基于权重的预修剪标准来更容易优化树结构,这确保叶节点至少包含样本权重的总和的一小部分。

from sklearn.datasets import make_blobs
class_1 = 1000 #类别1有1000个样本
class_2 = 100 #类别2只有100个
centers = [[0,0], [2.0, 2.0]] #设定两个类别的中心
clusters_std = [2.5, 0.5] #设定两个类别的方差,通常来说,样本量比较大的类别会更加松散
X, y = make_blobs(n_samples=[class_1, class_2],
                  centers=centers,
                  cluster_std=clusters_std,
                  random_state=420,shuffle=False)

#看看数据集长什么样
plt.scatter(X[:, 0], X[:, 1], c=y, cmap="rainbow",s=10)

决策树 Decision Tree_第4张图片

Xtrain,Xtest,Ytrain,Ytest = train_test_split(X,y,test_size=0.2,random_state=420)
#不设定class_weight
clf = DecisionTreeClassifier()
clf.fit(Xtrain,Ytrain)
clf.predict(Xtest)
#设定class_weight
wclf = DecisionTreeClassifier(class_weight='balanced')
wclf.fit(Xtrain,Ytrain)
wclf.predict(Xtest)

clf.score(Xtest,Ytest) 
wclf.score(Xtest,Ytest) 

可以看到,做了了样本平衡后,少数类几乎全部都被分类正确了了,但是多数类有许多被分错了了。从准确率的角度来看,不做样本平衡的时候准确率反而更高,做了样本平衡准确率反而变低了了,这是因为做了了样本平衡后,为了了要更有效地捕捉出少数类,模型误伤了了许多数类样本,而多数类被分错的样本量 >少数类被分类正确的样本数量,使得模型整体的精确性下降。所以我们下面用到混淆矩阵。

2、混淆矩阵

混淆矩阵是二分类问题的多维衡量指标体系,在样本不平衡时极其有用。在混淆矩阵中,我们将少数类认为是正例,多数类认为是负例。在决策树,随机森林这些普通的分类算法里,即是说少数类是1,多数类是0。在SVM里,就是说少数类是1,多数类是-1。普通的混淆矩阵,一般使用{0,1}来表示。

决策树 Decision Tree_第5张图片

其中,行代表预测情况,列则表示实际情况,positive表示阳性,即为真,negative则表示阴性,即为
假。因此矩阵中四个元素分别表示:
TP(True Positive):真实为1,预测也为1
FN(False Negative):真实为1,预测为0
FP(False Positive):真实为0,预测为1

TN(True Negative):真实为0,预测也为0
①模型整体效果:准确率

准确率Accuracy就是所有预测正确的所有样本除以总样本,通常来说越接近1越好。

决策树 Decision Tree_第6张图片
A c c u r a c y = T P + T N T P + T N + F P + F N = 11 + 00 11 + 10 + 01 + 00 Accuracy=\frac{TP+TN}{TP+TN+FP+FN}=\frac{11+00}{11+10+01+00} Accuracy=TP+TN+FP+FNTP+TN=11+10+01+0011+00
②捕捉少数类的艺术:精确度,召回率和F1 score

精确度Precision,又叫查准率,表示在所有预测结果为1的样例数中,实际为1的样例数所占比重。精确度越低,则代表我们误伤了过多的多数类。精确度是”将多数类判错后所需付出成本“的衡量。

决策树 Decision Tree_第7张图片
P r e c i s i o n = T P T P F P = 11 11 + 01 Precision=\frac{TP}{TPFP}=\frac{11}{11+01} Precision=TPFPTP=11+0111
做了样本平衡之后,精确度是下降的,精确度可以帮助我们判断,是否每一次对少数类的预测都精确,所以又被称为”查准率“。在现实的样本不平衡例子中,当每一次将多数类判断错误的成本非常高昂的时候(比如大众召回车辆的例子),我们会追求高精确度。精确度越低,我们对多数类的判断就会越错误。

召回率Recall,又被称为敏感度(sensitivity),真正率,查全率,表示所有真实为1的样本中,被我们预测正确的样本所占的比例。召回率越高,代表我们尽量捕捉出了了越多的少数类,召回率越低,代表我们没有捕捉出足够的少数类。

r1 = (Ytest[Ytest == clf.predict(Xtest)]==1).sum()/(Ytest==1).sum()
r1  # 返回0.41
r2 = (Ytest[Ytest == wclf.predict(Xtest)]==1).sum()/(Ytest==1).sum()
r2  #返回0.59

可以看出,做样本平衡之前,我们只成功捕获了了40%左右的少数类点,而做了了样本平衡之后的模型,捕
捉出了了60%的少数类点。召回率可以帮助我们判断,我们是否捕捉除了了全部的少数类,所以又叫做查全
率。而召回率和精确度是此消彼长的,两者之间的平衡代表了了捕捉少数类的需求和尽量不要误伤多数类的需求的平衡。

为了同时兼顾精确度和召回率,创造了两者的调和平均数作为考量两者平衡的综合性指标,称之F1measure。两个数之间的调和平均倾向于靠近两个数中比较小的那一个数,因此我们追求尽量高的F1 measure,能够保证我们的精确度和召回率都比较高。F1 measure在[0,1]之间分布,越接近1越好。
F − m e a s u r e = 2 1 P r e c i s i o n + 1 R e c a l l = 2 ∗ P r e c i s i o n ∗ R e c a l l P r e c i s i o n + R e c a l l F-measure=\frac{2}{\frac{1}{Precision}+\frac{1}{Recall}}=\frac{2*Precision*Recall}{Precision+Recall} Fmeasure=Precision1+Recall12=Precision+Recall2PrecisionRecall

from sklearn import metrics
wclf = DecisionTreeClassifier(class_weight='balanced')
wclf.fit(Xtrain,Ytrain)
wclf.predict(Xtest)
ypred = wclf.predict(Xtest)
# accuracy
metrics.accuracy_score(Ytest,ypred)
# precision
metrics.precision_score(Ytest,ypred)
# recall
metrics.recall_score(Ytest,ypred)
# F1
metrics.f1_score(Ytest,ypred)

八、决策树算法评价

决策树优点

  1. 易于理解和解释,因为树木可以画出来被看见。
  2. 需要很少的数据准备。其他很多算法通常都需要数据规范化,需要创建虚拟变量并删除空值等。但请注意,sklearn中的决策树模块不不支持对缺失值的处理。
  3. 使用树的成本(比如说,在预测数据的时候)是用于训练树的数据点的数量的对数,相比于其他算法,这是一个很低的成本。
  4. 能够同时处理数字和分类数据,既可以做回归又可以做分类。其他技术通常专门用于分析仅具有一种变量类型的数据集。
  5. 能够处理多输出问题,即含有多个标签的问题,注意与一个标签中含有多种标签分类的问题区别开。
  6. 是一个白盒模型,结果很容易能够被解释。如果在模型中可以观察到给定的情况,则可以通过布尔逻辑轻松解释条件。相反,在黑盒模型中(例例如,在工神经⽹网络中),结果可能更难以解释。
  7. 可以使用统计测试验证模型,这让我们可以考虑模型的可靠性。
  8. 即使其假设在某种程度上违反了了生成数据的真实模型,也能够表现良好。

决策树的缺点

  1. 决策树学习者可能创建过于复杂的树,这些树不能很好地推广数据。这称为过度拟合。修剪,设置叶节点所需的最小样本数或设置树的最大深度等机制是避免此问题所必需的,而这些参数的整合和调整对初学者来说会⽐比较晦涩。
  2. 决策树可能不不稳定,数据中微小的变化可能导致生成完全不不同的树,这个问题需要通过集成算法来解决。
  3. 决策树的学习是基于贪婪算法,它靠优化局部最优(每个节点的最优)来试图达到整体的最优,但这种做法不能保证返回全局最优决策树。这个问题也可以由集成算法来解决,在随机森林中,特征和样本会在分枝过程中被随机采样。
  4. 有些概念很难学习,因为决策树不容易表达它们,例如XOR,奇偶校验或多路复用器问题。
  5. 如果标签中的某些类占主导地位,决策树学习者会创建偏向主导类的树。因此,建议在拟合决策树
    之前平衡数据集。

九、网格搜索

from sklearn.model_selection import GridSearchCV
Xtrain,Xtest,Ytrain,Ytest = train_test_split(wine.data,wine.target,
                                            test_size=0.3,random_state = 420)
# 设置参数可取值
param_grid = {
     'criterion':['entropy','gini'],
             'max_depth':range(2,11),
             'min_samples_split':range(2,20,2),
             'min_samples_leaf':range(1,10)}

# 设置参数网格
reg = GridSearchCV(DecisionTreeClassifier(),param_grid,cv=5)
# 建模
reg.fit(Xtrain,Ytrain)
# 最优参数
reg.best_params_
#查看分数
reg.best_score_
#测试模型
clf = DecisionTreeClassifier(criterion='gini',max_depth=4,
                            min_samples_split=6,min_samples_leaf=5)
clf.fit(Xtrain,Ytrain)
clf.score(Xtest,Ytest)

erion’:[‘entropy’,‘gini’],
‘max_depth’:range(2,11),
‘min_samples_split’:range(2,20,2),
‘min_samples_leaf’:range(1,10)}

设置参数网格

reg = GridSearchCV(DecisionTreeClassifier(),param_grid,cv=5)

建模

reg.fit(Xtrain,Ytrain)

最优参数

reg.best_params_
#查看分数
reg.best_score_
#测试模型
clf = DecisionTreeClassifier(criterion=‘gini’,max_depth=4,
min_samples_split=6,min_samples_leaf=5)
clf.fit(Xtrain,Ytrain)
clf.score(Xtest,Ytest)


你可能感兴趣的:(机器学习,机器学习)