首页 > 代码库 > Decision trees

Decision trees

决策树有着非常广泛的应用,可以用于分类和回归问题。以下针对分类问题对决策树进行分析。

分类情况下,可以处理离散(if-then)的特征空间,也可以是连续(阈值化的if-than)的特征空间。

决策树由结点和边构成,其中结点分内结点(属性,特征)和外结点(类别)。边上代表着判别的规则,即if-then规则——Splitting datasets one feature at a time.

思想,决策树的每个分枝根据边代表的属性利用if-then规则将特征分类,直至获得分类的结果。

决策树的训练属于监督学习,训练生成的决策树作为分类器用于新样本的分类决策。因为决策树的生成可能会产生过拟合,需要提前停止树的生成或剪枝来解决。

决策树的三个主要问题,特征选择,生成,剪枝。其中特征的选择的概念,即熵、信息增益/比的概念很重要。

决策树的主要流行方法有,C3,C4.5,CART。

?

决策树的优点:

一、 决策树易于理解和解释.人们在通过解释后都有能力去理解决策树所表达的意义。

二、 对于决策树,数据的准备往往是简单或者是不必要的.其他的技术往往要求先把数据一般化,比如去掉多余的或者空白的属性。

三、 能够同时处理数据型和常规型属性。其他的技术往往要求数据属性的单一。

四、 决策树是一个白盒模型。如果给定一个观察的模型,那么根据所产生的决策树很容易推出相应的逻辑表达式。

五、 易于通过静态测试来对模型进行评测。表示有可能测量该模型的可信度。

六、 在相对短的时间内能够对大型数据源做出可行且效果良好的结果。

七、 可以对有许多属性的数据集构造决策树。

八、 决策树可很好地扩展到大型数据库中,同时它的大小独立于数据库的大小。

?

决策树的缺点:

一、 对于那些各类别样本数量不一致的数据,在决策树当中,信息增益的结果偏向于那些具有更多数值的特征。

二、 决策树处理缺失数据时的困难。

三、 过度拟合问题的出现。

四、 忽略数据集中属性之间的相关性。

?

先举个简单例子,来分析基本要素和概念

下图是weka软件安装目录下自带的测试数据例子。

这个数据文件内容表示的意思是:在不同的天气情况下,是否去玩。

一共有14个实例(天数),五种属性(天气外观,温度,湿度,有无风,是否玩),前四种是特征,最后一种是分类结果。这个例子的数值域都是离散的。

就以这个例子讲决策树的基本概念。

以下是weka中用决策树J48 (C4.5)算法生成的例子。

根据这个图我们来分析下决策树的基本要素。

决策树结构,结点和边构成的决策树,其中结点分内结点(特征)和外结点(类别)

边上代表着判别的规则,即if-then规则。I.E. Splitting datasets one feature at a time

发现没有少用了一个特征"温度",因为这个特征最不重要,而且加上它有可能并不能提高整体性能,即可能产生过拟合。

为了避免过拟合,办法有提前终止树的生成,和剪枝。

综上,决策树的三个主要问题,特征选择,生成,剪枝。具体细节请看《统计学习理论》李航。以下只叙述大致框架和要点

if-then规则

一共有14个实例,每个实例可以建立一个if-then规则来确定分类,如第1个实例:if(天气晴,温度高,湿度大,无风),then(不玩)。那么根据训练数据就可建立14种规则,但是一共有4!种情况,对新的实例并不能很好的分类,因此并不能这样简单的建立。

那该如何建立呢,根据机器学习监督学习分类的基本目标,要建立一套规则能很好的拟合训练实例情况,又能够有很好的泛化能力,即预测未知实例情况。所以在if-then规则中,要选取最好的特征来进行分类。

特征选择

那什么是较好的特征呢?想想看,如果取极端的情况,要求这个例子中四个特征中只选择一个特征来进行分类,你会选择哪个作为if的判别条件呢?也就是选定一个特征后,其他特征先不看,根据这个特征从训练实例中来建立if-then规则进行分类,比如选第十个特征"风",8次无风情况下其中2次不去,6次有风情况下其中3次不去。那么根据概率大的情况作为判定结果。规则是:if(有风),then(不去或者去,因为概率一样);if(无风),then(去)。根据这样的规则就能建立一个树结构模型。还能算出训练的错误率为(2+3)/14。然后看看分别单独选不同情况下的错误率哪个最小。显然为了使得训练误差要小,就选择那样的特征——错误率哪个最小代表的特征。这种很好理解的规则,就是使分类误差率最小。

根据这样的方法选好的以一个if-then规则中使用的特征,然后根据情况划分成几块情况,每块又可以重复上述过程,程序中表现为迭代。每次选择特征使用的方法就是启发式算法,得到次优解。因为建立一套整体规则是NP问题,并且生成这一套整体规则可以用树来表示,称之为决策树。

那还有哪些启发式算法可以作为选特征的依据吗?看下图

是的,还有熵、基尼指数可以作为选取特征的衡量标准来使用。下面就只说关于熵的。

信息增益

一句话:熵也大,随机变量的不确定性也越大。

因此选择信息增益大的特征,来作为if-then规则的判别条件,这就是决策树ID3的核心思想。

而改进的C4.5算法中,使用的是如下信息增益比来选取特征。

以下例子和程序来自《机器学习实战》第三章,以ID3算法为例,程序不全,附件有全程序是课本的代码。

程序:计算熵

def calcShannonEnt(dataSet):

numEntries = len(dataSet)

labelCounts = {}

for featVec in dataSet: #the the number of unique elements and their occurance

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) #log base 2

return shannonEnt

?

程序:根据信息增益比来选取特征

def chooseBestFeatureToSplit(dataSet):

numFeatures = len(dataSet[0]) - 1 #the last column is used for the labels

baseEntropy = calcShannonEnt(dataSet)

bestInfoGain = 0.0; bestFeature = -1

for i in range(numFeatures): #iterate over all the features

featList = [example[i] for example in dataSet]#create a list of all the examples of this feature

uniqueVals = set(featList) #get a set of unique values

newEntropy = 0.0

for value in uniqueVals:

subDataSet = splitDataSet(dataSet, i, value)

prob = len(subDataSet)/float(len(dataSet))

newEntropy += prob * calcShannonEnt(subDataSet)

infoGain = baseEntropy - newEntropy #calculate the info gain; ie reduction in entropy

if (infoGain > bestInfoGain): #compare this to the best gain so far

bestInfoGain = infoGain #if better than current best, set to best

bestFeature = i

return bestFeature #returns an integer

?

树的生成

内结点(特征)中选好特征来做为if-then规则的判别条件,根据不同情况在每条边上划分结点,检测结点是否满足成为外结点(类别)的情况,满足就把类别多的结果作为外结点(类别)表示的类。不满足就就是内结点(特征),就重复上一句话的做法(递推)。

程序:生成树

def createTree(dataSet,labels):

classList = [example[-1] for example in dataSet]

if classList.count(classList[0]) == len(classList):

return classList[0]#stop splitting when all of the classes are equal

if len(dataSet[0]) == 1: #stop splitting when there are no more features in dataSet

return majorityCnt(classList)

bestFeat = chooseBestFeatureToSplit(dataSet)

bestFeatLabel = labels[bestFeat]

myTree = {bestFeatLabel:{}}

del(labels[bestFeat])

featValues = [example[bestFeat] for example in dataSet]

uniqueVals = set(featValues)

for value in uniqueVals:

subLabels = labels[:] #copy all of labels, so trees don‘t mess up existing labels

myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels)

return myTree

?

树的剪枝

像CD3算法这样递归的产生决策树,因为规则用的过多,过细,树会建的很大,可能会较好的拟合训练数据,但容易产生过拟合,不能很好的预测未知数据的分类结果。

为了避免过拟合,办法有提前终止树的生成,和剪枝。

避免过拟合的方法:

?

测试数据

构建好的决策树,可以保存好,用于测试集进行分类。

程序:使用构建好的决策树来对测试集进行分类

def classify(inputTree,featLabels,testVec):

firstStr = inputTree.keys()[0]

secondDict = inputTree[firstStr]

featIndex = featLabels.index(firstStr)

key = testVec[featIndex]

valueOfFeat = secondDict[key]

if isinstance(valueOfFeat, dict):

classLabel = classify(valueOfFeat, featLabels, testVec)

else: classLabel = valueOfFeat

return classLabel

?

这是树的存储结构

{‘tearRate‘: {‘reduced‘: ‘no lenses‘, ‘normal‘: {‘astigmatic‘: {‘yes‘: {‘prescript‘: {‘hyper‘: {‘age‘: {‘pre‘: ‘no lenses‘, ‘presbyopic‘: ‘no lenses‘, ‘young‘: ‘hard‘}}, ‘myope‘: ‘hard‘}}, ‘no‘: {‘age‘: {‘pre‘: ‘soft‘, ‘presbyopic‘: {‘prescript‘: {‘hyper‘: ‘soft‘, ‘myope‘: ‘no lenses‘}}, ‘young‘: ‘soft‘}}}}}}

决策树的结构

新的测试数据就可以用以上规则来划分类型了。

?

参考:

《统计学习理论》,李航

《机器学习实战》

pedro domingos‘s machine learning course at coursera

各种分类算法比较from http://bbs.pinggu.org/thread-2604496-1-1.html

Decision trees