暑假打算吃透一本书叫《机器学习》,你们也亲切的叫它西瓜书,看完决策树这部分想作作总结,虽然几年前对决策树的知识就有点印象,可是我发现如今又有了不少新的收获。php
1、基本流程html
2、划分选择node
3、剪枝处理python
4、连续与缺失值算法
5、多变量决策树dom
6、房价数据集的决策树算法python实现机器学习
决策树(decision tree)是一类常见的机器学习算法,它是基于树结构来进行决策的。函数
——“这是好瓜吗?”性能
——“它的颜色是青绿色的、根蒂是蜷缩的、敲声是......,因此结论是:这是个好瓜”。学习
以上,为了给好瓜坏瓜分类,咱们要回答不一样瓜的不一样属性,来帮助咱们判断。
图1. 这是一棵决策树
叶子结点就对应咱们的决策结果,其它的根节点和内部节点就对应于一个属性测试。决策树学习的目的就是为了产生一棵泛化能力强,即处理未见事例能力强的决策树。
决策树学习的关键就是如何选择最优划分属性,也就是找到上面图中为何要选择“色泽”属性做为根节点的理由,以及在接下来的划分中,为何要选择该划分属性的理由。
著名的ID3决策树学习算法就是以信息增益为准则来选择划分属性,下面这个图(不是西瓜的例子了,是我以前整理的,关于得病与否的例子)在14个样本中,yes=9个,no=5个,此时信息熵=-(9/14*log(9/14)+5/14*log(5/14))=0.940286,值得注意的是这里的对数是以2为底,下面随机选择一个属性好比年龄做为划分依据,分红<30,31~40,>40这三组,这三组中yes和no各占不一样的数目,计算方式跟上面同样,获得0.97095,0,0.81这三个信息熵,而后成权重后相加获得0.57856,这跟没划分以前的信息熵相差0.361726,这就是信息增益的量。
对其它的属性咱们也能够作一样的计算,把获得最大的信息增益的做为最优划分属性,这就是ID3算法选择划分属性的准则。
实际上,信息增益准则对可取值数目较多的属性有所偏好,为了减小这种偏好可能带来的不利影响,C4.5决策树算法不直接使用信息增益,而是使用增益率来选择最优划分属性。
这至关于在上面例子中的信息增益0.57856的基础上再除以-(5/14*log(5/14)+4/14*log(4/14)+5/14*log(5/14)),也就是对属性值d 的权重再求个熵,相除后做为最后的增益率。
须要注意的是,增益率准则对可取值数目较少对属性有所偏好。因此,C4.5算法并非直接选择增益率最大对候选划分属性,而是用了一个启发式:先从候选划分属性中找出信息增益高于平均水平的属性,再从中选择增益率最高的。
CART决策树算法使用基尼指数来选择划分属性,这个准则再也不用熵和增益来衡量数据集的纯度,而是用基尼值来度量。直观来讲这个值反映了从数据集中随机抽取两个样本,其类别标记不一致的几率。所以基尼值越小,则数据集的纯度越高。
剪枝是决策树算法对付“过拟合”的主要手段,经过主动去掉一些分支来下降过拟合的风险。根据泛化性能是否提高来判断和评估要不要留下这个分支。
那么,如何判断决策树的泛化性能是否提高呢?能够采用“留出法”(一种性能评估方法),即预留一部分数据用做“验证集”来进行性能评估。
是否应该进行这个划分?预剪枝要对划分前和划分后的泛化性能进行估计。划分后的验证集精度若是比划分前的验证集精度高,那么,就决定划分,不然,预剪枝策略禁止这个结点被划分。
优势:预剪枝使得决策树的不少分支都没有展开,这不只下降来过拟合的风险,还显著减小了决策树的训练时间开销和测试时间的开销。
缺点:预剪枝基于“贪心”的本质,禁止这些分支展开,给预剪枝决策树带来来欠拟合的风险。
后剪枝先从训练集上生成一棵完整的树,从最后一个分支来判断要不要剪枝。下面是根据训练集生成的一整棵树:
后剪枝策略一般比预剪枝策略保留更多的分支。通常状况下,后剪枝决策树的欠拟合风险很小,泛化能力每每优于预剪枝决策树,可是它的训练时间开销比未剪枝决策树和预剪枝决策树都要大的多。
以上的属性值都是离散的,现实中一般会遇到连续的属性值。这个时候,连续属性离散化技术就能够用上啦,C4.5决策树算法采用的是最简单的策略二分法来对连续值进行处理。给西瓜属性考虑密度的属性,首先把不一样样本的密度值按照从小到大排序,而后找到候选划分点,把每一个候选划分点的信息增益算出来,取max的值做为密度的信息增益。第二次max就是找到最优划分属性了。
这里须要注意的是,与离散属性值不一样,若当前结点划分属性为连续的,那么该属性还能够做为后面结点的划分属性。
若是样本中有缺失值,那么会产生如下两个问题:
(1)如何在属性值缺失的状况下计算属性的信息增益,从而进行划分属性的选择?
(2)给定划分属性,若是样本在该属性值上是缺失的,如何对这个样本进行划分?
针对(1)的处理很是简单,假设17个样本在“色泽”属性上只有14个是有值的,另外3个是缺失的,那么就以这14个样本的属性值计算信息增益,而后把这个值乘以14/17,至关于乘上一个权重,看成这所有17个样本的信息增益。而后进行后续的属性划分。
针对(2)的处理也很简单,原本每一个样本在结点中的权重都是1,当样本「8」在“纹理”上出现缺失值,那么在“纹理=清晰”、“纹理=模糊”、“纹理=稍糊”这三个分支中都会出现样本「8」,只是权重再也不是1,而是7/15,5/15,3/15(这三个权重的来源是这三个分支中各个样本的比例,不包括这个样本「8」)
以上的讲到的各类结点,都是单个的属性,有没有多是多种属性的线性组合呢?看看下面这个两个图:
在多变量决策树中,非叶子结点再也不是针对某个属性,而是对属性的线性组合进行测试,也就是说每个非叶子结点就是一个线性分类器。(很6666)
%matplotlib inline #jupyternotebook上须要这句 import matplotlib.pyplot as plt import pandas as pd from sklearn.datasets.california_housing import fetch_california_housing #sklearn中自带数据集 housing = fetch_california_housing() print(housing.DESCR) print(housing.data.shape) #查看数据集形状 from sklearn import tree dtr = tree.DecisionTreeRegressor(max_depth = 2) #这个函数很重要,里面的参数有兴趣的同窗能够查看sklearn官方文档,很强势 dtr.fit(housing.data[:, [6, 7]], housing.target) #要可视化显示 首先须要安装 graphviz http://www.graphviz.org/Download..php dot_data = \ tree.export_graphviz( dtr, out_file = None, feature_names = housing.feature_names[6:8], filled = True, impurity = False, rounded = True ) #pip install pydotplus import pydotplus graph = pydotplus.graph_from_dot_data(dot_data) graph.get_nodes()[7].set_fillcolor("#FFF2DD") from IPython.display import Image Image(graph.create_png())
输出以下:
#将数据划分红训练集和验证集,查看准确率 from sklearn.model_selection import train_test_split data_train, data_test, target_train, target_test = \ train_test_split(housing.data, housing.target, test_size = 0.1, random_state = 42) dtr = tree.DecisionTreeRegressor(random_state = 42) dtr.fit(data_train, target_train) dtr.score(data_test, target_test)
输出以下:
0.637318351331017