文章目录
决策树
决策树(Decision Tree)是在已知各种情况发生概率的基础上,通过构成决策树来求取净现值的期望值大于等于零的概率,评价项目风险,判断其可行性的决策分析方法,是直观运用概率分析的一种图解法。决策树是一种树形结构,其中每个内部节点表示一个属性上的测试,每个分支代表一个测试输出,每个叶节点代表一种类别。
机器学习中,决策树是一个预测模型;他代表的是对象属性与对象值之间的一种映射关系。树中每个节点表示某个对象,而每个分叉路径则代表的某个可能的属性值,而每个叶结点则对应从根节点到该叶节点所经历的路径所表示的对象的值。
决策树的生成过程主要分为以下几部分:
- 特征选择:特征选择是指从训练数据中众多的特征中选择一个特征作为当前节点的分裂标准,如何选择特征有着很多不同量化评估标准,从而衍生出不同的决策树算法。
- 决策树生成: 根据选择的特征评估标准,从上至下递归地生成子节点,直到数据集不可分则决策树停止生长。 树结构来说,递归结构是最容易理解的方式。
- 剪枝:剪枝是决策树停止分支的方法之一,剪枝技术有预剪枝和后剪枝两种。
决策树示意图:
决策树的构造
决策树的优缺点以及适用数据类型:
- 优点:计算复杂度不高,输出结果易于理解,对中间值的确实不敏感,可以处理不相关特征数据。
- 缺点:可能会产生过度匹配问题。
- 适用数据类型:数值型和标称型。
构造决策树时首先要解决当前数据集上哪个特征在划分数据分类时起决定性作用的问题,为了找到决定性特征,划分出最好的结果,我们需要评估每个特征,在完成测试之后,原始数据集就划分为了几个数据子集,这些数据子集会分布在第一个决策点的所有分支上,若某个分支下的数据属于同一类型,则无需进一步对数据集进行分割。若数据子集内的数据不属于同一类型,则需要重复划分数据子集的过程。划分数据子集的算法和划分原始数据集的方法相同,直到所有具有相同类型的数据均在一个数据子集内。
创建分支的伪代码函数createBranch如下所示:
检测数据集中的每个子项是否属于同一分类:
If so return 类标签
Else
寻找划分数据集的最好特征
划分数据集
创建分支节点
for每个划分的子集
调用函数createBranch并增加返回结果到分支节点中
return 分支节点
决策树的一般流程
- 收集数据:可以使用任何方法
- 准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化
- 分析数据:可以使用任何方法,构造树完成之后,我们应该检查图形是否符合预期
- 训练算法:构造树的数据结构
- 测试算法:使用经验树计算错误率
- 使用算法:此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义
信息增益
划分数据集的大原则:将无序的数据变得更加有序。
组织杂乱无章数据的一种方法就是使用信息论度量信息,信息论是量化处理信息的分支科学。在划分数据集之前之后信息发生的变化称为信息增益,知道如何计算信息增益,我们就可以计算每个特征值划分数据集获得的信息增益,获得信息增益最高的特征就是最好的选择。
集合信息的度量方式称为香农熵或简称为熵。
熵定义为信息的期望值,若待分类的事务可能划分在多个分类当中,则符号 x i x_i xi的信息定义为: l ( x i ) = − l o g 2 p ( x i ) l(x_i)=-log_2p(x_i) l(xi)=−log2p(xi),其中 p ( x i ) p(x_i) p(xi)是选择该分类的概率。为了计算熵,我们需要计算所有类别所有可能值包含的信息期望值,通过下面公式得到: H = − Σ i = 1 n p ( x i ) l o g 2 p ( x i ) H=-Σ^n_{i=1}p(x_i)log_2p(x_i) H=−Σi=1np(xi)log2p(xi),其中n是分类的数目。
计算给定数据集的香农熵的代码部分:
from math import log
import operator
def calcshannonEnt(dataSet): #计算给定数据集的香农熵
nuMEntries = len(dataSet) #记录数据集行数
labelCounts = {
} #记录每个标签出现次数的字典
for featVec in dataSet: #为所有可能分类创建字典
currentLabel = featVec[-1] #提取标签信息
if currentLabel not in labelCounts.keys(): #若标签未放入统计次数的字典,进行添加
labelCounts[currentLabel] = 0
labelCounts[currentLabel] += 1
shannonEnt = 0.0 #经验熵
for key in labelCounts:
prob = float(labelCounts[key])/nuMEntries #选择该分类的概率
shannonEnt -= prob * log(prob,2) #,以2为底求对数,计算香农熵
return shannonEnt
在这部分计算给定数据集的香农熵的代码当中,首先,我们要计算出数据集中实例的总数,这里我们显示地声明一个变量保存实例总数。然后再创建一个数据字典,它的键值为最后一列的数值,若当前键值不存在,则扩展字典并将当前键值加入字典。这里每个键值都记录了当前类别出现的次数,最后再使用所有类标签的发生概率计算类别出现的概率。我们将用这个概率计算香农熵,统计所有类标签发生的次数。
利用createDataSet函数得到简单鱼鉴定数据集:
def createDataset():
dataSet = [[1,1,'yes'],[1,1,'yes'],[1,0,'no'],[0,1,'no'],[0,1,'no']]
labels = ['no surfacing','flippers']
return dataSet,labels
计算香农熵运行结果:
熵越高,混合数据越多,我们可以在数据集中添加更多分类,观察熵如何变化,我们增加第三个名为maybe的分类,测试熵的变化:
myData[0][-1]='maybe'
print(myData)
print(calcshannonEnt(myData))
测试结果:
另一个度量集合无需程度的方法是基尼不纯度,简单地说就是从一个数据集中随机选取子项,度量其被错误分类到其他分组里的概率。以下为计算基尼不纯度的公式 I G ( f ) = ∑ i = 1 m f i ( 1 − f i ) = ∑ i = 1 m f i − ∑ i = 1 m f 2 i = 1 − ∑ i = 1 m f 2 i IG(f)=∑i=1mfi(1−fi)=∑i=1mfi−∑i=1mf2i=1−∑i=1mf2i IG(f)=∑i=1mfi(1−fi)=