应用机器学习(六):决策树

时间:2021-07-16 10:25:03

决策树

决策树( decision tree )是一个树状图。其中,树里的每一个节点代表着对某一个属性的检验。例如,一次掷币试验出现正面还是反面。每一个分支代表一个检验的结果,每一个叶子节点代表一个类标签,即,经过所有属性计算后的决策结果。这样,从树根到叶子的不同路径代表了不同的分类规则。目标变量取离散值的树模型称分类树;目标变量取连续值的决策树称回归树。举个例子,根据周六上午的天气状况决定是否适合打网球。


应用机器学习(六):决策树

  • each node: 检验一个特定的属性;

  • each branch from a node: 选择属性的一个值;

  • each leaf node: 预测是否适合打网球。

决策树适用的问题

  • 实例由属性和互斥的属性值的集合表示。例如,属性 *Temperature, 值Hot, Mild, Cold.*

  • 目标函数取离散的输出值。例如,图1的分类树给每一个实例一个二值分类( yes or no ).

  • 训练集可能包括误差或缺失属性值。决策树学习方法对训练实例的分类误差和属性值误差是健壮的。

决策树学习

决策树学习使用带有类标签的训练实例构建一棵决策树。一棵决策树是一个类似流程图的结构,每一个内部节点代表一个对某属性的检验,每一个分支代表一个检验结果,每一个叶子节点则代表一个类标签。特别地,称树的最上层节点为根节点。常用的决策树学习算法有:

  • ID3 (Iterative Dichotomiser 3)
  • C4.5 ((successor of ID3)
  • CART (Classification and Regression Tree)

下面,介绍基本的 ID3 算法:

ID3 算法初始将数据集 S 作为根节点。在算法的每一次迭代,对任一未使用的属性,计算集 S 的熵 H(s) (也称信息增益 IG(S) )。然后,选择具有最小熵(或最大信息增益)值的属性。集 S 随后根据所选属性(例如,人的年龄小于50,在50到100之间,还是大于100)被拆分成若干个数据子集。算法继续在子集上递归,仅仅考虑之前从未被选择的属性。子集上的递归遇到下列情况之一则停止:

  • 子集中的每一个实例属于相同的类,那么节点变成了叶子节点,类标签为实例所属的类。

  • 不再有未使用过的属性可选,但实例仍然不属于相同的类,那么节点变成了叶子节点,类标签为子集中多数实例所属的类。

  • 子集中没有实例,这是因为在父集(上一层集)里没有实例对应所选属性的某个特定的值(例如,没有年龄大于100的人)。这时,也产生一个父集下的叶子节点,类标签为父集里多数实例所属的类。

纵观整个算法,在决策树构建过程中,每一个非终端节点代表一个选择的属性,数据依该属性的不同值被拆分,而终端节点代表分支最终的子集的类标签。

  • ID3 算法概要

    1. 计算每一个属性在数据集 S 上的熵;

    2. 根据最小熵(拆分后)的属性拆分集 S;

    3. 产生一个包含属性的决策树节点;

    4. 使用剩余的属性在子集上递归。

ID3 算法伪代码

ID3 (Examples, Target_Attribute, Attributes)
    Create a root node for the tree
    If all examples are positive, 
    Return the single-node tree Root, with label = +.
    If all examples are negative, 
    Return the single-node tree Root, with label = -.
    If number of predicting attributes is empty, 
    then Return the single node tree Root,
    with label = most common value of the target attribute
    in the examples.
    Otherwise Begin
        A ← The Attribute that best classifies examples.
        Decision Tree attribute for Root = A.
        For each possible value, vi, of A,
            Add a new tree branch below Root, corresponding 
            to the test A = vi.
            Let Examples(vi) be the subset of examples that 
            have the value vi for A
            If Examples(vi) is empty
                Then below this new branch add a leaf node 
                with label = most common target value 
                in the examples
            Else 
            below this new branch add the subtree ID3 
            (Examples(vi), Target_Attribute, 
            Attributes – {A})
    End
    Return Root

ID3 算法测度

  • 熵(Entropy)

H(S) 度量数据集 S 的不确定性总量,定义为

H(S)=xXp(x)log21p(x)

这里, S 是当前数据集, XS 里的类集, p(x) 是属于类 x 的实例数 / S 里的实例数。
特别地,如果 H(S)=0,那么 S 被完美分类,即, S 里的实例属于相同的类。

ID3 算法的迭代过程里,每一个未使用的属性都要计算熵,具有最小熵的属性被用来拆分当前数据集 S。熵越大,改善分类的潜力越大。

  • 信息增益( Information Gain )

信息增益 IG(A, S) 表示根据属性 A 拆分数据集 S 前后的熵差,换句话说,它表示根据属性 A 拆分 S 后,S 的不确定性减少了多少。具体定义为

IG(A,S)=H(S)tTp(t)H(t)

这里, H(S) 是集 S 的熵, T 是拆分 S 后的子集,即 S=tTt , p(t)t 的实例数 / S 的实例数, H(t)t 的熵。

ID3 算法的迭代过程里,每一个未使用的属性都要计算信息增益(代替熵),具有最大增益的属性被用来拆分当前数据集
S

一个例子:PlayTennis 的决策树学习

PlayTennis 的训练集如下:


应用机器学习(六):决策树

训练集 S 有14个实例,PlayTennis 类标签为 yes(+) or no(-),共9个 +,5个 -。 不妨观察属性 Wind,取两个值 Weak and Strong,那么,计算属性 WindS 上的信息增益。同理,可以计算其它属性在 S 上的信息增益。

  • ID3 算法的第一步

分别计算候选属性 Outlook, Temperature, Humidity, and Wind 的信息增益。由于属性 Outlook 的信息增益最大,故选择它作为根节点的决策属性。根据 Outlook 的不同取值在根节点下产生三个分支 Sunny, Overcast and Rain. 第一步后的决策树如图5所示。


应用机器学习(六):决策树


应用机器学习(六):决策树


应用机器学习(六):决策树

注意到,子节点 Overcast 的实例都是 + 类,故它的子节点是叶子节点,类标签为 +.

  • ID3 算法的第二步

对于每一个非终端节点,即, Sunny and Rain,实例属于不同的类,因此,使用这些节点的训练实例,继续计算这两个子节点上的剩余属性,即, Temperature, Humidity, and Wind 的信息增益。选择增益最大的新属性,将当前训练实例按它的不同值拆分。

  • ID3 算法的第三步

迭代此过程,直到满足下列条件之一:

(1). 每一个属性都已经被包括在树的路径里;

(2). 叶子节点的实例有相同的类标签。

该例子最终得到的决策树见图1.

决策树学习的过度拟合问题

有时,训练数据集存在噪音( noise ),或者训练实例太少而不能作为真实类别总体的典型样本。这些情况下,决策树学习可能过度拟合( overfit )了训练样本。所谓”过度拟合”,是指学习算法拟合训练实例的效果很好,但对于新实例,预测效果却很差。

那么,怎样避免过度拟合呢? 一种常见的办法是对决策树进行修剪( pruning )。具体说,就是对某些决策节点进行“剪枝”,这指的是,剪除该节点下的子树,将它变成叶子节点。按该节点的大多数实例所属的类分配这个叶子的类标签。将原始数据集分成训练集和验证集两部分,在训练集上构建决策树,在验证集上修剪它。迭代地修剪节点,确保每次剪枝后的决策树,在验证集上预测准确率改善最大。

一个例子:识别高风险的银行贷款

某家银行收集了1,000个贷款客户的个人信息,由16个特征组成,目标变量是 default, 表示该客户是否为高风险客户,它取 yes or no 的二值变量。这16个特征分别是

  1. checking_balance —— 支票账户余额(单位:德国马克( DM ),现已被欧元取代);

  2. months_loan_duration —— 贷款期限(单位:月);

  3. credit_history —— 信用历史状况;

  4. purpose —— 贷款目的;

  5. amount —— 贷款数目;

  6. savings_balance —— 存款余额;

  7. employment_duration —— 工作时间;

  8. percent_of_income —— 收入比例;

  9. years_at_residence —— 居住时间;

  10. age —— 客户年龄;

  11. other_credit —— 其它信用情况;

  12. housing —— 住房情况;

  13. existing_loans_count —— 已有贷款笔数;

  14. job —— 工作性质;

  15. dependents —— 依赖关系;

  16. phone —— 是否留有电话;

  17. default —— 是否为高风险贷款客户.

由这1,000个客户的17个特征/变量组成数据文件 credit.csv ,可以从网盘 http://pan.baidu.com/s/1gftG5wf 下载。

下面,用决策树识别高风险的贷款客户。首先,探索并准备数据。

dir <- "E:/机器学习/论文/代码/DecisionTree"
setwd(dir)
credit <- read.csv("credit.csv")
str(credit)

# look at two characteristics of the applicant
table(credit$checking_balance)
table(credit$savings_balance)

# look at two characteristics of the loan
summary(credit$months_loan_duration)
summary(credit$amount)

# look at the class variable
table(credit$default)
# create a random sample for training and test data
# use set.seed to use the same random number sequence as the tutorial
set.seed(12345)
credit_rand <- credit[order(runif(1000)), ]

# compare the credit and credit_rand data frames
summary(credit$amount)
summary(credit_rand$amount)
head(credit$amount)
head(credit_rand$amount)

# split the data frames
credit_train <- credit_rand[1:900, ]
credit_test  <- credit_rand[901:1000, ]

# check the proportion of class variable
prop.table(table(credit_train$default))
prop.table(table(credit_test$default))

第二步,在 R 环境下安装并加载 C50 包,使用函数 C5.0 在训练集上构建一个简单的决策树。

library(C50)
credit_model <- C5.0(credit_train[-17], credit_train$default)

# display simple facts about the tree
credit_model

# display detailed information about the tree
summary(credit_model)

第三步,在检验集上评价决策树模型的表现。

# create a factor vector of predictions on test data credit_pred <- predict(credit_model, credit_test) # cross tabulation of predicted versus actual classes library(gmodels) CrossTable(credit_test$default, credit_pred, prop.chisq = FALSE, prop.c = FALSE, prop.r = FALSE, dnn = c('actual default', 'predicted default'))


应用机器学习(六):决策树

第四步,改善优化决策树模型。

## Boosting the accuracy of decision trees
# boosted decision tree with 10 trials
credit_boost10 <- C5.0(credit_train[-17], credit_train$default,
                       trials = 10)
credit_boost10
summary(credit_boost10)

credit_boost_pred10 <- predict(credit_boost10, credit_test)
CrossTable(credit_test$default, credit_boost_pred10,
           prop.chisq = FALSE, prop.c = FALSE, prop.r = FALSE,
           dnn = c('actual default', 'predicted default'))

# boosted decision tree with 100 trials (not shown in text)
credit_boost100 <- C5.0(credit_train[-17], credit_train$default,
                        trials = 100)
credit_boost_pred100 <- predict(credit_boost100, credit_test)
CrossTable(credit_test$default, credit_boost_pred100,
           prop.chisq = FALSE, prop.c = FALSE, prop.r = FALSE,
           dnn = c('actual default', 'predicted default'))


应用机器学习(六):决策树

通过比较优化前后的决策树分类结果发现,优化后的决策树,对于检验集中 default 值取 no 的观测,预测准确性明显改善。

阅读更多精彩内容,请关注微信公众号“统计学习与大数据”!