def createDataSet(): #创造数据, 并在最后 return 数据集数组和 标签
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] #将样本数据最后一样的标签及结果赋值给currentLabel
if currentLabel not in labelCounts.keys(): labelCounts[currentLabel] = 0
labelCounts[currentLabel] += 1 #如何labelcount 里面有由这个key了 就加1 没有的话 新建并赋值0
#以上可以得出 样本中 不同类别的样本个数
shannonEnt = 0.0 #将信息熵设定初试数值为0
for key in labelCounts: #遍历labelCounts 这个字典里面的key 进行遍历 ,并进行信息熵的计算
prob = float(labelCounts[key])/numEntries
shannonEnt -= prob * log(prob, 2)
return shannonEnt #返回的是样本的信息熵
def splitDataSet(dataSet, axis, value): #根据某一属性进行分节的函数,这里的axis为需要考察属性的引索值,value为该属性下值
retDataSet = [] #先建立一个空list 用于下面的储存
for featVec in dataSet: #对样本数据里面的每一个样本信息进行遍历
if featVec[axis] == value: #如果该样本属性对应的值 为参数的值时 进入到下一步,如果不是 回到for 语句去
reducedFeatVec = featVec[:axis] #在确定属性及其需要的值之后,对样本的数据进行分割,和下面一起的2行代码
#将 样本信息中 该属性对应的值去掉, 及以它为节点,方便进行下一次的 分节,因为在用某一属性进行分节之后,继续往下走
#就不会再由该属性对应的值
reducedFeatVec.extend(featVec[axis+1:])
retDataSet.append(reducedFeatVec)
return retDataSet #返回去掉分解属性之后的样本数据
def chooseBestFeatureToSplit(dataSet): #选择最后特征值并进行分节的操作
numFeatures = len(dataSet[0]) - 1 #先求出每个样本数据的长度, 这里减去1 是因为 样本数据里面的最后一项为结果,不参与分节
baseEntropy = calcShannonEnt(dataSet) # 调用calcShannonEnt(dataSet) 函数 计算样本整体的信息熵
bestInfoGain = 0.0; bestFeature = -1 #初始化两个变量
for i in range(numFeatures): #假设有3个属性,则对这3个属性进行遍历,分别计算各自的信息增益,来判断最后的分节属性
featList = [example[i] for example in dataSet] # 先取出每个属性下面对应的取指,放在featlist 这个列表里面
uniqueVals = set(featList) # 用set 去重,使列表里面的所有值都只出现一次,表示一个属性下分别有多少种可能
newEntropy = 0.0 # 定一个新的信息熵变量为0
for value in uniqueVals: # 对一个属性下的所有取指进行计算
subDataSet = splitDataSet(dataSet, i, value) #调用splitDateSet这个函数 得出某一属性下的分法,subDateset包好所有
#满足这个分支的样本数据
prob = len(subDataSet)/float(len(dataSet)) #满足的样本数据和总量的比值。
newEntropy += prob * calcShannonEnt(subDataSet) #计算该属性可能下的 信息熵
infoGain = baseEntropy - newEntropy #计算改属性分类的信息增益
if (infoGain > bestInfoGain): #取出属性里面最大的信息增益。
bestInfoGain = infoGain
bestFeature = i
return bestFeature #并返回最有属性对应的引索位置
def majorityCnt(classList):
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] #取得每一个样本的最后分类值
if classList.count(classList[0]) == len(classList):
return classList[0] #对分类值列表的第一项进行计数,如果它的数量就是列表的长度,则返回该结果值
if len(dataSet[0]) == 1: #如果数据只有最后一项列的时候, 返回classList里面出现最多次的类别值
return majorityCnt(classList)
bestFeat = chooseBestFeatureToSplit(dataSet) #调用选择最有参数的函数,并返回最后参数对应的引索位置
bestFeatLabel = labels[bestFeat] # 取出最优参数的 名字
myTree = {bestFeatLabel:{}} # 建了一个字典,该字典的key 为最后参数的名字
del(labels[bestFeat]) #删除labels 里面对应的特征
featValues = [example[bestFeat] for example in dataSet] #列出该最后属性下 所有的值,为一个列表
uniqueVals = set(featValues) #并对该属性下所有值进行去重
for value in uniqueVals: #对最后属性的每一个值进行遍历
subLabels = labels[:] # 复制去掉最后属性之后的 label列表
myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), subLabels)
#用最有的属性进行递归,创造决策树
return myTree #返回决策树
def classify(inputTree,featLabels,testVec): #在决策树做好之后,我们就开始进行数据的分类人物
firstStr = inputTree.keys()[0] #取出第一个分节的的label
secondDict = inputTree[firstStr] #去除第一个分节点的value值 是一个字典
featIndex = featLabels.index(firstStr) # 然后在featLabels 中 去匹配 第一个分节点 属性的 引索值,这里要注意的是featLabels是一个列表
#那么返回的就是 匹配成功元素的引索值
key = testVec[featIndex] #有了引索值之后,我们才能到测试数据的中找到对应的值,该值将进行帮助寻找下一个分节点或者最后分类结果
valueOfFeat = secondDict[key] #用测试对应的值作为key 去核对第二个字典里面对应这个key 的属性
if isinstance(valueOfFeat, dict): #isinstance()函数是用来判断 第一个参数的类型是不是第二个参数,如果是 则返回True
classLabel = classify(valueOfFeat, featLabels, testVec) #如果是一个字典,则说明这个是一个分节点,要进行递归
else: classLabel = valueOfFeat #如果不是 那么这个valueOfFeat 就是一个分类值
return classLabel #最后返回这个分类值
那个用matplotlab画决策树的代码 还没有搞清楚,明天搞清楚了 再来讲解。 机器学习的小白正在奋力挣扎,针对上面代码有不懂的 请下面提问