1.基本流程
决策树:
决策树学习的目的是为了产生一棵处理未见示例能力强的决策树;
决策树学习基本算法:决策树生成是一个递归的过程,有三种情况会导致递归返回:
1.当前结点包含的样本全都属于同一类别,此时不需要划分;
2.当前结点属性集为空,或者所有样本属性取值相同,此时把当前结点标记为叶结点,类别设定为样本最多的类别(后验分布);
3.当前结点样本集为空,此时把当前结点标记为叶结点,类别设定为父结点样本最多的类别(先验分布)。
2.划分选择
信息熵:度量样本纯度的一种指标。
信息熵值越小,则D纯度越高,即熵越大,变量不确定性越大;
信息增益:;
一般而言,信息增益越大,用属性a进行划分所获得的信息纯度提升越大;
ID3决策树学习算法以信息增益为准则选择划分属性:
1.算出根结点包含D中所有样例的信息熵;
2.选择属性集合,根据属性值正例、反例所占比例,算出信息熵;
3.利用公式算出当前属性的信息增益;
4.对每个属性重复以上3步,并算出对应信息增益;
5.选择最大的作为划分属性,并将其作为新的D’。
增益率:
基尼系数:
基尼系数越小数据集D纯度越高。
3.剪枝处理
目的:处理过拟合;
预剪枝:在决策树生成过程中,对每个结点在规划前先进行估计,若当前节点的划分不能带来决策树泛化性能的提升,则停止划分,并将当前结点标记为叶结点;
优点:降低过拟合,减少时间;
缺点:会出现欠拟合。
后剪枝:先生成一课完整的决策树,再自底向上对非叶结点考察,如果将结点对应子树替换为叶结点能提升泛化性能,则替换为叶结点;
优点:欠拟合风险小,泛化性能优;缺点:时间消耗大。
4.连续与缺失值
连续值:将属性取值从小到大排序,用t对样本集进行划分,不大于t的样本为子集D-,大于t的样本为子集D+,t由相邻两属性值求平均值得到,则t可得到属性值个数减1个;
缺失值:先找到属性对应属性值缺失的样例,并算出其信息熵,在算出对应属性值的信息熵,然后计算出信息增益,将得到的信息增益乘以无缺失样本所占比例,则算出样本集属性的信息增益(C4.5算法)。多变量决策树即在空间坐标中建立合适的线性分类器。
5.决策树与KNN比较
KNN:无法给出数据的内在含义;
决策树:目的为了理解数据中所蕴含的知识信息,且形式容易理解。常用与专家系统。
决策树优点:计算复杂度不高,输出易于理解,对中间值缺失不敏感,可处理不相关特征数据;
决策树缺点:可能会产生过度匹配问题。
适用类型:数据型、标称型。
6.数据划分
划分数据集的原则:将无序的数据变得有序。信息论是量化处理信息的分支科学,组织杂乱无章数据的一种方法就是使用信息论度量信息。随着划分过程的进行,我们希望决策树的分支节点所包含的样本尽可能属于同一类别,即节点的纯度越高。信息熵是度量样本集合纯度的一种指标。
如果待分类的事务可能划分在多个分类之中,则符号的信息定义为
其中为选择该分类的概率,则信息熵的定义如下:
其中是分类的数目,信息熵
的值越小,则样本集合的纯度越高。
Shannon熵计算python代码如下
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 = labelCounts[key] / numEntries
shannonEnt -= prob * np.log2(prob)
return shannonEnt
根据信息熵可得到属性 对样本集合
进行划分所得的信息增益
信息增益越大,则用属性进行划分所得纯度提升越大。因此在选择划分属性时,选择信息增益最大的属性进行划分,ID3决策树便是以信息增益为准则选择划分属性。
计算信息增益,并返回最优特征代码如下:
def chooseBestFeatureToSplit(dataset):
numFeature = len(dataset[0]) - 1
baseEntropy = calcShannonEnt(dataset)
baseInfoGain = 0.0
bestFeature = -1
for i in range(numFeature):
featureList = [example[i] for example in dataset]
uniqueFeature = set(featureList)
newEntropy = 0.0
for value in uniqueFeature:
subDataset = splitDataSet(dataset, i, value)
prob = len(subDataset) / len(dataset)
newEntropy += prob*calcShannonEnt(subDataset)
infoGain = baseEntropy - newEntropy
if(infoGain > baseInfoGain):
baseEntropy = infoGain
bestFeature = i
return bestFeature
7.构建决策树
采用递归的原则处理数据集构建决策树,递归结束的条件是:程序遍历完所有划分数据集的属性,或者每个分支下的所有实例都具有相同的分类。如果所有实例具有相同的分类,则得到一个叶子节点或者终止块。任何到达叶子结点的数据必然属于叶子结点的分类。如果已经处理了所有属性,但是类标签依然不是唯一的,此时通常采用多数表决的方法确定子节点分类。多数表决代码如下:
def majorityCnt(classList):
classCount = {}
for vote in classList:
if vote not in classList:
classCount[vote] = 0
classList[vote] += 1
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount
决策树构建代码如下:
def createTree(dataset, labels):
classList = [example[-1] for example in dataset]
if classList.count(classList[0]) == len(classList):
return classList[0]
if len(dataset[0]) == 1:
return majorityCnt(classList)
bestFeat = chooseBestFeatureToSplit(dataset)
bestFeatureLabel = labels[bestFeat]
myTree = {bestFeatureLabel: {}}
del(labels[bestFeat])
featValues = [example[bestFeat] for example in dataset]
uniqueVals = set(featValues)
for value in uniqueVals:
subLabels = labels[:]
myTree[bestFeatureLabel] [value] = createTree(splitDataSet(dataset, bestFeat, value), subLabels)
return myTree
8.总结
决策树主要介绍决策树学习方法,其思想总体来说不难,把书中提到的算法思路、计算过程整理清楚,便能理解。
参考文献
[1] Peter Harringtom. 机器学习实战[M].北京, 人民邮电出版社, 2013.
[2] 周志华. 机器学习[M].北京,清华大学出版社,2016.