您的位置:首页 > 其它

机器学习实战--chapter3 决策树

2017-03-22 00:56 323 查看

1 大话决策树

决策树就是一颗树,每个父节点就是基于特征的一种表示,子节点就是对数据集的再次细分,通过层层细分,得到数据集中每个样本的类别。主要涉及到每层树根的特征的选取策略与递归结束时的处理。当然这里防止层数太多,可以人为限制层数。

2 决策树的一般流程

收集数据

准备数据:标称型数据。

分析数据:

训练算法:构造树的数据结构。

测试算法

应用

注:标称型数据:取值有限,适合分类;数值型数据:无限,适合回归。

3 信息熵

百度百科

博客1

博客2

3.1 不确定性

概率表示某事件发生的可能性,概率越大,也就说明不确定性越小;反之,概率越小,不确定性越大。所以,不确定性可以通过概率来衡量。怎么理解呢?比如综合天气的一些数据,天气预报得出明天90%下雨,那么明天基本会下雨,这事也就基本确定了,从而不确定性就非常小。

不确定性函数

l(xi)=−log2p(xI)

3.2 信息熵

熵形容系统的混乱程度,定义为信息的期望值,信息就是上面描述的不确定性。

H=−∑i=1np(xi)log2p(x2)

3.2 信息增益

信息增益就是系统原先的熵减去某事件发生后剩余的熵,就是该事件发生后,系统不确定性降低了多少,降低越大,说明不确定消除越多,获得的信息量越大。

4 决策树算法

4.1 递归构建

结束条件:

1. 所有特征已经过滤完,此时如果剩余样本还是类别不清楚,则选择其中的众数作为该子集的类别;

2. 剩余样本已经属于某一类,即已确定。

4.2 每个树的树根的选取

采用第三节的方法,每选的一个特征,使得系统的信息增益最大化。

5 代码

5.1 计算熵

#创建数据集,列表的形式,yes, no是tag.
def createDataSet():
dataSet = [[1, 1, 'yes'],
[1, 1, 'yes'],
[1, 0, 'no'],
[0, 1, 'no'],
[0, 1, 'no']]
labels = ['no surfacing','flippers']  #起显示作用,对算法没作用
#change to discrete values
return dataSet, labels

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) #根据熵公式计算,对信息的加权平均,即信息的均值。
return shannonEnt


5.2 选择特征

#根据特征筛选数据集,作为一个分支
def splitDataSet(dataSet, axis, value):
retDataSet = []
for featVec in dataSet:
if featVec[axis] == value:
reducedFeatVec = featVec[:axis]     #slice操作,提取特征axis==value的样本,同时删去该特征,举例样本exp1 = [1, 2, 'yes'], 则exp1[0]特征为1的,组装一个新的列表,即[2, 'yes']
reducedFeatVec.extend(featVec[axis+1:])
retDataSet.append(reducedFeatVec)
return retDataSet

#特征选取的依据,信息增益最大
def chooseBestFeatureToSplit(dataSet): #选择某个特征使得的信息增益最大
numFeatures = len(dataSet[0]) - 1      #取得特征数,数据集最后一列是tag.
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                      #returns an integer


5.3 递归构建树

结束条件:

1. 所有特征已经过滤完,此时如果剩余样本还是类别不清楚,则选择其中的众数作为该子集的类别;

2. 剩余样本已经属于某一类,即已确定。

def majorityCnt(classList): #条件一,返回剩余数据集众数的tag.
classCount={}
for vote in classList:
if vote not in classCount.keys(): 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] #数据集tag列表
if classList.count(classList[0]) == len(classList):
return classList[0]       #满足条件二
if len(dataSet[0]) == 1:      #满足条件一,特征用完啦
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[:]       #列表深度拷贝,不是对原先的引用
myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels)
return myTree
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  机器学习 决策树