1.与KNN 算法比较
1.1 共同点
决策树和KNN算法一样,都是用于处理分类问题。(决策树也可以解决回归问题,但少用)
1.2 不同点
KNN算法处理的是连续性数据;决策树处理的离散型数据。
离散型数据(特征、属性):取值可以具有有限个或无限可数个值,这个值可以用来定性描述属性的汉字、单词;当然也可以是整数,注意是整数,而不是浮点数。
连续性数据:不是离散型数据的就是连续性数据。
想使用决策树算法,我们可以将连续性数据转化为离散型数据。
2.核心
构造决策树的基本思想是随着树的深度加深,节点的熵值迅速的降低。熵降低的速度越快,这样我们有望得到一颗高度最矮的决策树。
3.信息熵的概念、公式
3.1概念
信息是个很抽象的概念。人们常常说信息很多,或者信息较少,但却很难说清楚信息到底有多少。比如一本五十万字的中文书到底有多少信息量。
直到1948年,香农提出了“信息熵”的概念,才解决了对信息的量化度量问题。信息熵这个词是C.E.Shannon(香农)从热力学中借用过来的。热力学中的热熵是表示分子状态混乱程度的物理量。香农用信息熵的概念来描述信源的不确定度。
简言之,一个事情越不确定(即这件事发生的概率越小),信息熵就越大。
3.2 公式
3.3例子
初步建立决策树:
4.条件熵、信息增益
为什么我们会选用是否能在水下生活作为根节点,其实这和这个特征的信息增益或者gini指数有关。
4.1 条件熵
条件熵是用来解释信息增益而引入的概念,概率定义:随机变量X在给定条件下随机变量Y的条件熵,对定义描述为:X给定条件下Y的条件概率分布的熵对X的数学期望,在机器学习中为选定某个特征后的熵,公式如下:
4.2 信息增益
信息增益在决策树算法中是用来选择特征的指标,信息增益越大,则这个特征的选择性越好,在概率中定义为:待分类的集合的熵和选定某个特征的条件熵之差(这里只的是经验熵或经验条件熵,由于真正的熵并不知道,是根据样本计算出来的),公式如下:
4.3 小结
文字描述:
如果要算信息增益,因为信息增益=信息熵-条件熵,所以要算信息熵和条件熵。
4.4 例子
解决是否买电脑
信息熵:
条件熵:
信息增益:
5.算法分类
5.1 ID3算法
在ID3中,每次根据“最大信息熵增益”选取当前最佳的特征来分割数据,并按照该特征的所有取值来切分,也就是说如果一个特征有4种取值,数据将被切分4份,一旦按某特征切分后,该特征在之后的算法执行中,将不再起作用。
ID3采用的信息增益度量存在一个缺点,它一般会优先选择有较多属性值的Feature,因为属性值多的Feature会有相对较大的信息增益(信息增益反映的给定一个条件以后不确定性减少的程度,必然是分得越细的数据集确定性更高,也就是条件熵越小,信息增益越大)。
5.2 C4.5算法
为了避免ID3算法的不足,C4.5中是用信息增益比率(gain ratio)来作为选择分支的准则。信息增益比率通过引入一个被称作分裂信息(Split information)的项来惩罚取值较多的Feature。除此之外,C4.5还弥补了ID3中不能处理特征属性值连续的问题。但是,对连续属性值需要扫描排序,会使C4.5性能下降,但是同样的这个增益率对可取值数目较少的属性有所偏好。
分裂信息公式:
信息增益比率(gain ratio):
5.3 CART算法
CART使用了CCP代价复杂度剪枝算法,对C4.5的剪枝方法进行了优化。
针对C4.5的多叉树的问题,CART改成了二叉树。
CART可以分为CART分类树和CART回归树。
采用基尼系数来划分属性
基尼指数
基尼系数
因此在候选属性中选择基尼系数最小的属性作为最优划分属性。
基尼系数增益=基尼指数-基尼系数!!!!
6.决策树的组成部分
7.ID3算法具体案列
解决是否买电脑
elect.csv
7.1 导入相关包和数据
#调用sklearn里面的决策树
from sklearn import tree
import csv
#将字符串转化为数据
from sklearn.feature_extraction import DictVectorizer
from sklearn import preprocessing #预处理包
featureList=[]#存放特征属性值
labels=[]
#DictReader创建的是一个字典对象,遍历后不包含表头
reader=csv.DictReader(open('elect.csv'))#字典读取方式
print(reader)
运行结果:
小结:
使用DictReader字典读取elect.csv文件
7.2 将数据分为特征属性值和标签
for x in reader:
#把每一行数据写成一个字典的形式
print(x)
value={"age":x['age'],"income":x["income"],"sudent":x['student'],
"credit_rating":x["credit_rating"]}
featureList.append(value)#特征属性值
labelV=x['class_buys_computer']
labels.append(labelV)
print("featureList:",featureList)
print("labels:",labels)
运行结果:
小结:
1.把每一行数据写成一个字典的形式
2.通过字典形式,找到特征和特征值一一对应的关系,即特征为键,特征值为值。标签也是如此。
7.3 将特征值和标签二值化
#这个类是专门将字典列表的字符转化为数值(0 1)
vec=DictVectorizer()
featureDate=vec.fit_transform(featureList).toarray()
print(featureDate)
print("特征属性名:",vec.get_feature_names())
#类别二值化
lb=preprocessing.LabelBinarizer()
#LabelBinarizer二值化,字符串转化为数值
#LabelEncoder多指化
labels=lb.fit_transform(labels)
print(labels)
print(lb.classes_)
运行结果:
小结:
1.通过csv包里面的DictVectorizer,将特征值二值化。特征属性名按字母顺序排序。
2.通过preprocessing包里面的LabelBinarizer,将标签二值化。标签名按字母顺序排序。
7.3 建立和训练模型
#建立模型
computer=tree.DecisionTreeClassifier(criterion="entropy")#ID3算法需要写criterion="entropy",不写默认CART算法
#训练模型
computer.fit(featureDate,labels)
小结:
ID3算法需要写criterion=“entropy”,不写默认CART算法。
7.4 画出决策树
7.4.1 需要安装graphviz画图工具
详细安装步骤点击这里
import graphviz
dot_data=tree.export_graphviz(computer,#模型名称
out_file=None,#None表示没有输出文件
feature_names=vec.get_feature_names(),
#每一列的特征属性名,即 ['age=middle_age', 'age=senior', 'age=youth', 'credit_rating=excellent',
#'credit_rating=fair', 'income=high', 'income=low', 'income=medium', 'sudent=no', 'sudent=yes']
class_names=lb.classes_,#训练集标签,即['no' 'yes']
filled=True,#由颜色标识不纯度
rounded=True,#True表示框框是圆角
special_characters=False)
graph=graphviz.Source(dot_data)
graph
运行结果:
8.CART算法具体案列
8.1 数据表和问题
问题:是否拖欠贷款
数据表:
8.2 计算是否拖欠贷款的基尼指数
3/10表示拖欠贷款的概率,7/10表示没有拖欠贷款的概率。
8.3 计算是否有房的基尼指数、gini系数、gini系数增益
gini指数:
gini系数:
gini系数增益:
8.4 计算婚姻状况的gini指数、gini系数、gini系数增益
若按婚姻状况属性来划分,属性婚姻状况有三个可能的取值{married,single,divorced},分别计算划分后的的Gini系数增益。
分类有:
{married} | {single,divorced}
{single} | {married,divorced}
{divorced} | {single,married}
然后选择最大的gini系数增益和其他特征属性gini系数增益作比较。
当分组为{married} | {single,divorced}时,
gini指数:
左侧:1-(4/4)^2
右侧:1-(3/6)^2-(3/6) ^ 2
gini系数:
4/10*(1-(4/4)^2)+6/10*1-(3/6) ^ 2-(3/6) ^ 2
gini系数增益:
Δ{婚姻状况}=0.42−4/10×(1-(4/4) ^2)−6/10×[1−(3/6) ^2−(3/6) ^2]=0.12
当分组为{single} | {married,divorced}时,
gini指数:
左侧:1-(2/4)^2-(2/4) ^2
右侧:1-(5/6) ^2-(1/6) ^2
gini系数:
4/10* 1-(2/4)^2-(2/4) ^2 + 6/10*1-(5/6) ^2-(1/6) ^2
注:4/10表示 single/总人数
6/10 表示 married+divorceed /总人数
gini系数增益:
Δ{婚姻状况}=0.42−4/10×(1-[(2/4) ^ 2+ (2/4) ^ 2]−6/10×[1−(1/6 ^ )2−(5/6) ^2]=0.053
当分组为{divorced} | {single,married}时,
gini指数:
左侧:1-(1/2) ^2 -(1/2) ^2=0.5
右侧:1-(6/8) ^2-(2/8) ^2
gini系数:
2/10 * 0.5+8/10 * (1-(6/8) ^2-(2/8) ^2)
gini系数增益:
0.42-(2/10 * 0.5+8/10 * (1-(6/8) ^2-(2/8) ^2))=0.02
8.5 计算收入的gini指数、gini系数、gini系数增益
考虑年收入属性,我们发现它是一个连续的数值类型。
对于年收入属性为数值型属性,首先需要对数据按升序排序,然后从小到大依次用相邻值的中间值作为分隔将样本划分为两组。
当面对年收入为60和70这两个值时,我们算得其中间值为65。倘若以中间值65作为分割点。
gini指数:
左侧:1-(1/1)^2
右侧:1-(6/9)^ 2-(3/9) ^2
gini系数:
1/10 * (1-(1/1)^2)+ 9/10 * (1-(6/9)^ 2-(3/9) ^2)
gini系数增益:
0.42-(1/10 * (1-(1/1)^2)+ 9/10 * (1-(6/9)^ 2-(3/9) ^2))=0.02
当面对年收入为70和75这两个值时,我们算得其中间值为72.5。倘若以中间值72.5作为分割点。
gini系数增益:0.045
以此类推。
最后,三个属性划分根节点的增益最大的有两个:年收入属性和婚姻状况,他们的增益都为0.12。此时,选择其中任意一个属性都可以。
例如以收入为根节点
8.6计算以收入为根节点
也就是说进行决策的时候,只要收入高于97.5,我就直接认为他不拖欠贷款!
Gini(是否拖欠贷款)=1−(3/6) ^ 2−(3/6) ^ 2=0.5
是否有房gini增益:
Δ{是否有房}=0.5−6/6×[1−(3/6) ^2−(3/6) ^2]=0
婚姻状况划分:
当分组为{single} | {married,divorced}时:
∆{婚姻状况}=0.5−{3/6×[1−(1/3) ^2−(2/3) ^2 ]+3/6×[1−(1/3) ^2−(2/3) ^2 ]}=0.222
当分组为{divorced} | {single,married}时:
∆{婚姻状况}=0.5−{1/6×[1−(1/1) ^2 ]+5/6×[1−(2/5) ^2−(3/5) ^2 ]}=0.100
当分组为{married} | {single,divorced}时:
∆{婚姻状况}=0.5−{2/6×[1−(2/2) ^2 ]+4/6×[1−(1/4) ^2−(3/4) ^2 ]}=0.25
年收入划分:
Cart算法构造决策树时,以递归的方式构造二叉树。在根节点选取完之后,经过上面的计算,发现年收入(80为分割点)进行划分的时候,信息增益最大。
因此选择income<=80为结点继续向下划分
在以income<=80为结点进行划分时,我们发现得到的叶子节点已经非常纯,划分完毕。
8.6计算以婚姻状况为根节点
根节点的Gini系数为
对于是否有房属性的gini系数增益:
对于年收入属性的gini系数增益:
展示决策树