机器学习——分类算法2:决策树 思想和代码解释
2018-01-28 21:52
543 查看
思想:
将原始数据集根据决定性特征划分为几个数据子集,这些数据子集会分布在第一个决策点的所有分支上,如果某个分支下的数据属于同一类型,则表示到达终止模块,可以得到结论,无需进一步对数据集进行分割;如果子集内的数据不属于同一类型,则需重复划分数据子集,直到所有具有相同类型的数据均在一个数据子集内。但是应该怎样划分数据呢,显然是根据决定性特征,这里引进一个度量标准--信息增益(划分数据集之前之后信息发生的变化),我们可以计算每个特征值划分划分数据集获得的信息增益,获得信息增益最高的特征就是最好的选择。数据:
no surfacing(不浮出水面是否可以生存) | flippers(是否有脚蹼) | file(是否为鱼类) |
1 | 1 | yes |
1 | 1 | yes |
1 | 0 | no |
0 | 1 | no |
0 | 1 | no |
代码
python3版本代码(对于小白,在每次测试时候,可以打断点到测试那里,更容易理解,对于print过多,自行删除):from math import log import operator #创建数据集,自己可以定义 def creatDataSet(): dataSet = [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']] labels = ['no surfacing', 'flippers'] return dataSet, labels #显示数据集和标签 myDat, labels = creatDataSet() #测试 print("dataSet:") print(myDat) print("labels:") print(labels) print("----------------"*10) ################################################################################################################ #计算给定数据集的香农熵 """ 1、计算各个分类出现的次数 2、计算各个分类出现的概率 3、根据香农公式:H(X)=−∑p(xi)*log2(p(xi)),其中p(xi)为各个分类的期望,计算香农熵 """ def calcShannonEnt(dataSet): """ :param dataSet: 数据集 :return: 香农熵 """ numEntries = len(dataSet)#数据集的总数 labelCounts = {}#字典,{类别:数量}---{'yes':1} #1、为所有可能分类创建字典,计算各个分类出现的次数 for featVec in dataSet: currentLabel = featVec[-1]#数组下表-1表示该数据的最后一个,也就是'yes'或者'no' if currentLabel not in labelCounts.keys():#如果没有改分类,则创建该字典 labelCounts[currentLabel] = 0 labelCounts[currentLabel] += 1#累加分类 #显示该字典数据 print("此时该字典数据:", labelCounts) #2、3、计算概率、计算香农熵,公式:H(X)=−∑p(xi)*log2(p(xi)),其中p(xi)为各个分类的期望 shannonEnt = 0.0#初始化香农熵 for key in labelCounts: prob = float(labelCounts[key])/numEntries#计算该分类的期望值,即概率 shannonEnt -= prob * log(prob, 2)#以2为底求对数 # 显示计算后的香农熵 print("此时香农熵:", shannonEnt) return shannonEnt #测试 calcShannonEnt(myDat) ################################################################################################################## #先讲一下extend和append的区别 print("--------------------"*10) a = [1, 2, 3] b = [4, 5, 6] a.extend(b) print("extend:先将自己分解成元素,然后加到其他元素后面") print(a) A = [1, 2, 3] B = [4, 5, 6] A.append(B) print("append:不分解,直接加到其他元素后面,是什么样还是什么样") print(A) print("--------------------"*10) ################################################################################################################### #按照给定特征划分数据集 def splitDataSet(dataSet, axis, value): """ :param dataSet: 待划分的数据集 :param axis: 划分数据集的特征列,就是第几列 :param value: 特征列的值,就是第几列的值 :return:返回的是与特征列值匹配后并且去除特征列的数组对象 """ retDataSet = []#创建新的list对象,这个list里面各个元素也都是list for featVec in dataSet: if featVec[axis] == value:#如果该特征与值对应 reducedFeatVec = featVec[:axis]#该特征列前面列 reducedFeatVec.extend(featVec[axis+1:])#该特征列+1后面的列,extend是将自身变为元素再追加到数组元素后面 retDataSet.append(reducedFeatVec)#直接追加到list对象中 return retDataSet #测试 print(myDat) print(splitDataSet(myDat, 0, 1)) print(splitDataSet(myDat, 0, 0)) print("--------------------"*10) ################################################################################################################### #选择最好的数据集划分方式 """ 1、记录原始熵 2、对每个特征进行循环计算各个特征的熵: 2.1获取每个特征所有值 2.2对每个特征值循环进行划分计算熵 3、计算信息增益,公式:gain(S ,A) = Entropy(S) - ∑|Sv|/|S|*Entropy(Sv),其中,S为整个集合,v为特征A的值,A表示特征,Entropy(S)为原始熵,Sv为特征为A的,值为v的子集 """ def chooseBestFeature(dataSet): """ :param dataSet: 待分类的数据集 :return: 返回最好的特征列 """ numFeatures = len(dataSet[0])-1#特征总数,最后那个分类不算 print("原始香农熵:") # 1、计算原始香农熵 baseEntropy = calcShannonEnt(dataSet) print("给定特征之后,进入for循环:\n", "-------"*14) #2、对每个特征进行循环计算各个特征的熵 bestInfoGain = 0.0 #最好的信息增益初始化 beatFeature = -1 #最好的特征初始化 for i in range(numFeatures): print("第一层for循环:") # 2.1、获取第i个特征,所有的可能取值 featList = [example[i] for example in dataSet] print("原始数据集:", dataSet) print("第%d个特征列的所有值:" %(i), featList) uniqueVals = set(featList) #set集合,重复的元素会合并,也就是uniqueVals是{0,1} newEntropy = 0.0 #新的香农熵 # 2.2、计算每一种划分方式的香农熵 for value in uniqueVals: print("第二层for循环:", "-------"*5) subDataSet = splitDataSet(dataSet, i, value) #按照给定特征划分数据集 print("此时给定特征划分后的数据集为:", subDataSet) prob = len(subDataSet)/float(len(dataSet)) #子集在原始集的期望 newEntropy += prob * calcShannonEnt(subDataSet) #子集的香农熵*期望,其中此处是∑|Sv|/|S|*Entropy(Sv) #3、计算最好的信息增益 print("计算最好的信息增益:", "-----"*8) infoGain = baseEntropy - newEntropy print("原始香农熵:", baseEntropy) print("新分类后的香农熵:", newEntropy) print("相减之后:", infoGain) if(infoGain > bestInfoGain): bestInfoGain =infoGain beatFeature = i print("-------"*10) print("最好的特征列:", beatFeature) print("-------------------------"*10) return beatFeature #测试 chooseBestFeature(myDat) #下面就是决策树,进入正题,对于前面的要理解清楚,后面的都是调用前面的方法,将前面可以单独运行 ########################################################################################################## #特征用完仍不能将数据集划分为只包含唯一类别的分组,返回出现次数最多的 def majorityCnt(classList): classCount = {}#对分类进行计数 for vote in classList: if vote not in classCount.keys(): classCount[vote] = 0 classCount[vote] += 1 sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0] ############################################################################################################# #创建决策树 def createTree(dataSet,labels): classList = [example[-1] for example in dataSet]#获取数据集的每一个类别 print("classList", classList) if classList.count(classList[0]) == len(classList): #终止条件之一:所有数据的类别的都相同 return classList[0] if len(dataSet[0]) == 1:#终止条件之二:特征用完仍不能将数据集划分为只包含唯一类别的分组,返回出现次数最多的。 return majorityCnt(classList) bestFeat = chooseBestFeature(dataSet) #选择最佳划分特征 bestFeatLabel = labels[bestFeat] #对应的标签 myTree = {bestFeatLabel:{}} #用字典来存储树 print("myTree", myTree) del(labels[bestFeat])#删除最好的标签留下其他标签 featValues = [example[bestFeat] for example in dataSet] #跟上个函数一样,不赘述 print("featValues", featValues) uniqueVals = set(featValues)#uniqueVals为0,1 for value in uniqueVals: subLabels = labels[:] print("subLabels :", subLabels) myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), subLabels) #按照给定特征划分数据集,在数据集上递归调用 return myTree #测试 print(createTree(myDat,labels))
结果:{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}
图片形式:
相关文章推荐
- 机器学习——分类算法4:Logistic回归 梯度上升 思想 和 代码解释
- 机器学习——分类算法3:朴素贝叶斯(Bayes) 思想 和 代码解释
- 机器学习——分类算法1:k-近邻 (KNN) 思想和代码
- 机器学习技法-决策树和CART分类回归树构建算法
- 用Python开始机器学习(2:决策树分类算法)
- [Java][机器学习]用决策树分类算法对Iris花数据集进行处理
- 第四篇:决策树分类算法原理分析与代码实现
- 用Python开始机器学习(2:决策树分类算法)
- 决策树分类算法原理分析与代码实现
- 机器学习实战代码详解(七)利用AdaBoost元算法提高分类性能
- 用Python开始机器学习(2:决策树分类算法)
- MP算法和OMP算法及其思想 分类: 机器学习 2014-08-16 10:50 116人阅读 评论(0) 收藏
- DNS通道检测 国内学术界研究情况——研究方法:基于特征或者流量,使用机器学习决策树分类算法居多
- 《机器学习:算法原理与编程实践》的读书笔记:SMO部分最难,大部分代码基于Scikit-Learn,决策树其实用处不大
- python机器学习——数据的分类(knn,决策树,贝叶斯)代码笔记
- 用Python开始机器学习(2:决策树分类算法)
- 机器学习经典算法详解及Python实现--CART分类决策树、回归树和模型树
- 【机器学习】分类算法之决策树(Decision tree)
- 2python机器学习--SVM(决策树分类算法)
- 决策树分类算法及python代码实现案例