决策树(一)

#决策树
1.定义
分类决策树模型是一种描述对实例进行分类的树形结构。决策树由结点和有向边组成。
结点有两种类型:内部节点和叶节点,内部节点表示一个特征或属性,叶节点表示一个类。
分类的时候,从根节点开始,对实例的某一个特征进行测试,根据测试结果,将实例分配到其子结点;
此时,每一个子结点对应着该特征的一个取值。如此递归向下移动,直至达到叶结点,最后将实例分配到叶结点的类中。
#优点:计算复杂度不高,输出结果易于理解,对中间值缺失不敏感,可以处理不相关特征数据
#缺点:可能会产生过度匹配问题
#适用数据类型:数值型和标称型
'''
createBranch()函数伪代码
检测数据集中的每个子项是否属于同一类分类:
If so return 类标签:
Else
寻找划分数据集的最好特征
划分数据集
创建分支节点
for 每个划分的子类
调用函数createBranch并增加返回结果到分支节点中
return 分支节点

决策树一般流程:
收集-准备-分析数据-训练-测试-使用算法

信息增益:在划分数据集之前之后信息发生的变化
获得信息增益最高的特征就是最好的选择
香农熵(熵):集合信息的度量方式
熵定义为信息的期望值
'''
 1 #计算给定数据集的香农熵
 2 from math import log
 3 from matplotlib.font_manager import FontProperties
 4 import matplotlib.pyplot as plt
 5 import operator
 6 from importlib import reload
 7 def calcShannonEnt(dataSet):
 8     numEntries = len(dataSet)
 9     labelCounts = {}    #创建一个数据字典,它的键值是最后一列的数值
10     for featVec in dataSet:
11         currentLabel = featVec[-1]
12         if currentLabel not in labelCounts.keys():
13             labelCounts[currentLabel] = 0
14             labelCounts[currentLabel] += 1
15         shannonEnt = 0.0
16         for key in labelCounts: #使用所有类标签的发生频率计算类别出现的概率
17             prob = float(labelCounts[key])/numEntries   #利用这个概率计算香农熵
18             shannonEnt -= prob * log(prob,2)
19         return shannonEnt
20 def createDataSet():
21     dataSet = [[1,1,'yes'],[1,1,'yes'],[1,0,'no'],[0,1,'no'],[0,1,'no']]
22     labels = ['no surfacing','flippers']
23     return dataSet, labels
24 
25 #划分数据集
26 def splitDataSet(dataSet, axis, value): #待划分数据集,划分数据集的特征,特征的返回值
27     retDataSet = [] #创建新的列表对象
28     for featVec in dataSet:
29         if featVec[axis] == value:  #将符合特征的数据抽取出来
30             reducedFeatVec = featVec[:axis]
31             reducedFeatVec.extend(featVec[axis+1:])
32             retDataSet.append(reducedFeatVec)
33     return retDataSet
34 
35 def chooseBestFeatureToSplitByID3(dataSet):
36     '''
37     选择最好的数据集划分方式
38     param dataSet:数据集
39     return: 划分结果
40     '''
41     numFeatures = len(dataSet[0]) - 1  # 最后一列yes分类标签,不属于特征向量
42     baseEntropy = calcShannonEnt(dataSet)
43     bestInfoGain = 0.0
44     bestFeature = -1
45     for i in range(numFeatures):  # 遍历所有特征
46         featList = [example[i] for example in dataSet]
47         uniqueVals = set(featList)
48         newEntropy = 0.0
49         for value in uniqueVals:    #创建唯一的分类标签列表
50             subDataSet = splitDataSet(dataSet, i, value)
51             prob = len(subDataSet)/float(len(dataSet))
52             newEntropy += prob * calcShannonEnt(subDataSet)
53         infoGain = baseEntropy - newEntropy     # 计算信息增益
54         if (infoGain > bestInfoGain):  # 选择最大的信息增益
55             bestInfoGain = infoGain
56             bestFeature = i
57     return bestFeature  # 返回最优特征对应的维度
58 
59 #递归构建决策树
60 def majorityCnt(classList):
61 #采用多数表决的方法决定叶结点的分类,param: 所有的类标签列表,return: 出现次数最多的类
62     classCount = {}
63     for vote in classList:                  # 统计所有类标签的频数
64         if vote not in classCount.keys():
65             classCount[vote] = 0
66         classCount[vote] += 1       #利用operation操作键值排序字典,并返回出现次数最多的分类名称
67     sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True) # 排序
68     return sortedClassCount[0][0]
69 
70 #创建数的函数代码
71 def createTree(dataSet,labels):
72     #param: dataSet:训练数据集
73     #return: labels:所有的类标签
74     classList = [example[-1] for example in dataSet]
75     if classList.count(classList[0]) == len(classList):
76         return classList[0]             # 第一个递归结束条件:所有的类标签完全相同
77     if len(dataSet[0]) == 1:
78         return majorityCnt(classList)   # 第二个递归结束条件:用完了所有特征
79     bestFeat = chooseBestFeatureToSplitByID3(dataSet)   # 最优划分特征
80     bestFeatLabel = labels[bestFeat]
81     myTree = {bestFeatLabel:{}}         # 使用字典类型储存树的信息
82     del(labels[bestFeat])
83     featValues = [example[bestFeat] for example in dataSet]
84     uniqueVals = set(featValues)
85     for value in uniqueVals:
86         subLabels = labels[:]       # 复制所有类标签,保证每次递归调用时不改变原始列表的内容
87         myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels)
88     return myTree


 
原文地址:https://www.cnblogs.com/fd-682012/p/11584859.html