《机器学习实战》第三章决策树代码详解

本文深入解析决策树算法的实现过程,从数据集创建到决策树构建,再到分类预测,全面覆盖决策树算法的核心要点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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画决策树的代码 还没有搞清楚,明天搞清楚了 再来讲解。 机器学习的小白正在奋力挣扎,针对上面代码有不懂的 请下面提问

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值