1.决策树算法简介
决策树是一种分类学习的方法,思想来源很朴素,类似于程序设计中的条件分支结构(if-else)。
决策树特点如下:
- 是一种树形结构,本质是一颗由多个判断节点组成的树。
- 其中每个内部节点表示一个属性上的判断。
- 每个分支代表一个判断结果的输出。
- 最后每个叶节点代表一种分类的结果。
举个例子来介绍一下决策树算法:
比如你的朋友邀请你去某个地方郊游,你跟他的对话是这样的:
你:远吗?
朋友:5km。
你:风景怎么样?
朋友:有山有水。
你:什么时候去?
朋友:两天以后。
你:那天天气如何?
朋友:天朗气清,惠风和畅。
你:那好,我们一起去。
以下是你的lua决策树:
是否参加郊游?
|__ 距离 <= 5km?
|__ 是
|__ 否
|__ 风景是否有山有水?
|__ 是
|__ 出发时间是否在两天以后?
|__ 是
|__ 天气是否天朗气清、惠风和畅?
|__ 是 --> 参加郊游
|__ 否 --> 不参加郊游
|__ 否 --> 不参加郊游
|__ 否 --> 不参加郊游
2.决策树分类原理
2.1 熵
2.1.1概念
在物理学上,熵(Entropy) 是“混乱”程度的量度。
熵值越低,系统越有序;熵值越高,系统越混乱。
信息熵(Entropy)的概念是香农在1948年提出的。
信息理论:
- 信息完整性描述:
当系统的有序性状态一致时,数据越集中的地方熵值越小,数据越分散的地方熵值越大。- 信息有序性描述:
当数据量一致时,系统越有序,熵值越低;系统越混乱,熵值越高。
"信息熵" (information entropy)是度量样本集合纯度最常⽤的⼀种指标。
假定当前样本集合 D 中第 k 类样本所占的⽐例为 P_{k}(k = 1, 2,. . . , |y|) ,
,D为样本的所有数量,分子为第k类样本的数量。
则D的信息熵定义为(log是以2为底,lg是以10为底):
其中:Ent(D)越小,则D的纯度越高。
2.2 决策树的划分依据⼀----信息增益
2.2.1 概念
信息增益:以某特征划分数据集前后的熵的差值。熵可以表示样本集合的不确定性,熵越大,样本的不确定性就越大。因此可以使用划分前后的差值来衡量当前特征对于样本集合D划分效果的好坏。
信息增益 = entroy(前) - entroy(后)
信息增益表示得知特征X的信息而使得类Y的信息熵减少的程度。
定义与公式:
假定离散属性a有 V 个可能的取值:
设使用a来对样本集D进行划分,则会产生V个分支节点。
其中第V个分支节点包含了D中所有属性a上取值为的样本,我们可以根据前面给出的信息熵公式计算出的信息熵,在考虑到不同分支节点包含的样本数不同,给分支节点赋予权重
即样本数越多的分⽀结点的影响越⼤,于是可计算出⽤属性a对样本集 D 进⾏划分所获得的"信息增益" (information gain)
其中:
特征a对训练数据集D的信息增益Gain(D,a)定义为集合D的信息熵Ent(D)与给定特征条件下D的信息条件熵Ent(D|a)之差,即公式为:
公式的详细解释:
信息熵的计算:
Ent(D)=-\sum_{k=1}^n\frac{C^k}Dlog\frac{C^k}D
条件熵的计算:
其中:
表示a属性中第v个分支节点包含的样本数
表示a属性中第v个分支节点包含的样本数,第K个类别下包含的样本数。
⼀般⽽⾔,信息增益越⼤,则意味着使⽤属性 a 来进⾏划分所获得的"纯度提升"越⼤。因此,我们可⽤信息增益来进⾏决策树的划分属性选择,著名的 ID3 决策树学习算法 [Quinlan, 1986] 就是以信息增益为准则来选择划分属性。
其中,ID3 名字中的 ID 是 Iterative Dichotomiser (迭代⼆分器)的简称
3 决策树的划分依据⼆----信息增益率
3.1 概念
增益率:增益率是用前面的信息增益Gain(D,a)和属性a对应的“固有值”(intrinsic value)的比值来共同定义的。
其中
属性a的可能取值数目越多(V越大),则IV(a)的值通常会越大。
4 决策树的划分依据三 ----基尼值和基尼指数
4.1 概念
CART 决策树 [Breiman et al., 1984] 使用"基尼指数" (Gini index)来选择划分属性.
CART 是Classification and Regression Tree的简称,这是⼀种著名的决策树学习算法,分类和回归任务都可⽤
基尼值Gini(D):从数据集D中随机抽取两个样本,其类别标记不⼀致的概率。故,Gini(D)值越小,数据集D的纯度越高。
其中,D为样本的所有数量,为第k类样本的数量。
基尼指数Gini_index(D):一般选择使划分后的基尼系数最小的属性作为最优化属性。
5.决策树算法总结
5.1 ID3算法
存在缺点:
- ID3算法在选择根节点和各内部节点中的分支属性时,采用信息增益作为评价标准。信息增益的缺点是倾向于选择取值较多的属性,在有些情况下这类属性可能不会提供太多有价值的信息。
- ID3算法只能对描述属性为离散型属性的数据集构造决策树。
5.2 C4.5算法
做出的改进(有点)
- 用信息增益率来选择属性
- 可以处理连续数值型属性
- 采用后剪枝方法
- 对于缺失值的处理
有点:
产生的分类规则易于理解,准确率较高。
缺点:
- 在构造树的过程中,需要对数据集进行多次的顺序扫描和排序,因而导致算法的低效。
- C4.5只适合于能够驻留于内存的数据集,当训练集过大无法在内存容纳时程序无法运行。
5.3 CART算法
CART算法相比于C4.5算法的分类方法,采用简化的二叉树模型,同时特征选择采用了近似的基尼系数来简化计算。
C4.5不一定是二叉树,但CART一定是二叉树。
5.4 多变量决策树(multi-variate decision tree)
⽆论是ID3, C4.5还是CART,在做特征选择的时候都是选择最优的一个特征来做分类决策,但是大多数,分类决策应该由一组特征决定而不是某一个特征。这样得到的决策树才能更加精准。这个决策树叫做多变量决策树。在选择最优特征的时候,多变量决策树不是选择某一个最优特征,二十选择最优的一个特征线性组合来做决策。
如果样本发生一点点改动,就会导致树结构的剧烈改变。这个可以通过集成学习里边的随机森林之类的方法解决。
5.5 决策树变量的两种类型:
- 数字型(Numeric):变量类型是证书或者浮点数。(排序后,利⽤已有的分割情况,可以优化分割算法的时间复杂度)。
- 名称型(Nominal):类似编程语言的枚举类型,变量只能在有限的选项中选取。
5.6 如何评价分割点好坏?
如果一个分割点可以将当前所有的节点分成两类,使得每一类都很“纯”,也就是同一类的记录较多,那么就是一个好的分割点。
构建决策树采用贪心算法,只考虑当前纯度差最大的情况作为分割点。
6. cart剪枝
6.1 为什么要剪枝
剪枝 (pruning)是决策树学习算法对付"过拟合"的主要手段。
在决策树学习中,为了尽可能正确分类训练样本,结点划分过程将不断重复,有时会造成决策树分支过多,这时就可能因训练样本学得"太好"了,以致于把训练集⾃身的⼀些特点当作所有数据都具有的⼀般性质而导致过拟合。因此,可通过主动去掉一些分支来降低过拟合风险。
6.2 常用的剪枝方法
决策树剪枝的基本策略有两种:预剪枝(pre-pruning)和后剪枝(post- pruning)。
- 预剪枝是指在决策树生成过程中,对每个节点在划分钱进行估计,若当前节点的划分前进行估计,若当前节点不能带来决策树泛化性能提升,则停止划分并将当前节点标记为叶节点。
- 后剪枝是指先从训练集生成一棵完整的决策树,然后自底向上对非叶节点进行考察,若将该机对应的子树替换为叶节点能带来决策树泛化性能提升,则将该孩子树替换为叶节点。
7 特征工程-特征提取
7.1 定义
将任意数据(文本或图像)转换为可用于机器学习的数字特征。
注:特征值化是为了计算机更好的去理解数据。
特征提取分类:
- 字典特征提取(特征离散化)
- 文本特征提取
- 图像特征提取
特征提取API:
sklearn.feature_extraction
7.2 字典特征提取
作用:对字典数据进行特征值化
7.2.1 应用
数据特征提取
文本特征提取
7.2.2 Tf-idf⽂本特征提取
- TF-IDF的主要思想:如果某个词或者短语在一篇文章中出现的概率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
- TF-IDF作用:用以评估一字词对于一个文件集或一个语料库的其中一份文件的重要程度。
公式:
- 词频(term frequency,tf):值得是某一个给定的词语在该文件中出现的频率。
- 逆向文档频率(inverse document frequency,idf)是一个词语普遍重要性的度量。某一特定词语的idf,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取以10为底的对数得到。
最终得出的结果可以理解为重要程度。
8 决策树算法API
class sklearn.tree.DecisionTreeClassifier(criterion=’gini’, max_depth=None,random_state=None)
- criterion
· 特征选择标准
· "gini"或者"entropy",前者代表基尼系数,后者代表信息增益。⼀默认"gini",即CART算法。- min_samples_split
· 内部节点再划分所需最⼩样本数
· 这个值限制了⼦树继续划分的条件,如果某节点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分。 默认是2.如果样本量不⼤,不需要管这个值。如果样本量数量级⾮常大,则推荐增大这个值。
可以作为参考。- min_samples_leaf
· 叶子节点最少样本数
· 这个值限制了叶⼦节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点⼀起被剪枝。默认是1,可以输⼊最少的样本数的整数,或者最少样本数占样本总数的百分比。如果样本量不⼤,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。- max_depth
· 决策树最⼤深度
· 决策树的最⼤深度,默认可以不输⼊,如果不输⼊的话,决策树在建立子树的时候不限制子树的深度。⼀般来说,数据少或者特征少的时候可以不管这个值。如果模型样本量多,特征也多的情况下,推荐限制这个最⼤深度,具体的取值取决于数据的分布。常用的可以取值10-100之间- random_state
· 随机数种子
9 案例:泰坦尼克号乘客生存预测
9.1 案例背景
泰坦尼克号沉没是历史上最臭名昭着的沉船之⼀。1912年4⽉15⽇,在她的处⼥航中,泰坦尼克号在与冰⼭相撞后沉没,在2224名乘客和机组⼈员中造成1502⼈死亡。这场耸⼈听闻的悲剧震惊了国际社会,并为船舶制定了更好的安全规定。 造成海难失事的原因之⼀是乘客和机组⼈员没有⾜够的救⽣艇。尽管幸存下沉有⼀些运⽓因素,但有些⼈⽐其他⼈更容易⽣存,例如妇⼥,⼉童和上流社会。 在这个案例中,我们要求您完成对哪些⼈可能存活的分析。特别是,我们要求您运⽤机器学习⼯具来预测哪些乘客幸免于悲剧。
import pandas as pd
import numpy as np
from sklearn.feature_extraction import DictVectorizer
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier, export_graphviz
# 1、获取数据
titan = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")
x = titan[["pclass", "age", "sex"]]
y = titan["survived"]
# 缺失值需要处理,将特征当中有类别的这些特征进⾏字典特征抽取
x['age'].fillna(x['age'].mean(), inplace=True)
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=22)
# 对于x转换成字典数据x.to_dict(orient="records")
# [{"pclass": "1st", "age": 29.00, "sex": "female"}, {}]
transfer = DictVectorizer(sparse=False)
x_train = transfer.fit_transform(x_train.to_dict(orient="records"))
x_test = transfer.fit_transform(x_test.to_dict(orient="records"))
# 4.机器学习(决策树)
estimator = DecisionTreeClassifier(criterion="entropy", max_depth=5)
estimator.fit(x_train, y_train)
# 5.模型评估
estimator.score(x_test, y_test)
estimator.predict(x_test)
export_graphviz(estimator, out_file="./data/tree.dot", feature_names=['age', 'pclass=1st', 'pclass=2nd', 'pclas
s=3rd', '⼥性', '男性'])
9.2 实验结果
digraph Tree {
node [shape=box] ;
0 [label="petal length (cm) <= 2.45\nentropy = 1.584\nsamples = 112\nvalue = [39, 37, 36]"] ;
1 [label="entropy = 0.0\nsamples = 39\nvalue = [39, 0, 0]"] ;
0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ;
2 [label="petal width (cm) <= 1.75\nentropy = 1.0\nsamples = 73\nvalue = [0, 37, 36]"] ;
0 -> 2 [labeldistance=2.5, labelangle=-45, headlabel="False"] ;
3 [label="petal length (cm) <= 5.05\nentropy = 0.391\nsamples = 39\nvalue = [0, 36, 3]"] ;
2 -> 3 ;
4 [label="sepal length (cm) <= 4.95\nentropy = 0.183\nsamples = 36\nvalue = [0, 35, 1]"] ;
3 -> 4 ;
5 [label="petal length (cm) <= 3.9\nentropy = 1.0\nsamples = 2\nvalue = [0, 1, 1]"] ;
4 -> 5 ;
6 [label="entropy = 0.0\nsamples = 1\nvalue = [0, 1, 0]"] ;
5 -> 6 ;
7 [label="entropy = 0.0\nsamples = 1\nvalue = [0, 0, 1]"] ;
5 -> 7 ;
8 [label="entropy = 0.0\nsamples = 34\nvalue = [0, 34, 0]"] ;
4 -> 8 ;
9 [label="petal width (cm) <= 1.55\nentropy = 0.918\nsamples = 3\nvalue = [0, 1, 2]"] ;
3 -> 9 ;
10 [label="entropy = 0.0\nsamples = 2\nvalue = [0, 0, 2]"] ;
9 -> 10 ;
11 [label="entropy = 0.0\nsamples = 1\nvalue = [0, 1, 0]"] ;9 -> 11 ;
12 [label="petal length (cm) <= 4.85\nentropy = 0.191\nsamples = 34\nvalue = [0, 1, 33]"] ;
2 -> 12 ;
13 [label="entropy = 0.0\nsamples = 1\nvalue = [0, 1, 0]"] ;
12 -> 13 ;
14 [label="entropy = 0.0\nsamples = 33\nvalue = [0, 0, 33]"] ;
12 -> 14 ;
}
那么这个结构不能看清结构,所以可以在⼀个⽹站上显示⽹站显示结构
10 回归决策树
10.1 原理概述
决策树和回归决策树的两个核心问题:
- 如何选择划分点?
- 如何决定叶节点的输出值?
一个回归树对应着输入空间(特征空间)的一个划分以及在划分单元上的输出值。分类树中,我们采用信息论中的方法,通过计算选择最佳划分点。
⽽在回归树中,采⽤的是启发式的⽅法。假如我们有n个特征,每个特征有si (i ∈ (1, n))个取值,那我们遍历所有特征,尝试该特征所有取值,对空间进⾏划分,直到取到特征 j 的取值 s,使得损失函数最⼩,这样就得到了⼀个划分点。描述该过程的公式如下:
假设将输⼊空间划分为M个单元:R1 , R 2, ..., Rm 那么每个区域的输出值就是:也就是该区域内所有点y值的平均数。
10.2 算法描述
- 输入:训练数据集D
- 输出:回归树 f(x)
- 在训练数据集所在的输入空间中,递归的将每个区域划分为两个子区域并决定每个子区域上的输出值,构建二叉决策树:
(1)选择最优切分特征j于切分点s,求解
遍历特征j,对固定的切分特征j扫描切分点s,选择使得上式达到最小值的对(j,s)
(2)用选定的对(j,s)划分区域并决定相应的输出值:
(3)继续对两个子区域调用步骤(1)和(2),直到满足条件。
(4)将输入空间划分为M个区域R1,R2···,Rm,生成决策树:
10.3 回归决策树和线性回归对比
import numpy as np
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeRegressor
from sklearn import linear_model
# ⽣成数据
x = np.array(list(range(1, 11))).reshape(-1, 1)
y = np.array([5.56, 5.70, 5.91, 6.40, 6.80, 7.05, 8.90, 8.70, 9.00, 9.05])
# 训练模型
model1 = DecisionTreeRegressor(max_depth=1)
model2 = DecisionTreeRegressor(max_depth=3)
model3 = linear_model.LinearRegression()
model1.fit(x, y)
model2.fit(x, y)
model3.fit(x, y)
# 模型预测
X_test = np.arange(0.0, 10.0, 0.01).reshape(-1, 1) # ⽣成1000个数,⽤于预测模型
X_test.shape
y_1 = model1.predict(X_test)
y_2 = model2.predict(X_test)
y_3 = model3.predict(X_test)
# 结果可视化
plt.figure(figsize=(10, 6), dpi=100)
plt.scatter(x, y, label="data")
plt.plot(X_test, y_1,label="max_depth=1")
plt.plot(X_test, y_2, label="max_depth=3")
plt.plot(X_test, y_3, label='liner regression')
plt.xlabel("data")
plt.ylabel("target")
plt.title("Decision Tree Regression")
plt.legend()
plt.show()
实验结果