决策树Python实现

来源:互联网 发布:淘宝 手办时光机 编辑:程序博客网 时间:2024/05/22 06:54

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

计算香农熵的函数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 生成决策树的时候,基尼指数和信息增益的选取恰恰相反。选取基尼指数最小的最优特征

0 0