【机器学习算法】 决策树ID3,C4.5

一、决策树基本概念及算法优缺点

###1.什么是决策树
分类决策树模型是一种描述对实例进行分类的树形结构。决策树由结点有向边组成。结点有两种类型:内部结点和叶结点。内部结点表示一个特征或属性,叶结点表示一个类。
决策树(Decision Tree),又称判定树,是一种以树结构(包括二叉树和多叉树)形式来表达的预测分析模型。

  • 通过把实例从根节点排列到某个叶子节点来分类实例
  • 叶子节点即为实例所属的分类
  • 树上每个节点说明了对实例的某个属性的测试,节点的每个后继分支对应于该属性的一个可能值

2 决策树结构

这里写图片描述

3 决策树种类

分类树—对离散变量做决策树
回归树—对连续变量做决策树

4 决策树算法

  • 有监督的学习
  • 非参数学习算法
  • 自顶向下递归方式构造决策树
  • 在每一步选择中都采取在当前状态下最好/优的选择
    决策树学习的算法通常是一个递归地选择最优特征,并根据该特征对训练数据进行分割,使得各
    个子数据集有一个最好的分类的过程。在决策树算法中,ID3基于信息增益作为属性选择的度量,C4.5基于信息增益比作为属性选择的度量,CART基于基尼指数作为属性选择的度量。

5 决策树学习过程

  • 特征选择
  • 决策树生成:递归结构,对应于模型的局部最优
  • 决策树剪枝:缩小树结构规模、缓解过拟合,对应于模型的全局选择
6 决策树优缺点

优点:
(1) **速度快:**计算量相对较小,且容易转化成分类规则。只要沿着树根向下一直走到叶,沿途的分裂条件就能够唯一确定一条分类的谓词。
(2) 准确性高:挖掘出的分类规则准确性高,便于理解,决策树可以清晰的显示哪些字段比较重要,即可以生成可以理解的规则。
(3)可以处理
连续和种类字段

缺点:
(1) 对于各类别样本数量不一致的数据,信息增益偏向于哪些具有更多数值的特征
(2) 易于过拟合
(3) 对连续的字段比较难预测
(4) 不是全局最优

二、决策树数学知识

1.信息论
若一事假有k种结果,对应的概率为P_i,则此事件发生后所得到的信息量I为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YvNtq4VP-1594541496321)(http**😕/img.blog.csdn.net/20161113212743385)]
2.熵
给定包含关于某个目标概念的正反样例的样例集S,那么S相对这个布尔型分类的熵为:
这里写图片描述
其中P+代表正样例,p-代表反样例
3.条件熵
假设随机变量(X,Y),其联合分布概率为P(X=xi,Y=yi)=Pij,i=1,2,⋯,n;j=1,2,⋯,m
则条件熵H(Y|X)表示在已知随机变量X的条件下随机变量Y的不确定性,其定义为X在给定条件下Y的条件概率分布的熵对X的数学期望
这里写图片描述

三、决策树算法Hunt

在Hunt算法中,通过递归的方式建立决策树。
1)如果数据集D中所有的数据都属于一个类,那么将该节点标记为为节点。
2)如果数据集D中包含属于多个类的训练数据,那么选择一个属性将训练数据划分为较小的子集,对于测试条件的每个输出,创建一个子女节点,并根据测试结果将D中的记录分布到子女节点中,然后对每一个子女节点重复1,2过程,对子女的子女依然是递归的调用该算法,直至最后停止。

四、决策树算法ID3

1. 分类系统信息熵

这里写图片描述

2. 条件熵

分类系统中的条件熵指的是当样本的某一特征X固定时的信息熵
因此样本特征X取值为xi的概率是Pi,该特征被固定为值xi时的条件信息熵就是H(C|X=xi),那么H(C|X)就是分类系统中特征X被固定时的条件熵(X=(x1,x2,……,xn)):
这里写图片描述

3. 信息增益Gain(S,A)

这里写图片描述

4. 属性选择度量

使用信息增益,选择最高信息增益的属性作为当前节点的测试属性

5. 算法不足

1) 使用ID3算法构建决策树时,若出现各属性值取值数分布偏差大的情况,分类精度会大打折扣
2) ID3算法本身并未给出处理连续数据的方法
3) ID3算法不能处理带有缺失值的数据集,故在算法挖掘之前需要对数据集中的缺失值进行预处理
4) ID3算法只有树的生成,所以该算法生成的树容易产生过拟合

6.算法流程

这里写图片描述

五、决策树算法C4.5

1. 属性选择度量

C4.5算法用信息增益率来选择属性,即选用信息增益比选择最佳特征

2. 信息增益比率度量

信息增益比率度量是用ID3算法中的增益度量Gain(D,X)和分裂信息度量SplitInformation(D,X)来共同定义的。分裂信息度量SplitInformation(D,X)就相当于特征X(取值为x1,x2,……,xn,各自的概率为P1,P2,…,Pn,Pk就是样本空间中特征X取值为Xk的数量除上该样本空间总数)的熵。
SplitInformation(D,X) = -P1 log2(P1)-P2 log2§-,…,-Pn log2(Pn)
GainRatio(D,X) = Gain(D,X)/SplitInformation(D,X)

3.对连续分布特征的处理

C4.5先把连续属性转换为离散属性再进行处理。如果有N条样本,那么我们有N-1种离散化的方法:<=vj的分到左子树,>vj的分到右子树。计算这N-1种情况下最大的信息增益率。
1)对特征的取值进行升序排序
2)两个特征取值之间的中点作为可能的分裂点,将数据集分成两部分,计算每个可能的分裂点的信息增益(InforGain)。优化算法就是只计算分类属性发生改变的那些特征取值。
3)选择修正后信息增益(InforGain)最大的分裂点作为该特征的最佳分裂点
4)计算最佳分裂点的信息增益率(Gain Ratio)作为特征的Gain Ratio。
这里写图片描述

4. 相比ID3算法改进

1) 使用信息增益比例而非信息增益作为分裂标准
2) 处理含有带缺失值的样本方法为将这些值并入最常见的某一类中或以最常用的值代替
3) 处理连续值属性
4)规则的产生:规则集存储于一个二维数组中,每一行代表决策树的一个规则
5) 交互验证:训练开始之前,预留一部分数据,训练之后,使用这部分数据对学习的结果进行验证

六、叶子裁剪

####1.剪枝的原因和目的
解决决策树对训练样本的过拟合问题
####2.决策树常用剪枝方法
预剪枝(Pre-Pruning)和后剪枝(Post-Pruning)

3.预剪枝

预剪枝是根据一些原则及早的停止树增长,如树的深度达到用户所要的深度、节点中样本个数少于用户指定个数、不纯度指标下降的最大幅度小于用户指定的幅度等。

4. 后剪枝

通过在完全生长的树上剪去分枝实现的,通过删除节点的分支来剪去树节点,可以使用的后剪枝方法有多种,比如:代价复杂性剪枝、最小误差剪枝、悲观误差剪枝等等
修剪方式有:
1)用叶子节点来替换子树,叶节点的类别由子树下面的多类决定
2)用子树最常用的分支来替代子树

七、Python sklearn实战

1. Python Sklearn 实现
class sklearn.tree.DecisionTreeClassifier(criterion='gini', splitter='best', max_depth=None, min_samples_split=2,min_samples_leaf=1, max_features=None, random_state=None, min_density=None, compute_importances=None,max_leaf_nodes=None)

比较重要的参数:

  • criterion :规定了该决策树所采用的的最佳分割属性的判决方法,有两种:“gini”,“entropy”。
  • max_depth :限定了决策树的最大深度,对于防止过拟合非常有用
  • min_samples_leaf :限定了叶子节点包含的最小样本数,这个属性对于防止上文讲到的数据碎片问题很有作用

模块中一些重要的属性方法:

  • n_classes_ :决策树中的类数量。
  • classes_ :返回决策树中的所有种类标签
  • feature_importances_ :feature的重要性,值越大,越重要
  • fit(X, y, sample_mask=None, X_argsorted=None, check_input=True, sample_weight=None)
    将数据集x,和标签集y送入分类器进行训练,这里要注意一个参数是:sample_weight,它和样本的数量一样长,所携带的是每个样本的权重。
  • get_params(deep=True) 得到决策树的各个参数。
  • set_params(**params) 调整决策树的各个参数。
  • predict(X) 送入样本X,得到决策树的预测。可以同时送入多个样本。
  • transform(X, threshold=None) 返回X的较重要的一些feature,相当于裁剪数据。
  • score(X, y, sample_weight=None)
    返回在数据集X,y上的测试分数,正确率。

使用建议

  • 当我们数据中的feature较多时,一定要有足够的数据量来支撑我们的算法,不然的话很容易overfitting
  • PCA是一种避免高维数据overfitting的办法
  • 从一棵较小的树开始探索,用export方法打印出来看看。
  • 善用max_depth参数,缓慢的增加并测试模型,找出最好的那个depth。
  • 善用min_samples_split和min_samples_leaf参数来控制叶子节点的样本数量,防止overfitting。
  • 平衡训练数据中的各个种类的数据,防止一个种类的数据dominate
2 Python 实战

测试数据data.txt
1.5 50 thin
1.5 60 fat
1.6 40 thin
1.6 60 fat
1.7 60 thin
1.7 80 fat
1.8 60 thin
1.8 90 fat
1.9 70 thin
1.9 80 fat

Python实战代码
# -*- coding: utf-8 -*-
import numpy as np  
from sklearn import tree  
from sklearn.metrics import precision_recall_curve  
from sklearn.metrics import classification_report  
from sklearn.cross_validation import train_test_split  

#数据读入
data=[]
labels=[]
with open('C:\Users\Allen\Desktop\data.txt') as ifile:
    for line in ifile:
        tokens=line.strip().split(' ')
        data.append([float(tk) for tk in tokens[:-1]])
        labels.append(tokens[-1])
x=np.array(data)
labels=np.array(labels)
y=np.zeros(labels.shape)
#标签转化为0,1
y[labels=='fat']=1
#拆分训练数据和测试数据
x_train,x_test,y_train,y_test=train_test_split(x, y, test_size = 0.2) 
#使用信息熵作为划分标准,对决策树进行训练
clf=tree.DecisionTreeClassifier(criterion='entropy')
print clf
#DecisionTreeClassifier(class_weight=None, criterion='entropy', max_depth=None,
            #max_features=None, max_leaf_nodes=None, min_samples_leaf=1,
            #min_samples_split=2, min_weight_fraction_leaf=0.0,
            #presort=False, random_state=None, splitter='best')
clf.fit(x_train,y_train)
#把决策树写入文件  
with open("tree.dot", 'w') as f:  
    f = tree.export_graphviz(clf, out_file=f)   
# digraph Tree {
# node [shape=box] ;
# 0 [label="X[1] <= 75.0\nentropy = 0.9544\nsamples = 8\nvalue = [3, 5]"] ;
# 1 [label="X[0] <= 1.65\nentropy = 0.971\nsamples = 5\nvalue = [3, 2]"] ;
# 0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ;
# 2 [label="entropy = 0.0\nsamples = 2\nvalue = [0, 2]"] ;
# 1 -> 2 ;
# 3 [label="entropy = 0.0\nsamples = 3\nvalue = [3, 0]"] ;
# 1 -> 3 ;
# 4 [label="entropy = 0.0\nsamples = 3\nvalue = [0, 3]"] ;
# 0 -> 4 [labeldistance=2.5, labelangle=-45, headlabel="False"] ;
# }
#系数反映每个特征的影响力。越大表示该特征在分类中起到的作用越大
print(clf.feature_importances_) 
#测试结果的打印
answer=clf.predict(x_train)
print(x_train)
print(answer)
print(y_train)
print(np.mean(answer==y_train))

#准确率与召回率
#准确率:某个类别在测试结果中被正确测试的比率
#召回率:某个类别在真实结果中被正确预测的比率
#测试结果:array([ 0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.,  0.])
#真实结果:array([ 0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.])
#分为thin的准确率为0.83。是因为分类器分出了6个thin,其中正确的有5个,因此分为thin的准确率为5/6=0.83。
#分为thin的召回率为1.00。是因为数据集中共有5个thin,而分类器把他们都分对了(虽然把一个fat分成了thin!),召回率5/5=1。
#分为fat的准确率为1.00。不再赘述。
#分为fat的召回率为0.80。是因为数据集中共有5个fat,而分类器只分出了4个(把一个fat分成了thin!),召回率4/5=0.80。
#本例中,目标是尽可能保证找出来的胖子是真胖子(准确率),还是保证尽可能找到更多的胖子(召回率)。
precision, recall, thresholds = precision_recall_curve(y_train, clf.predict(x_train))  
answer = clf.predict_proba(x)[:,1]  
print(classification_report(y, answer, target_names = ['thin', 'fat']))  
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值