决策树-分类算法
1 认识决策树
决策树是一种基本的分类方法,也可以用于回归。我们一般只讨论用于分类的决策树。决策树模型呈树形结构,在分类问题中,表示基于特征对实例进行分类的过程,它可以认为是if-then规则的集合。在决策树的结构中,每一个实例都被一条路径或者一条规则所覆盖。
2 特征选择
特征选择在于选取对训练数据具有分类能力的特征。这样可以提高决策树学习的效率,如果利用一个特征进行分类的结果与随机分类的结果没有很大差别,则称这个特征是没有分类能力的,经验上扔掉这样的特征对决策树学习的影响不大。
首先举个例子,
母亲要给你介绍男朋友的对话:
女儿:多大了? 母亲:26。
女儿:长的帅不? 母亲:挺帅的。
女儿:有房不? 母亲:有的。
女儿:那好,我去见见。
上图中,长相和是否有房为什么放在年龄后面,不把他们放在前面呢,这是因为女儿把年龄看得比较重要,那么年龄就更具有分类的能力。回到特征选择中,如果一个特征具有更好的分类能力,是在当前的条件下有最好的分类,那么就更应该选择这个特征。
2.1 信息度量
某个信息有用,那么它的作用如何客观、定量地体现出来呢,1948年,香农在他的论文“通信的数学原理”中提到了“信息熵”的概念,解决了信息的度量问题,并量化出信息的作用。
一条信息的信息量与其不确定性有着直接的关系,比如我们要搞清一件非常不确定的事,就需要大量的信息。相反如果对某件事了解较多,则不需要太多的信息就能把它搞清楚 。所以从这个角度看,可以认为,信息量就等于不确定的多少。
那么如何量化信息量的度量,假设某次世界杯上有32支球队,谁会赢呢,每猜一次给一块钱,告诉我是否猜对了,那么我需要掏多少钱才能知道谁是冠军?我可以把球编上号,从1到32,然后提问:冠 军在1-16号吗?依次询问,只需要五次,就可以知道结果,以谁是世界杯冠军这条消息只值五块钱。香农用“比特”这个概念来度量信息量。一个比特是 一位二进制数,在计算机中一个字节是8比特。
如果有一天有64支球队进行决赛阶段的比赛,那么“谁是世界杯冠军”的信息量就是6比特,因为要多猜一次,信息量的比特数和所有可能情况的对数函数log有关,(log32=5,log64=6)
实际上不需要猜五次就能才出冠军,因为像西班牙、巴西、德国这样的球队夺得冠军的可能性比南非、尼日利亚等球队大得多,因此第一次猜测时不需要把32支球队等分成两个组,而可以把少数几支最有可能的球队分成一组,把其他球队分成一组。然后才冠军球队是否在那几支热门队中。这样,也许三次就猜出结果。因此,当每支球队夺冠的可能性不等时,“谁是世界杯冠军”的信息量比5比特少。香农指出,它的准确信息量应该是:
H = -(p1logp1 + p2logp2 + ... + p32log32)
其中,p1...p32为这三支球队夺冠的概率。H的专业术语称之为信息熵,单位为比特。当这32支球队夺冠的几率相同时,对应的信息熵等于5比特,这个可以通过计算得出。有一个特性就是,5比特是公式的最大值。那么信息熵(经验熵)的具体定义可以为如下:
H(X)=∑x∈XP(x)logP(x)
2.2 信息增益
信息和消除不确定性是相联系的。所以决策树的过程其实是在寻找某一个特征对整个分类结果的不确定减少的过程。那么这样就有一个概念叫做信息增益(information gain)。
信息增益表示得知特征X的信息而使得Y的信息的不确定性减少的程度,所以对于选择特征进行分类的时候,要选择信息增益较大的特征,这样具有较强的分类能力。特征A对训练数据集D的信息增益g(D,A),定义为集合D的信息熵H(D)与特征A给定条件下D的信息条件熵H(D|A)之差,即公式为:
根据信息增益的准则的特征选择方法是:对于训练数据集D,计算其每个特征的信息增益,并比较它们的大小,选择信息增益最大的特征。
2.3 信息增益的计算
假设训练数据集为D,|D|表示样本个数。设有K个类Ck,k=1,2,3,4...k,∣Ck∣为属于类Ck的样本个数,=∣D∣.设特征A有n个不同的取值{a1,a2,...,an},根据特征A的取值将D划分为n个子集D1,D2,...,Dn,∣Di∣为样本个数,其中Di中属于Ck类的样本的集合为Dik
信息熵的计算如下:
条件熵的计算如下:
3 常见决策树使用的算法
ID3:信息增益 最大的准则
C4.5:信息增益比 最大的准则
CART :回归树: 平方误差 最小
分类树: 基尼系数 最小的准则,在sklearn中默认划分的原则
基尼系数划分比信息增益划分更加仔细
4 sklearn决策树API
class sklearn.tree.DecisionTreeClassifier(criterion=’gini’, max_depth=None,random_state=None) 决策树分类器
常用参数:
criterion:默认是’gini’系数,也可以选择信息增益的熵’entropy’
max_depth:树的深度大小
random_state:随机数种子
常用方法::
apply 返回每个样本被预测的叶子的索引
decision_path:返回决策树的路径
fit_transform(X,y=None,fit_params)** 输入数据,然后转换
predict(X) 预测输入数据的类型,完整代码
score(X,y,sample_weight=None) 返回给定测试数据的准确精度
决策树的结构、本地保存。
①sklearn.tree.export_graphviz() 该函数能导出DOT格式
tree.export_graphviz(estimator,out_file='tree.dot’,feature_names=[‘’,’’])
②工具:(能够将dot文件转换为pdf、png)
安卓:https://graphviz.gitlab.io/_pages/Download/Download_windows.html(下载解压后需要添加到环境变量中)
安装graphviz ubuntu:sudo apt-get install graphviz Mac:brew install graphviz
③运行命令 然后我们运行这个命令
$ dot -Tpng tree.dot -o tree.png
如果我们安装了Python模块pydotplus,我们可以直接在Python中生成PDF文件,通过pip install pydotplus,还需要安装好graphviz,然后运行
import pydotplus
from sklearn import tree
from sklearn.datasets import load_iris
clf = tree.DecisionTreeClassifier()
iris = load_iris()
clf = clf.fit(iris.data, iris.target)
dot_data = tree.export_graphviz(clf, out_file=None)
graph = pydotplus.graph_from_dot_data(dot_data)
graph.write_pdf("iris.pdf")
5 案例
决策树对泰坦尼克号预测生死:数据来源http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt
泰坦尼克号数据,数据集中的特征是票的类别,存活,乘坐班,年龄,登陆,home.dest,房间,票,船和性别。乘坐班是指乘客班(1,2,3),是社会经济阶层的代表。 其中age数据存在缺失。
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier,export_graphviz
# 1.加载数据
datas = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")# 2.处理数据,找出目标值和特征值
x = datas[['pclass','age','sex']]
y = datas['survived']# 2.1利用pandas.DataFrame.fillna方法处理缺失数据,inplace=True直接修改原对象
x['age'].fillna(x['age'].mean(),inplace=True)# 3 分割数据集为训练集合测试集
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25)# 4.特征工程的抽取 特征->类别->one_hot编码
# 当特征里面是类别的信息,应该要one-hot编码,否则计算机不知道怎么去计算
dict = DictVectorizer(sparse=False)
# 将x_train(DataFrame类型)转换为字典,关键字orient='records' 时形成[{column -> value}, … , {column -> value}]的结构
# 整体构成一个列表,内层是将原始数据的每行提取出来形成字典
x_train = dict.fit_transform(x_train.to_dict(orient='records'))
print(dict.get_feature_names())
x_test = dict.transform(x_test.to_dict(orient='records'))# 5.决策树进行预测
dec = DecisionTreeClassifier()
dec.fit(x_train,y_train)
# 预测准确率
print("预测准确率:", dec.score(x_test, y_test))
# 导出决策树的结构
export_graphviz(dec, out_file="./tree.dot", feature_names=['年龄', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', '女性', '男性'])
6 决策树的优缺点
优点: 简单的理解和解释,树木可视化;需要很少的数据准备,其他技术通常需要数据归一化
缺点: 决策树学习者可以创建,不能很好地推广数据过于复杂的树,这被称为过拟合; 决策树可能不稳定,因为数据的小变化可能会导致完全不同的树被生成
改进: 减枝cart算法,随机森林