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

'''
Created on Oct 12, 2010
Decision Tree Source Code for Machine Learning in Action Ch. 3
@author: Peter Harrington
'''
from math import log
import operator

def createDataSet():					#创建一个数据集,前两列为特征,最后一列为类别
    dataSet = [[1, 1, 'yes'],
               [1, 1, 'yes'],
               [1, 0, 'no'],
               [0, 1, 'no'],
               [0, 1, 'no']]
    labels = ['no surfacing','flippers']#特征对应的标签
   
    return dataSet, labels              #返回数据集和特征标签

def calcShannonEnt(dataSet):            #计算数据集的熵
    numEntries = len(dataSet)           #得出样本的数量
    labelCounts = {}                    #存放每个类别对应的样本的数量
    for featVec in dataSet: 
        currentLabel = featVec[-1]      #遍历数据集合中的最后一列(类别),如果该类别不在字典中,加入字典,如果已经在字典中计数加1 
        if currentLabel not in labelCounts.keys(): 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                                  #返回整个数据集合的熵
    
def splitDataSet(dataSet, axis, value):                #划分数据集合 axis为特征,value为特征对应的特征值
    retDataSet = []
    for featVec in dataSet:                            #遍历数据集合中的每一行,也就是一个样本
        if featVec[axis] == value:                     #选取参数所选定的样本
            reducedFeatVec = featVec[:axis]            #重新组织划分后的样本,样本中每一个行由 axis为特征,value为特征对应的特征值选定不包括该特征  
            reducedFeatVec.extend(featVec[axis+1:])
            retDataSet.append(reducedFeatVec)
    return retDataSet                                  #返回划分后的数据集
    
def chooseBestFeatureToSplit(dataSet):                 #根据ID3算法选择最佳特征进行分割
    numFeatures = len(dataSet[0]) - 1                  #计算一共有多少个特征,保存到numFeatures
    baseEntropy = calcShannonEnt(dataSet)              #计算总样本集合的熵
    bestInfoGain = 0.0; bestFeature = -1
    for i in range(numFeatures):        			   #迭代所有的特征,在一次for循环之内,遍历一个特征所对应的值,并统计每个特征值对应样本的数量
        featList = [example[i] for example in dataSet] #第i个特征,在整个数据集合内对应的特征值取值放进featList中
        uniqueVals = set(featList)                     #得带第i特征,所有可能的取值情况,set(featList)消除掉featlist中的重复的元素
        newEntropy = 0.0
        for value in uniqueVals:
            subDataSet = splitDataSet(dataSet, i, value)
            prob = len(subDataSet)/float(len(dataSet)) #计算第i个特征,取特征值value的个数在整个数据集合中的概率
            newEntropy += prob * calcShannonEnt(subDataSet) #循环n次把对用的值相加,计算出条件熵    
        infoGain = baseEntropy - newEntropy                 #信息增益=数据集合的熵-条件熵
        if (infoGain > bestInfoGain):                       #统计出信息增益最大的特征值,并把该特征i作为bestFeature返回
            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]         #把整个数据集合中的最后一列(类别)放进一个List
    if classList.count(classList[0]) == len(classList):      #如果classlist中所有的类别都为同一个类别,递归结束,返回该类别
        return classList[0]
    if len(dataSet[0]) == 1:                                 #使用完了所有特征,仍然不能讲数据划分成仅包含唯一类别的分组
        return majorityCnt(classList)
    bestFeat = chooseBestFeatureToSplit(dataSet)             #计算最佳特征切分数据
    bestFeatLabel = labels[bestFeat]                         #最佳特征对应的标签
    myTree = {bestFeatLabel:{}}                              #通过字典存放决策树
    del(labels[bestFeat])                                    #删除已经进入树的标签
    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                            
    
def classify(inputTree,featLabels,testVec):
    firstStr = inputTree.keys()[0]
    secondDict = inputTree[firstStr]
    featIndex = featLabels.index(firstStr)
    key = testVec[featIndex]
    valueOfFeat = secondDict[key]
    if isinstance(valueOfFeat, dict): 
        classLabel = classify(valueOfFeat, featLabels, testVec)
    else: classLabel = valueOfFeat
    return classLabel

def storeTree(inputTree,filename):
    import pickle
    fw = open(filename,'w')
    pickle.dump(inputTree,fw)
    fw.close()
    
def grabTree(filename):
    import pickle
    fr = open(filename)
    return pickle.load(fr)


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
周志华是一位著名的机器学习专家,他在《机器学习》一书中详细介绍了决策树算法。下面是决策树算法的伪代码: 1. 定义决策树节点类: class DecisionTreeNode: def __init__(self): self.feature = None # 当前节点选择的特征 self.threshold = None # 特征的阈值 self.label = None # 叶子节点的类别标签 self.left_child = None # 左子树 self.right_child = None # 右子树 2. 定义决策树构建函数: def build_decision_tree(data, labels): # 创建新节点 node = DecisionTreeNode() # 如果所有样本属于同一类别,则将当前节点标记为叶子节点,并返回 if all_same_class(labels): node.label = labels return node # 如果没有特征可用,则将当前节点标记为叶子节点,并返回 if no_more_features(): node.label = majority_class(labels) return node # 选择最优特征和阈值 best_feature, best_threshold = choose_best_feature(data, labels) node.feature = best_feature node.threshold = best_threshold # 根据最优特征和阈值划分数据集 left_data, left_labels, right_data, right_labels = split_data(data, labels, best_feature, best_threshold) # 递归构建左子树和右子树 node.left_child = build_decision_tree(left_data, left_labels) node.right_child = build_decision_tree(right_data, right_labels) return node 3. 定义决策树预测函数: def predict(node, sample): if node.label is not None: return node.label if sample[node.feature] <= node.threshold: return predict(node.left_child, sample) else: return predict(node.right_child, sample) 以上是决策树算法的伪代码,其中包括了决策树节点类的定义、决策树构建函数和决策树预测函数。通过递归地选择最优特征和阈值来构建决策树,并使用构建好的决策树进行样本的预测。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值