机器学习---决策树

转载:http://blog.csdn.net/lszdh/article/details/32700007?reload

应为要用到迭代决策树,就先学了决策树。主要参考《机器学习实战》。

一、决策树概念

决策树原理很简单,一个流程图就能明白。

图中构造了一个假想的邮件系统,通过检测域名地址和是否包含单词“曲棍球”来将邮件分类。
决策树也有分类树和回归树的分别。常见的分类数就是id3和c4.5,回归树有cart。
分类树就像上图进行分类,回归树在每个节点都会得一个预测值,以年龄为例,该预测值等于属于这个节点的所有人平均年龄。
接下来以ID3分类数为例,介绍决策树的构造。
关于决策树的原理和c++实现,可以看此博客决策树——从原理到实现,写的很不错。

二、决策树的构造

机器学习实战中有很详细的叙述,伪代码如下:
检测数据集中每个子项是否属于同一分类:
if so return 类标签;
else
       寻找划分数据集的最好特征
       划分数据集
       创建分支节点
            for 每个划分的子集
                  调用函数createBranch并增加返回结果到分支节点中
       return 分支节点

每一次分支都要找出划分数据集最好的特征,ID3中选取最好的特征是根据信息增益来选取的。

对于信息增益,先要明白信息熵的概念,首先熵是由热力学引述来的,在热力学中,熵表示能量分布的均匀程度,能量越混乱,熵越小,而能量总是由无序状态向有序状态转变,这就是熵增。无序状态的能量是能够做功的有效能量,熵增就意味着能量转化为不能做功的无效能量。(扯多了)
在信息论中,信息熵用来度量信息量,信息越有序,熵越小。计算公式如下

通过比较信息增益大小,找出信息增益最大的特征,即按照该特征划分的数据集的信息熵和原数据集的信息熵差值最大。
接下来就可以递归构造决策树了,结束条件:1、程序遍历完所有特征属性。2、每个分支下的所有实例都具有相同分类。
ID3每次划分消耗一个特征,这和C4.5、CART,是不一样的。若分支结束,叶子节点仍有分类不同的,以投票方式选择类别,即选取数目最多的那一类。

三、python实现

from math import log
import operator
#计算香农熵
def calcShannonEnt(dataSet):
    numEntries=len(dataSet)
    labelCounts={}
    for featVec in dataSet:#为所有分类创建字典
        currentLabel=featVec[-1]#the last
        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)
    return shannonEnt
#测试样例
def createDataSet():
    dataSet=[[1,1,'yes'],
             [1,1,'yes'],
             [1,0,'no'],
             [0,1,'no'],
             [0,1,'no']]
    labels=['no surfacin','flippers']
    return dataSet,labels
#划分数据集
def splitDataSet(dataSet,axis,value):
    retDataSet=[]
    for featVec in dataSet:
        if featVec[axis]==value:
            reducedFeatVec=featVec[:axis]#0~axis
            reducedFeatVec.extend(featVec[axis+1:])#注意两个函数区别
            retDataSet.append(reducedFeatVec)
    return retDataSet
#选择最好的特征
def chooseBestFeatureToSplit(dataSet):
    numFeatures=len(dataSet[0])-1#不包括类标签
    baseEntropy=calcShannonEnt(dataSet)
    bestInfoGain=0.0;bestFeature=-1
    for i in range(numFeatures):
        featList=[example[i] for example in dataSet]
        uniqueVals=set(featList)
        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
        if (infoGain>bestInfoGain):#找到最好的信息增益
            bestInfoGain = infoGain
            bestFeature = i
    return bestFeature
#分支结束若叶子节点分类不唯一,采取投票方式
def majorityCht(classList):
    classCount={}
    for vote in classList:
        if vote not in classCount.key():
            classCount[vote]=0
        classCount[vote]+=1
    sortedClassCount=sorted(classCount.iteritems(),
                            key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]
#构造树
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:# no more features
		return majorityCnt(classList)
	bestFeat = chooseBestFeatureToSplit(dataSet)#bestFeat is the index of best feature
	bestFeatLabel = labels[bestFeat]
	myTree = {bestFeatLabel:{}}
	del (labels[bestFeat])
	featValues = [example[bestFeat] for example in dataSet]
	uniqueFeatVals = set(featValues)
	for value in uniqueFeatVals:
		subLabels=labels[:]
		myTree[bestFeatLabel][value] = createTree(splitDataSet\
                                                          (dataSet,bestFeat,value),subLabels)
	return myTree

参考文献
[1]. 机器学习实战
[2]. 决策树之ID3算法

你可能感兴趣的:(机器学习,c/c++/python,python,机器学习)