直接给代码
1 # -*- coding: UTF-8 -*- 2 from math import log 3 import operator 4 5 """ 6 函数说明:计算给定数据集的经验熵(香农熵) 7 8 Parameters: 9 dataSet - 数据集 10 Returns: 11 shannonEnt - 经验熵(香农熵) 12 Author: 13 Jack Cui 14 Blog: 15 http://blog.csdn.net/c406495762 16 Modify: 17 2017-07-24 18 """ 19 def calcShannonEnt(dataSet): 20 numEntires = len(dataSet) #返回数据集的行数 21 labelCounts = {} #保存每个标签(Label)出现次数的字典 22 for featVec in dataSet: #对每组特征向量进行统计 23 currentLabel = featVec[-1] #提取标签(Label)信息 24 if currentLabel not in labelCounts.keys(): #如果标签(Label)没有放入统计次数的字典,添加进去 25 labelCounts[currentLabel] = 0 26 labelCounts[currentLabel] += 1 #Label计数 27 shannonEnt = 0.0 #经验熵(香农熵) 28 for key in labelCounts: #计算香农熵 29 prob = float(labelCounts[key]) / numEntires #选择该标签(Label)的概率 30 shannonEnt -= prob * log(prob, 2) #利用公式计算 31 return shannonEnt #返回经验熵(香农熵) 32 33 """ 34 函数说明:创建测试数据集 35 36 Parameters: 37 无 38 Returns: 39 dataSet - 数据集 40 labels - 特征标签 41 Author: 42 Jack Cui 43 Blog: 44 http://blog.csdn.net/c406495762 45 Modify: 46 2017-07-20 47 """ 48 def createDataSet(): 49 dataSet = [[0, 0, 0, 0, ‘no‘], #数据集 50 [0, 0, 0, 1, ‘no‘], 51 [0, 1, 0, 1, ‘yes‘], 52 [0, 1, 1, 0, ‘yes‘], 53 [0, 0, 0, 0, ‘no‘], 54 [1, 0, 0, 0, ‘no‘], 55 [1, 0, 0, 1, ‘no‘], 56 [1, 1, 1, 1, ‘yes‘], 57 [1, 0, 1, 2, ‘yes‘], 58 [1, 0, 1, 2, ‘yes‘], 59 [2, 0, 1, 2, ‘yes‘], 60 [2, 0, 1, 1, ‘yes‘], 61 [2, 1, 0, 1, ‘yes‘], 62 [2, 1, 0, 2, ‘yes‘], 63 [2, 0, 0, 0, ‘no‘]] 64 labels = [‘年龄‘, ‘有工作‘, ‘有自己的房子‘, ‘信贷情况‘] #特征标签 65 return dataSet, labels #返回数据集和分类属性 66 67 """ 68 函数说明:按照给定特征划分数据集 69 70 Parameters: 71 dataSet - 待划分的数据集 72 axis - 划分数据集的特征 73 value - 需要返回的特征的值 74 Returns: 75 无 76 Author: 77 Jack Cui 78 Blog: 79 http://blog.csdn.net/c406495762 80 Modify: 81 2017-07-24 82 """ 83 def splitDataSet(dataSet, axis, value): 84 retDataSet = [] #创建返回的数据集列表 85 for featVec in dataSet: #遍历数据集 86 if featVec[axis] == value: 87 reducedFeatVec = featVec[:axis] #去掉axis特征 88 reducedFeatVec.extend(featVec[axis+1:]) #将符合条件的添加到返回的数据集 89 retDataSet.append(reducedFeatVec) 90 return retDataSet #返回划分后的数据集 91 92 """ 93 函数说明:选择最优特征 94 95 Parameters: 96 dataSet - 数据集 97 Returns: 98 bestFeature - 信息增益最大的(最优)特征的索引值 99 Author: 100 Jack Cui 101 Blog: 102 http://blog.csdn.net/c406495762 103 Modify: 104 2017-07-20 105 """ 106 def chooseBestFeatureToSplit(dataSet): 107 numFeatures = len(dataSet[0]) - 1 #特征数量 108 baseEntropy = calcShannonEnt(dataSet) #计算数据集的香农熵 109 bestInfoGain = 0.0 #信息增益 110 bestFeature = -1 #最优特征的索引值 111 for i in range(numFeatures): #遍历所有特征 112 #获取dataSet的第i个所有特征 113 featList = [example[i] for example in dataSet] 114 uniqueVals = set(featList) #创建set集合{},元素不可重复 115 newEntropy = 0.0 #经验条件熵 116 for value in uniqueVals: #计算信息增益 117 subDataSet = splitDataSet(dataSet, i, value) #subDataSet划分后的子集 118 prob = len(subDataSet) / float(len(dataSet)) #计算子集的概率 119 newEntropy += prob * calcShannonEnt(subDataSet) #根据公式计算经验条件熵 120 infoGain = baseEntropy - newEntropy #信息增益 121 # print("第%d个特征的增益为%.3f" % (i, infoGain)) #打印每个特征的信息增益 122 if (infoGain > bestInfoGain): #计算信息增益 123 bestInfoGain = infoGain #更新信息增益,找到最大的信息增益 124 bestFeature = i #记录信息增益最大的特征的索引值 125 return bestFeature #返回信息增益最大的特征的索引值 126 127 128 """ 129 函数说明:统计classList中出现此处最多的元素(类标签) 130 131 Parameters: 132 classList - 类标签列表 133 Returns: 134 sortedClassCount[0][0] - 出现此处最多的元素(类标签) 135 Author: 136 Jack Cui 137 Blog: 138 http://blog.csdn.net/c406495762 139 Modify: 140 2017-07-24 141 """ 142 def majorityCnt(classList): 143 classCount = {} 144 for vote in classList: #统计classList中每个元素出现的次数 145 if vote not in classCount.keys():classCount[vote] = 0 146 classCount[vote] += 1 147 sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse = True) #根据字典的值降序排序 148 return sortedClassCount[0][0] #返回classList中出现次数最多的元素 149 150 """ 151 函数说明:创建决策树 152 153 Parameters: 154 dataSet - 训练数据集 155 labels - 分类属性标签 156 featLabels - 存储选择的最优特征标签 157 Returns: 158 myTree - 决策树 159 Author: 160 Jack Cui 161 Blog: 162 http://blog.csdn.net/c406495762 163 Modify: 164 2017-07-25 165 """ 166 def createTree(dataSet, labels, featLabels): 167 classList = [example[-1] for example in dataSet] #取分类标签(是否放贷:yes or no) 168 if classList.count(classList[0]) == len(classList): #如果类别完全相同则停止继续划分 169 return classList[0] 170 if len(dataSet[0]) == 1: #遍历完所有特征时返回出现次数最多的类标签 171 return majorityCnt(classList) 172 bestFeat = chooseBestFeatureToSplit(dataSet) #选择最优特征 173 bestFeatLabel = labels[bestFeat] #最优特征的标签 174 featLabels.append(bestFeatLabel) 175 myTree = {bestFeatLabel:{}} #根据最优特征的标签生成树 176 del(labels[bestFeat]) #删除已经使用特征标签 177 featValues = [example[bestFeat] for example in dataSet] #得到训练集中所有最优特征的属性值 178 uniqueVals = set(featValues) #去掉重复的属性值 179 for value in uniqueVals: #遍历特征,创建决策树。 180 myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), labels, featLabels) 181 return myTree 182 183 """ 184 函数说明:使用决策树分类 185 186 Parameters: 187 inputTree - 已经生成的决策树 188 featLabels - 存储选择的最优特征标签 189 testVec - 测试数据列表,顺序对应最优特征标签 190 Returns: 191 classLabel - 分类结果 192 Author: 193 Jack Cui 194 Blog: 195 http://blog.csdn.net/c406495762 196 Modify: 197 2017-07-25 198 """ 199 def classify(inputTree, featLabels, testVec): 200 firstStr = next(iter(inputTree)) #获取决策树结点 201 secondDict = inputTree[firstStr] #下一个字典 202 featIndex = featLabels.index(firstStr) 203 for key in secondDict.keys(): 204 if testVec[featIndex] == key: 205 if type(secondDict[key]).__name__ == ‘dict‘: 206 classLabel = classify(secondDict[key], featLabels, testVec) 207 else: classLabel = secondDict[key] 208 return classLabel 209 210 if __name__ == ‘__main__‘: 211 dataSet, labels = createDataSet() 212 featLabels = [] 213 myTree = createTree(dataSet, labels, featLabels) 214 testVec = [0,0] #测试数据 215 result = classify(myTree, featLabels, testVec) 216 if result == ‘yes‘: 217 print(‘放贷‘) 218 if result == ‘no‘: 219 print(‘不放贷‘)
原文地址:https://www.cnblogs.com/smartisn/p/12403877.html
时间: 2024-11-09 02:04:12