机器学习:决策树python实现

                                     机器学习:决策树python实现源码笔记


     打算今天开始回顾一下ml的经典算法,就去按照书上实现了决策树。其实,ml代码模式有很大的相似之处,特征的划分等等。

def createDataSet():
    dataSet = [[1, 1, 'yes'],
               [1, 1, 'yes'],
               [1, 0, 'no'],
               [0, 1, 'no'],
               [0, 1, 'no']]
	# 下面的标签labels主要是对应dataset上的1和0,yes和no代表的是标签
    labels = ['no surfacing','flippers']
    return dataSet, labels

	//计算数据集的信息熵
def calcShannonEnt(dataSet):
    numEntries = len(dataSet)
    labelCounts = {}
    for featVec in dataSet: //主要是实现对标签的计数
        currentLabel = featVec[-1]//这里对应数据标签
        if currentLabel not in labelCounts.keys(): 
		//当前的标签还不存在在labelcounts中
		    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
 
//按照不同的属性列划分数据 axis--列索引,value--当前的列所对应的数据
def splitDataSet(dataSet, axis, value):
    retDataSet = []
    for featVec in dataSet:
	    //属性列中不同的数据进行不同的划分
        if featVec[axis] == value:
		    //数据的从新组合--去掉当前的value。
			//[1,2,3]-->[1,3]-->用数值2去划分
            reducedFeatVec = featVec[:axis]     
            reducedFeatVec.extend(featVec[axis+1:])
            retDataSet.append(reducedFeatVec)
    return retDataSet

//选择最好的划分属性所对应的索引-->也就是选择划分前后entory变化最大的划分    
def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1//特征的个数      
    baseEntropy = calcShannonEnt(dataSet)//计算当前data的entory
    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:
		    //对特征i下不同的value进行划分数据,在计算划分之后的entory
            subDataSet = splitDataSet(dataSet, i, value)
			//划分之后每个数据集所占的比例
            prob = len(subDataSet)/float(len(dataSet))
			//计算划分之后的entory
            newEntropy += prob * calcShannonEnt(subDataSet)  
        //计算划分前后entory的差			
        infoGain = baseEntropy - newEntropy    
        if (infoGain > bestInfoGain):       
            bestInfoGain = infoGain         
            bestFeature = i
    return bestFeature                      

//考虑到存在就算划分到最后,有些节点的还会存在两种以上的label
//那就找出划分之后节点中label最多的那个label
def majorityCnt(classList):
    classCount={}
    for vote in classList://计算每个label所对应的个数
        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):
    //找出当前数据中存在的labels
    classList = [example[-1] for example in dataSet]
	//只有一种label的话也就代表当前的data停止划分
    if classList.count(classList[0]) == len(classList): 
        return classList[0]
	//当前的data中只有一个特征,就不要再划分了。
    if len(dataSet[0]) == 1: 
        return majorityCnt(classList)
	//找出最好的划分特征索引
    bestFeat = chooseBestFeatureToSplit(dataSet)
	//得到特征
    bestFeatLabel = labels[bestFeat]
	//把当前的特征作为tree的根
    myTree = {bestFeatLabel:{}}
    del(labels[bestFeat])//当前的label已经划分过之后就不会再划分,删除
	//得到索引所对应的全部属性值
    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                            


你可能感兴趣的:(MachineLearning)