决策树

决策树(Decision Tree)是一种非参数的有监督学习方法,它能够从一系列有特征和标签的数据中总结出决策规则,并用树状图的结构来呈现这些规则,以解决分类和回归问题。

如何工作

决策树算法的本质是一种图结构,我们只需要问一系列问题就可以对数据进行分类了。比如说,来看看下面这组数据集,这是一系列已知物种以及所属类别的数据

名字 体温 表皮覆盖 胎生 水生动物 飞行动物 有腿 冬眠 类标号
人类 恒温 毛发 哺乳类
鲑鱼 冷血 鳞片 鱼类
恒温 毛发 哺乳类
青蛙 冷血 两栖类
巨蜥 冷血 鳞片 爬行类

我们现在的目标是,将动物们分为哺乳类和非哺乳类。那根据已经收集到的数据,决策树算法为我们算出了下面的这棵决策树。

            体温
     恒温  /     \ 冷血
        胎生        【非哺乳动物】
   是 /      \ 否

【哺乳动物】 【非哺乳动物】

假如现在发现了新物种Python,它是冷血动物,不是胎生,就可以根据决策树来判断它的类别。

决策树的类型

  • ID3: 使用信息增益方法作为属性的选择标准,来帮助确定生成每个节点时所采用的合适属性
  • C4.5:相对于ID3,使用信息增益率来选择节点属性。ID3只适用于离散的描述属性,而C4.5算法既能够处理离散的描述属性,也可以处理连续的描述属性
  • CART:CART决策树是一种十分有效的非参数分类和回归方法,通过构建树、修剪树、评估树来构建一个二叉树,当终结点事连续变量时,为回归树;当终节点是分类变量,则为分类树。

Decision Tree Classifier 与红酒数据集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
import pandas as pd

wine = load_wine()
pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)

Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data,wine.target,test_size=0.3)

clf = tree.DecisionTreeClassifier(criterion="entropy")
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) #返回预测的准确度
score

criterion

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

画树

1
2
3
4
5
6
7
8
9
10
11
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

特征重要性

1
2
clf.feature_importances_
[*zip(feature_name,clf.feature_importances_)]

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

1
2
3
4
clf = tree.DecisionTreeClassifier(criterion="entropy",random_state=30)
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) #返回预测的准确度
score