决策树
1.1 概述
1 Decision Tree 非参数的有监督学习方法;树状图;解决分类和回归问题;
根节点;中间节点;叶节点;子节点和父节点
2 决策树算法的核心是要解决两个问题:
1)如何从数据表中找出最佳节点和最佳分支
2)如何让决策树停止生长,防止过拟合
1.2 sklearn中的决策树
tree.DecisionTreeClassifier | 分类树 |
tree.DecisionTreeRegressor | 回归树 |
tree.export_graphviz | 将生成的决策树导出为DOT格式,画图专用 |
tree.ExtraTreeClassifier | 高随机版本的分类树 |
tree.ExtraTreeRegressor | 高随机版本的回归树 |
# sklearn的基本建模流程
在这个流程下,分类树对应的代码:
# 导入需要的模块
from sklearn import tree
# 实例化
clf = tree.DecisionTreeClassifier()
# 用训练集数据训练模型
clf = clf.fit(x_train, y_train)
# 导入测试集,从接口中调用需要的信息
result = clf.score(x_test, y_test)
2 DecisionTreeClassifier与红酒数据集
class sklearn.tree.DecisionTreeClassifier(criterion='gini', )
2.1 重要参数
2.1.1 criterion
对分类树来说,衡量决策树最佳节点和最佳分支的指标叫“不纯度”;不纯度越低,决策树对训练集的拟合越好;现在使用的决策树算法在分支方法上围绕着不纯度相关指标的最优化
criterion这个参数正是用来决定不纯度的计算方法的
sklearn提供了两种选择:
1) 输入'entropy',使用信息熵(Entropy)
sklearn实际计算的是基于信息熵的信息增益(Information Gain),即父节点的信息熵和子节点的信息熵之差
2) 输入'gini',使用基尼系数(Gini Impurity)
参数 | criterion |
如何影响模型? | 确定不纯度的计算方法,帮忙找出最佳节点和最佳分支,不纯度越低,决策树对训练集的拟合越好 |
可能的输入有哪些? | 不填默认gini,填gini用基尼系数,填entropy用信息增益 |
怎样选取参数? | 通常用gini;数据维度大噪音大,用gini;纬度低数据清晰,两个都行;决策树的拟合程度不够,用信息熵 |
至此,可以简单概括决策树的基本流程:
直到没有更多的特征可用、或整体的不纯度指标已经最优,决策树停止生长
现在来建立一棵树
# 导入库和模块
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
# 导入数据,看看数据基本信息
wine = load_wine()
wine
# 查看所需的数据部分
wine.data
wine.data.shape
# 查看标签,可以看出是三分类问题
wine.target
# 通过pandas,先将data和target转为dataframe,再用concat联起来,成表
import pandas as pd
pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)
# 查看数据集特征名和标签名
wine.feature_names
wine.target_names
# 将数据集分为训练集和测试集
# test_size=0.3意味着测试集占30%,训练集占70%
Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data,wine.target,test_size=0.3)
# 看看训练集测试集什么样
Xtrain.shape
Xtest.shape
# 开始建模咯
# 实例化
clf = tree.DecisionTreeClassifier(criterion='entropy')
#用训练集数据训练模型
clf = clf.fit(Xtrain, Ytrain)
# 导入测试集,从接口中调用需要的信息
score = clf.score(Xtest, Ytest) # 返回预测的准确度accuracy
# 看看分数
score
# 每次的分数不一样,需要用random_state来控制随机性
clf = tree.DecisionTreeClassifier(criterion='entropy',random_state=30)
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest)
score
# 把特征名定义一下
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类',
'花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']
# 把建模的图画出来
# filled给不给颜色,颜色越深不纯度越低
import graphviz
dot_data = tree.export_graphviz(clf
,feature_names=feature_name
,class_names=['琴酒','雪莉','贝尔摩德']
,filled=True
,rounded=True
,out_file=None)
graph = graphviz.Source(dot_data)
graph
# 看特征在决策树中发挥的作用
clf.feature_importances_
# 将特征比重跟特征名联起来康康,清晰展示决策树用了什么特征,特征如何重要
[*zip(feature_name,clf.feature_importances_)]
(里面的out_file=None记得写,没有的话一直报错,辛酸史)
2.1.2 random_state & splitter
random_state用来设置分支中的随机模式的参数,默认为None
splitter也是用来控制随机性,输入“best”会优先选择更重要的特征进行分支;输入“random”分支会更加随机,对训练集的拟合将会降低
clf = tree.DecisionTreeClassifier(criterion="entropy"
,random_state=30
,splitter="random"
)
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest)
score
2.1.3 剪枝参数
为了让决策树有更好的泛化性,我们要对决策树进行剪枝;剪枝策略对决策树的影响巨大,正确的剪枝策略是优化决策树算法的核心
sklearn为我们提供了不同的剪枝策略
max_depth
限制树的最大深度,把超过设定深度的树枝全部剪掉;用得最广泛;=3开始
min_samples_leaf
用来限制叶节点的参数,限定一个节点在分支后的每个子节点都必须包含至少min_samples_leaf个训练样本;搭配max_depth使用,在回归树中可以让模型变得更加平滑;=5开始
min_samples_split
限定一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分支
clf = tree.DecisionTreeClassifier(criterion="entropy"
,random_state=30
,splitter="random"
,max_depth=3
,min_samples_leaf=10
,min_samples_split=10
)
clf = clf.fit(Xtrain, Ytrain)
max_features
用作树的“精修”,限制分支时考虑的特征个数,超过限制个数的特征都会被舍弃;方法暴力;可以使用PCA, ICA或者特征选择模块中的降维算法
min_impurity_decrease
限制信息增益的大小,信息增益小于设定数值的分支不会发生
如何确定最优的剪枝参数?
使用确定超参数的曲线进行判断
import matplotlib.pyplot as plt
test = []
for i in range(10):
clf = tree.DecisionTreeClassifier(max_depth=i+1
,criterion="entropy"
,random_state=30
,splitter="random"
)
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest)
test.append(score)
plt.plot(range(1,11),test,color="red",label="max_depth")
plt.legend()
plt.show()
2.1.4 目标权重参数
class_weight & min_weight_fraction_leaf
用class_weight参数对样本标签进行一定的均衡,给少量的标签更多的权重,向捕捉少数类的方向建模;参数默认None
有了权重后,样本量会受到权重影响,此时剪枝需要搭配min_weight_fraction_leaf这个基于权重的剪枝参数
2.2 重要属性和接口
# apply返回每个测试样本所在的叶节点的索引
clf.apply(Xtest)
# predict返回每个测试样本的分类/回归结果
clf.predict(Xtest)
# 还有前面用的
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest)
所有接口输入的特征矩阵必须至少是一个二维矩阵,不接受任何一维矩阵作为特征矩阵被输入;如果数据只有一个特征,必须用reshape(-1,1)来给矩阵增维;如果数据只有一个特征和一个样本,需使用reshape(1,-1)来给数据增维
总结
以上是分类树 DecisionTreeClassifier 和用决策树绘图(export_graphviz)的所有基础;
我们了解了决策树的基本流程,分类树的八个参数,一个属性,四个接口,以及绘图所用代码;
八个参数:criterion;两个随机性相关的参数(random_state, splitter);五个剪枝参数(max_depth, min_samples_split, min_samples_leaf, max_feature, min_impurity_decrease)
一个属性:feature_importances_
四个接口:fit, score, apply, predict
TIPS
分类树天生不擅长环形数据;
擅长月亮型数据:最近邻算法,RBF支持向量机,高斯过程
擅长环形数据:最近邻算法,高斯过程
擅长对半分的数据:朴素贝叶斯,神经网络,随机森林