决策树Python实现

决策树的实现主要是通过进行特征选择来进行决策树构建,而特征选择取决于信息增益或者信息增益比
信息增益由熵和条件熵确定 熵是表示随机变量不确定时的度量
决策树的实现比较多的是利用信息增益来实现的,在 划 分 数 据 集 之 前 之 后 信 息 发 生 的 变 化 称 为 信 息 增 益 ,通过特 征 值 划 分 数 据 集 获 得 的 信 息 增 益 ,获 得 信 息 增 益 最 高 的 特 征 就 是 最 好 的 选 择。
得 到 熵 之 后 , 我 们 就 可 以 按 照 获 取 最 大 信 息 增 益 的 方 法 划 分 数 据 集

计算香农熵的函数
def calcShannonEnt(dataSet):
    numEntries = len(dataSet) # 数据的长度
    labelCounts = {}
    for featVec in dataSet:
        currentLabel = featVec[-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):
    retDataSet = []
    for featVec in dataSet:
        if featVec[axis] == value:
            reducedFeatVec = featVec[:axis]     #选择划分数据集的特征进行划分
            reducedFeatVec.extend(featVec[axis+1:])
            retDataSet.append(reducedFeatVec)
    return retDataSet

选择最好的特征划分方式

def chooseBestFeatureToSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1 # 获取数据集长度
    baseEntropy = calcShannonEnt(dataSet) # 计算数据集的熵
    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:   #计算每种划分方式的信息熵
            subDataSet = splitDataSet(dataSet, i, value)
            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:   # 遍历 完 所 有 特 征 时 返 回 出 现 次 数 最 多 的
        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

对于创建好的树,可以通过matplotlib画出来 也可以通过pydotplus,graphviz转化为可视化pdf
createTree.export_graphviz(clf, out_file=dot_data)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
graph.write_pdf("xxx.pdf")#写入pdf

决 策 树 非 常 好 地 匹 配 了 实 验 数 据 , 然 而 这 些 匹 配 选 项 可 能 太 多 了 。我 们 将 这 种问 题 称 之 为 过 度 匹 配 。为 了 减 少 过 度 匹 配 问 题 , 我 们 可 以 裁 剪 决 策 树 , 去 掉 一 些 不必要 的 叶 子 节 点。如果 叶 子 节 点只 能 增 加 少 许 信 息 , 则 可 以 删 除 该 节 点, 将 它 并 人 到 其 他 叶 子 节点 中 本次使用的算法是ID3 算法 ,但是该算法并不完美,如果 存 在 太 多 的 特 征 划 分 , ID3 算 法 仍 然 会 面 临 其 他 问 题

决 策 树 分 类 器 就 像 带有 终 止 块 的 流 程 图 , 终 止 块 表 示 分 类 结 果 。开 始 处 理 数 据 集 时 , 我 们 首先 需 要 测 量 集 合 中 数 据 的 不 一 致 性 , 也 就 是 熵 , 然 后 寻 找 最 优 方 案 划 分 数 据 集 , 直 到 数 据 集 中 的所 有 数 据 属 于 同 一 分 类

通 过 裁 剪 决 策 树 , 合 并 相 邻 的 无 法 产 生 大 量 信 息 增 益
的 叶 节 点, 消 除 过 度 匹 配 问 题
决策树有多种生成方式,第一种就是上面使用的iD3,还有就是使用信息增益比的 C4.5生成算法以及使用基尼指数的CART 分类回归树生成,值得一提的是,在使用CART 生成决策树的时候,基尼指数和信息增益的选取恰恰相反。选取基尼指数最小的最优特征

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值