决策树总结 - DecisionTreeClassifier(一)

1,480 阅读6分钟

根据菜菜的课程进行整理,方便记忆理解

sklearn中的决策树

模块sklearn.tree

sklearn中决策树的类都在”tree“这个模块之下。这个模块总共包含五个类:

tree.DecisionTreeClassifier分类树
tree.DecisionTreeRegressor回归树
tree.export_graphviz将生成的决策树导出为DOT格式,画图专用
tree.ExtraTreeClassifier高随机版本的分类树
tree.ExtraTreeRegressor高随机版本的回归树

sklearn的基本建模流程

image.png

from sklearn import tree            #导入需要的模块
clf = tree.DecisionTreeClassifier() #实例化
clf = clf.fit(X_train,y_train)      #用训练集数据训练模型
result = clf.score(X_test,y_test)   #导入测试集,从接口中调用需要的信息

DecisionTreeClassifier与红酒数据集

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)

重要参数

criterion
  • 为了要将表格转化为一棵树,决策树需要找出最佳节点和最佳的分枝方法,对分类树来说,衡量这个“最佳”的指标叫做“不纯度”。通常来说,不纯度越低,决策树对训练集的拟合越好。现在使用的决策树算法在分枝方法上的核心大多是围绕在对某个不纯度相关指标的最优化上。
  • 不纯度基于节点来计算,树中的每个节点都会有一个不纯度,并且子节点的不纯度一定是低于父节点的,也就是说,在同一棵决策树上,叶子节点的不纯度一定是最低的

Criterion这个参数正是用来决定不纯度的计算方法的。sklearn提供了两种选择:

  • 输入”entropy“,使用信息熵(Entropy)

    • image.png
  • 输入”gini“,使用基尼系数(Gini Impurity)

    • image.png

其中t代表给定的节点,i代表标签的任意分类,p(it)p(i|t)代表标签分类i在节点t上所占的比例。注意,当使用信息熵时,sklearn实际计算的是基于信息熵的信息增益(Information Gain),即父节点的信息熵和子节点的信息熵之差。

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

参数criterion
如何影响模型?确定不纯度的计算方法,帮忙找出最佳节点和最佳分枝,不纯度越低,决策树对训练集的拟合越好
可能的输入有哪些?不填默认基尼系数,填写gini使用基尼系数,填写entropy使用信息增益
怎样选取参数?通常就使用基尼系数 数据维度很大,噪音很大时使用基尼系数 维度低,数据比较清晰的时候,信息熵和基尼系数没区别 当决策树的拟合程度不够的时候,使用信息熵 两个都试试,不好就换另外一个

到这里,决策树的基本流程其实可以简单概括如下:

image.png

直到没有更多的特征可用,或整体的不纯度指标已经最优,决策树就会停止生长。

建立一棵树

这个部分的代码可以在这个位置进行查看:

建立一棵树

这个部分的代码可以在这个位置进行查看:

导入需要的算法库和模块
# 导包
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
探索数据
# 使用的是sklearn的默认的数据集---红酒数据集
wine = load_wine()

# 展示数据集的各种属性(整体:一个字典)
wine

# 我们可以看到数据集的  特征数据:data  标签数据:target  标签名称:target_names  描述信息:DESCR  特征名称:feature_names 
wine.keys()

# 数据的shape 一般是二维数据  13个特征,178条数据
wine.data.shape

# 数据展示:字典的调用方式
wine.data

# 标签
wine.target

# 对于上面的DataFrame的数据进行美化
import pandas as pd
df = pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)

# 注意这个地方的写法,可以直接使用对等的列表进行替换,也可以使用rename进行单列的替换
df.columns =["label"] + wine.feature_names

# 数据展示
df

# 特征的名称列表
wine.feature_names

# 类别的列表
wine.target_names
分训练集和测试集
# 直接调用数据的形式传入
# 将数据分成训练集和测试集,分布的比例7/3  由test_size指定
Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data,wine.target,test_size=0.3)

Xtrain.shape
Xtest.shape
建立模型
# 实际上的调用方式只需要三步即可
# 第一步:实例化决策树模型
# 第二步:将训练数据加入其中,使用fit进行训练
# 第三步:使用score进行打分(这个主要是我们有真实的标签,可以将预测出来的标签和真实标签进行准确性的计算)
clf = tree.DecisionTreeClassifier(criterion="entropy")
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) #返回预测的准确度
score
# 92.5925
画出一棵树
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']

import graphviz
dot_data = tree.export_graphviz(clf
                             ,out_file = None
                             ,feature_names= feature_name
                             ,class_names=["琴酒","雪莉","贝尔摩德"]
                             ,filled=True
                             ,rounded=True
)
graph = graphviz.Source(dot_data)
graph

image.png

探索决策树
# 特征重要性,用于进行决策树进行分支的属性的重要程度
clf.feature_importances_

# 将属性和重要程度进行绑定,显示每个属性的对于决策树减小信息混乱程度的重要性
[*zip(feature_name,clf.feature_importances_)]

我们已经在只了解一个参数的情况下,建立了一棵完整的决策树。但是回到步骤4建立模型,score会在某个值附近波动,引起步骤5中画出来的每一棵树都不一样。它为什么会不稳定呢?如果使用其他数据集,它还会不稳定吗?

我们之前提到过,无论决策树模型如何进化,在分枝上的本质都还是追求某个不纯度相关的指标的优化,而正如我们提到的,不纯度是基于节点来计算的,也就是说,决策树在建树时,是靠优化节点来追求一棵优化的树,但最优的节点能够保证最优的树吗?集成算法被用来解决这个问题:sklearn表示,既然一棵树不能保证最优,那就建更多的不同的树,然后从中取最好的。怎样从一组数据集中建不同的树?在每次分枝时,不从使用全部特征,而是随机选取一部分特征,从中选取不纯度相关指标最优的作为分枝用的节点。这样,每次生成的树也就不同了。

总结

之所以会有随机性:

  • 第一层随机性,random的随机性;
  • 第二层的随机性:种很多棵树,取表现的最好的一颗;
  • 第三层随机性:特征的随机性,每次分支选择不同的总特征子集,保证树的不同;
clf = tree.DecisionTreeClassifier(criterion="entropy",random_state=30)
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) #返回预测的准确度

score