sklearn-DecisionTreeClassifier的基本用法
决策树的流程
计算全部特征的不纯度,选取不纯度指标最优的特征来分支,在第一个特征的分支下,计算全部特征的不纯度指标,选取不纯度指标最优的特征继续分支
DecisionTreeClassifier的核心参数:
criterion
为了要将表格转化为一棵树,决策树需要找出最佳节点和最佳的分枝方法,对分类树来说,衡量这个“最佳”的指标
叫做“不纯度”。通常来说,不纯度越低,决策树对训练集的拟合越好。现在使用的决策树算法在分枝方法上的核心
大多是围绕在对某个不纯度相关指标的最优化上。
entropy
信息熵gini
基尼系数
建树
1.导入需要的算法库和模块
from sklearn import tree from sklearn.datasets import load_wine from sklearn.model_selection import train_test_split
2.探索数据
wine = load_wine() #将数据库中的练习数据导入 wine.data.shape #获取数据结构——178行,13列,即13个特征 >(178,13) wine.target #因为wine是一个字典,所以我们可以通过键来获取对于的值 >array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
import pandas as pd pd.concat([pd.DataFrame(wine.data), pd.DataFrame(wine.target)], axis=1) #将数据和标签都传入pd.DataFrame,生成表格,更方便的查看数据结构
wine.feature_names #查看特征名 >['alcohol', 'malic_acid', 'ash', 'alcalinity_of_ash', 'magnesium', 'total_phenols', 'flavanoids', 'nonflavanoid_phenols', 'proanthocyanins', 'color_intensity', 'hue', 'od280/od315_of_diluted_wines', 'proline']
wine.targets_names #查看标签名 >array(['class_0', 'class_1', 'class_2'], dtype='<U7')
3.将数据划分为训练集和测试集
Xtrain,Xtest,Ytrain,Ytest = train_test_split(wine.data, wine.target, test_size=0.3) #给出数据和标签,test_size是指30%做测试集,剩下的70%做训练集
Xtrain.shape >(124, 13) Xtest.shape >(54, 13)
查看数据结构,确认原始数据已经被分成70%和30%两部分
建模三部曲
第一步: 实例化
clf = tree.DecisionTreeClassifier(criterion="entropy") #criterion 默认是基尼系数,此处我们选择使用信息熵
第二部: 训练模型
clf = clf.fit(Xtrain, Ytrain)
第三步: 打分
score = clf.score(Xtest, Ytest) #用测试集来打分,返回的是一个准确度accuracy score >>0.9259259259259259 #在此处每次打分的结果都可能不一样
画图
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸'] import graphviz dot_data = tree.export_graphviz(clf, feature_names=feature_name, class_names=['琴酒','雪莉', '贝尔摩德'], filled=True, rounded=True ) # 分别传入模型 clf ;特征名 ; 标签名 # filled表示是否填充颜色,不纯度越低,颜色越深 # rounded表示方框的圆度
graph = graphviz.Source(dot_data) graph
接下来查看我们感兴趣的数值,并针对性的分析
clf.feature_importances_ #虽然返回了数值,但是看不懂,需要连接前面的特征 >>array([0. , 0. , 0. , 0.01424694, 0. , 0. , 0.47329119, 0. , 0.02568071, 0.31227528, 0. , 0. , 0.17450589]) # 此处返回的是特征值的权重
[*zip(feature_name, clf.feature_importances_)] #用 *zip 连接特征名和对于数值 >>[('酒精', 0.0), ('苹果酸', 0.0), ('灰', 0.0), ('灰的碱性', 0.01424693586672224), ('镁', 0.0), ('总酚', 0.0), ('类黄酮', 0.4732911864435072), ('非黄烷类酚类', 0.0), ('花青素', 0.02568070945422599), ('颜色强度', 0.31227528031774815), ('色调', 0.0), ('od280/od315稀释葡萄酒', 0.0), ('脯氨酸', 0.17450588791779637)] 可以看到 类黄酮 的数值最高,所以在决策树的顶端作为根结点
模型的分值随机变化,那么我们如何获得稳定的模型呢?
clf = tree.DecisionTreeClassifier(criterion="entropy",random_state=20) clf = clf.fit(Xtrain, Ytrain) score = clf.score(Xtest, Ytest) score >>0.8888888888888888
在模型中加入
random_state
参数控制模型,使模型稳定,数值本身通过调试选择合适值;如果加入splitter=“random”
可以让模型更加随机,从而防止过拟合,适用于特征值相当大的时候。可以说
criterion
用来规定不纯度的计算,random_state
和splitter
用来控制决策树的随机度
最后我们对训练集的拟合程度怎么样呢?
score_train = clf.score(Xtrain,Ytrain) score_train >>1.0
因为训练集的精准度在92%,所以虽然我们测试集的打分是满分,也是正常现象。如果训练集打分只有80%,则考虑模型过拟合。
剪枝策略-剪枝参数调优
剪枝策略对决策树有巨大的影响,正确的剪枝策略是优化决策树算法的核心。
max_depth
限制树的最大深度,超过设定深度的树枝全部剪掉,能够有效的控制过拟合,通常从3开始。
min_samples_leaf & min_samples_split
min_samples_leaf
限定,一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分 枝就不会发生,或者,分枝会朝着满足每个子节点都包含min_samples_leaf个样本的方向去发生,一般搭配max_depth使用,在回归树中有神奇的效果,可以让模型变得更加平滑。这个参数的数量设置得太小会引起过拟合,设置得太大就会阻止模型学习数据。一般来说,建议从=5开始使用。如果叶节点中含有的样本量变化很 大,建议输入浮点数作为样本量的百分比来使用。同时,这个参数可以保证每个叶子的最小尺寸,可以在回归问题 中避免低方差,过拟合的叶子节点出现。对于类别不多的分类问题,=1通常就是最佳选择.
min_samples_split
限定,一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分枝,否则 分枝就不会发生。max_features & min_impurity_decrease
一般max_depth使用,用作树的”精修“
max_features
限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃。和max_depth异曲同工,max_features是用来限制高维度数据的过拟合的剪枝参数,但其方法比较暴力,是直接限制可以使用的特征数量而强行使决策树停下的参数,在不知道决策树中的各个特征的重要性的情况下,强行设定这个参数可能会导致模型学习不足。如果希望通过降维的方式防止过拟合,建议使用PCA,ICA或者特征选择模块中的降维算法。
min_impurity_decrease
限制信息增益的大小,信息增益小于设定数值的分枝不会发生。>clf = tree.DecisionTreeClassifier(criterion="entropy" ,random_state=20 ,splitter='random' ,max_depth=4 # ,min_samples_leaf=10 # ,min_samples_split=10 ) clf = clf.fit(Xtrain, Ytrain) dot_data = tree.export_graphviz(clf ,feature_names=feature_name ,class_names=['琴酒','雪莉','贝尔摩德'] ,filled=True ,rounded=True ) graph = graphviz.Source(dot_data) graph
score_train = clf.score(Xtrain,Ytrain) score_train >>0.9758064516129032
可以看出通过剪枝后的模型,比原来分值更高
那么如何确定最优的剪枝参数呢?
使用确定超参数的曲线来进行判断,继续使用我们已经训练好的决策树模型clf。超参数的学习曲线,是一条以超参数的取值为横坐标,模型的度量指标为纵坐标的曲线,它是用来衡量不同超参数取值下模型的表现的线。在我们建好的决策树里,我们的模型度量指标就是score。
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()
图中可得当max_depth=4
时最优