决策树
决策树( 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 算法概要
计算每一个属性在数据集 S 上的熵;
根据最小熵(拆分后)的属性拆分集 S;
产生一个包含属性的决策树节点;
使用剩余的属性在子集上递归。
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 的不确定性总量,定义为
这里, S 是当前数据集, X 是 S 里的类集, p(x) 是属于类 x 的实例数 / S 里的实例数。
特别地,如果 H(S)=0,那么 S 被完美分类,即, S 里的实例属于相同的类。
在 ID3 算法的迭代过程里,每一个未使用的属性都要计算熵,具有最小熵的属性被用来拆分当前数据集 S。熵越大,改善分类的潜力越大。
- 信息增益( Information Gain )
信息增益 IG(A, S) 表示根据属性 A 拆分数据集 S 前后的熵差,换句话说,它表示根据属性 A 拆分 S 后,S 的不确定性减少了多少。具体定义为
这里, H(S) 是集 S 的熵, T 是拆分 S 后的子集,即
在 ID3 算法的迭代过程里,每一个未使用的属性都要计算信息增益(代替熵),具有最大增益的属性被用来拆分当前数据集
S。
一个例子:PlayTennis 的决策树学习
PlayTennis 的训练集如下:
训练集 S 有14个实例,PlayTennis 类标签为 yes(+) or no(-),共9个 +,5个 -。 不妨观察属性 Wind,取两个值 Weak and Strong,那么,计算属性 Wind 在 S 上的信息增益。同理,可以计算其它属性在 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个特征分别是
checking_balance —— 支票账户余额(单位:德国马克( DM ),现已被欧元取代);
months_loan_duration —— 贷款期限(单位:月);
credit_history —— 信用历史状况;
purpose —— 贷款目的;
amount —— 贷款数目;
savings_balance —— 存款余额;
employment_duration —— 工作时间;
percent_of_income —— 收入比例;
years_at_residence —— 居住时间;
age —— 客户年龄;
other_credit —— 其它信用情况;
housing —— 住房情况;
existing_loans_count —— 已有贷款笔数;
job —— 工作性质;
dependents —— 依赖关系;
phone —— 是否留有电话;
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 的观测,预测准确性明显改善。
阅读更多精彩内容,请关注微信公众号“统计学习与大数据”!