一、什么是决策树
决策树(Decision Tree)是一种非参数的有监督学习方法,它能够从一系列有特征和标签的数据中总结出决策规则,并用树状图的结构来呈现这些规则,以解决分类和回归问题。
本文主要介绍分类树。
划分选择
决策树的关键在于如何选择最优划分属性。随着划分过程不断进行,我们希望决策树的分支节点所包含的样本尽可能属于同一类别,即节点的**“纯度”**越来越高(纯度高代表混合的数据少)。
划分准则:
(一)信息增益
“信息熵”是度量样本纯度最常用的准则,信息熵的定义公式为:
D:样本集合,共有n类样本。
P(xi):第i类样本的所占比。标签为i的样本数/总样本数
Ent(D)越小,D的纯度越高。信息增益(Information Gain)的是父节点的信息熵与其下所有子节点总信息熵之差。但这里要注意的是,此时计算子节点的总信息熵不能简单求和,而要在求和汇总之前进行修正(对不同子节点赋予不同的权重)。
信息增益的公式:
a:属性
V:属性a共有V个可能得取值,若用a对D进行划分,会产生V个子节点。
Dv:在属性a上取值为av的样本数。
权重:分支节点的样本数/总样本数
划分数据集的准则是:选取最大的信息增益,即信息下降最快的方向。
计算信息熵的Python实现:
#计算信息熵函数,返回信息熵
def calEnt(dataSet):
n=dataSet.shape[0] #计算总行数
iset=dataSet.iloc[:,-1].value_counts() #计算标签个数
p=iset/n #每类标签的所占比
ent=(-p*np.log2(p)).sum()
return ent
选择最优划分属性:
#根据信息增益选择最佳数据集切分的列 返回:数据集最佳切分列的索引
def bestSplite(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] #某个子节点
ent=calEnt(childSet) #子节点信息熵
ents+=(childSet.shape[0]/dataSet.shape[0])*ent #当前列的信息熵
infoGain=baseEnt-ents #当前列的信息增益
if(infoGain>bestGain):
bestGain=infoGain #选取信息增益最大的
axis=i
return axis
(二)增益率
(三)基尼指数
决策树的基本流程
- 计算全部特征的不纯度指标
- 选取不纯度指标最优的特征进行分支
- 在第一个特征的分支下,计算全部特征的不纯度指标
- 选取不纯度指标最优的特征进行分支
- …
重要参数
- Criterion:用来决定不纯度的计算方法。
1)输入”entropy“,使用信息熵(Entropy)
2)输入”gini“,使用基尼系数(Gini Impurity) - random_state:用来设置分枝中的随机模式的参数。默认为None。输入任意整数,会一直长出同一棵树,让模型稳定下来。
- splitter:也是用来控制决策树中的随机选项的。有两种输入值,输入”best",决策树在分枝时虽然随机,但是还是会优先选择更重要的特征进行分枝(重要性可以通过属性feature_importances_查看);输入“random",决策树在分枝时会更加随机,树会因为含有更多的不必要信息而更深更大,并因这些不必要信息而降低对训练集的拟合。这 也是防止过拟合的一种方式。
- 剪枝参数:为了防止过拟合,提高决策树的泛化性,要对决策树进行剪枝。剪枝策略对决策树的影响巨大,正确的剪枝策略是优化决策树算法的核心。
max_depth:限制树的最大深度,超过设定深度的树枝全部剪掉。
min_samples_leaf:限定,一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分枝就不会发生,或者,分枝会朝着满足每个子节点都包含min_samples_leaf个样本的方向去发生 。
min_samples_splite:限定,一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分枝,否则 分枝就不会发生。
max_features:限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃。
min_impurity_decrease:限制信息增益的大小,信息增益小于设定数值的分枝不会发生。 - 目标权重参数
class_weight:对样本标签进行少量的均衡,给少量标签更多的权重,让模型更偏向少数标签,向捕获少数类的方向建模。默认值为None,表示给各类标签相同的权重。
min_weight_fraction_leaf:当有了权重后需要搭配这个基于权重的剪枝参数来进行剪枝。
属性
feature_importances_:能够查看各个特征的重要性。
接口
fit:拟合数据。
score:对模型进行评估。
apply:输入测试集,返回测试样本所在叶子节点的索引。
predict:输入测试集返回每个测试样本的标签。
决策树示例
通过训练红酒数据集预测红酒的种类。
step1: 导入需要的算法库和模块
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
step2:探索数据
wine=load_wine()
import pandas as pd
pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)
step4 :分训练集和测试集
#70%训练集,30%测试集
Xtrian,Xtest,Ytrain,Ytest=train_test_split(wine.data,wine.target,test_size=0.3)
step5:创建模型(关键步骤)
#建模并进行探索
clf=tree.DecisionTreeClassifier(criterion='entropy') #实例化,采用信息增益的方式
clf=clf.fit(Xtrian,Ytrain) #拟合数据
score=clf.score(Xtest,Ytest) #评估,相当于accuracy
score
step6 画出决策树
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚',
'类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']
import graphviz
dot_data=tree.export_graphviz(clf,
feature_names=feature_name,
class_names=["琴酒","雪莉","贝尔摩德"],
filled=True,
rounded=True)
graph=graphviz.Source(dot_data)
graph
step7:探索决策树
#特征重要性
clf.feature_importances_
[*zip(feature_name,clf.feature_importances_)]