决策树

决策树

什么是决策树

决策树其实就是一个树形结构,而由于其结构为树,所以决策树能对样本进行分析,因为一个树形结构其实就相当于if-else结构, 树的每一层可以看做是对一个特征的决策。比如下面这个决策是否打篮球的例子,先根据年龄特征:如果年龄小于15则有可能,而大于15则没有可能,然后再根据性别:如果是男性则有可能,是女性则不可能。所以通过一系列的决策便能得到一个数据的类别。

决策树_1.png

决策树创建过程 (如果不想看数学,可直接跳过看下面应用)

在我们使用决策树进行预测的时候,前提是我们有了一棵决策树,所以决策树的关键点在于怎么建造树,建造树的过程里面涉及几个数学概念,下面依次展开。

关于熵的概念

熵以前可能我们都接触过,熵代表了混乱程度,比如两个集合,集合一为:{1,1,1,1,2,2},集合二为:{1,2,3,4,5,6},很显然集合一的混乱程度要低一点,集合二的混乱程度要高一点,但是这个只是我们直观的感觉,现在要把这个直观的感觉转换成数学语言,使用数学公式来表达熵,那么熵可以表示为:
H ( x ) = − ∑ p ( i ) ∗ l o g p ( i ) , i = 1 , 2 , 3 , … , n H(x) = -\sum p(i) * log{p(i)} ,i = 1,2,3,\dots , n H(x)=p(i)logp(i),i=1,2,3,,n

对于这个公式可以用一个极端例子来表示,比如一个集合全部都是1,那么其概率p = 1,所以计算的熵值为0,也就是代表熵值很小,所以混乱程度也很小。所以这个 H ( x ) H(x) H(x)可以作为衡量一组数据的混乱程度。

树的构造

有了熵的概念我们就可以构造树了,其实树的构造主要是选择哪个作为根节点,当选择完根节点后,其左右子树同样也是选择计算子树的根节点(这就是一个同样的过程),所以这里介绍怎么找到根节点。

在进行树的构造,我们的目的是构造一棵尽量矮的树,并且能赶快把数据分开,也就是赶快分到叶子节点,而叶子节点的特点就是种类比较少,纯度比较高,所以也就是熵值比较低的节点,所以你的目的就是找到一个根节点,划分后,其熵值下降的最快,这个熵值下降的值就叫做信息增益。比如下面这个例子:

决策树_2.png

里面有14个样本,表示不同因素对于是否出去玩的影响,outlook代表外面天气…。

选择根节点步骤:

一、先计算目前的熵值,在14个样本中有9天是出去玩,5天不出玩,所以熵值为  −(9/14*log(9/14)+5/14*log(5/14))=0.940。  

二、然后我们在计算基于outlook进行划分后的熵值。  

	1. 当outlook = sunny时,可以看出共有5个样本其中2个出去玩,3个不出去玩,所以对应熵值为0.971。  
	2. 当outlook = overcast时,可以看出共有4个样本其中4个出去玩,所以对应熵值为0。  
	3. 当outlook = rainy时,可以看出共有5个样本其中3个出去玩,2个不出去玩,所以对应熵值为0.971(可以看出如果总样本个数一样,然后分布一样其熵值也一样)。  
	4. 而outlook取值为sunny,overcast,rainy的概率分别为:5/14, 4/14, 5/14,所以使用outlook进行划分的最终熵值是 5/14 * 0.971 + 4/14 * 0 + 5/14 * 0.971 = 0.693

三、根据原来的熵值0.940,以及现在根据outlook划分后的熵值0.693,得出其信息增益为0.940-0.693 = 0.247。  

四、使用上面同样的方法(第二步开始)计算基于temperature、humidity、windy划分得到的信息增益,然后比较得出最大的信息增益那个,这样就可以使这个树向着变纯的方向变化的更快,树也会更矮。  

然后第二层也同样计算熵,然后按照特征进行划分,计算信息增益,最后分别得到子树的根节点,最后组成一棵树。

当前构造方法的弊端

假如当前特征值里面有一个ID特征,那么显然每个样本ID是惟一的,所以此时对树的根节点划分的时候会出现ID的信息增益是最大的(因为基于ID划分的熵值为0),但这样是没有意义的,因为ID不具有实际意义。这个时候就可以引入其他的方式来代替信息增益的计算方式,比如C4.5、GINI系数等,有兴趣可以查阅资料了解,这些方法的不同之处仅仅在与在算下降的时候换了中方式,原来我们是使用熵值以及熵值的差来作为评判标准的,而其他算法则使用不同评判标准。

使用sklearn中的决策树

导入相应的库
from sklearn.tree import DecisionTreeClassifier
from sklearn import datasets,model_selection
import numpy as np
import matplotlib.pyplot as plt   

datasets里面存储了一些数据集可以直接使用,model_selection进行测试集和训练集的划分,你也可以使用交叉验证进行划分。

读数据集
#读数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
#数据集划分
X_train,X_test,y_train,y_test = modeel_data = model_selection.train_test_split(X, y,test_size=0.25,random_state=0,stratify=y)  

这段代码实现了读取数据集,并且把数据集划分成训练集和测试集两部分。

对数据集进行训练并进行预测
# 初始化一个决策树,其中criterion代表采用的策略,这里使用gini,你也可以选择熵值entropy策略。max_depth是指生成树的最大高度,这样可以避免树太过于高,造成过拟合
clf = DecisionTreeClassifier(criterion="gini",max_depth=10)
# 开始训练
clf.fit(X_train,y_train)
# 准确率预测
score= clf.score(X_test,y_test)  
通过画图分析结果

这次是画出来不同策略在不同深度下对最终正确率的影响。

# 生成树的时候可以采用gini(CART决策树)也可以使用信息熵entropy(ID3)策略
# entropy gini
criterions = ['gini','entropy']
# 深度从1到40 每次都测试一下
depths = np.arange(1,40)
# 记录不同策略下的分数,train代表用该树验证训练集的正确率(一般都很高的)
scores ={criterions[0]:[],criterions[1]:[],"train":[]}

# 先验证两种不同策略下的不同高度的准确率
for criterion in criterions:
    for depth in depths:
        clf = DecisionTreeClassifier(criterion=criterion,max_depth=depth)
        clf.fit(X_train,y_train)
        scores[criterion].append(clf.score(X_test,y_test))
        
# 再验证一下该树在训练集下的正确率(作为参考,一把这个正确率能达到100%),可以最为gini和entropy的参考
for depth in depths:
    clf = DecisionTreeClassifier(criterion=criterion,max_depth=depth)
    clf.fit(X_train,y_train)
    scores["train"].append(clf.score(X_train,y_train))
# 画第一个折线图,在策略为gini时不同高度的情况 
plt.plot(depths,scores[criterions[0]],marker='o',label =criterions[0])
# 画第二个折线图,在策略为entropy时不同高度的情况 
plt.plot(depths,scores[criterions[1]],marker='*',label =criterions[1])
# 画第三个折线图,在训练集时不同高度的情况 
plt.plot(depths,scores["train"],marker='*',label ="best")
plt.legend(framealpha=0.5,loc='best')
plt.show()

最终图片如下:

决策树_3.png

结论

可以看出一般情况下在训练集下其准确率几乎100%,然后gini通常由于entropy,但是树的高度并不是越高越好,如果越高可能会出现过拟合现象。

欢迎大家关注我的微信公众号,未来上面会推送python 机器学习 算法学习 深度学习 论文阅读 以及偶尔的小鸡汤等内容。ようこそいらっしゃい!

搜索 coderwangson 关注

image

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值