2、原理
决策树是一种类似流程图的结构,其中每个内部节点代表对某个属性的“测试”,每个分支代表测试的结果,每个叶节点代表一个测试结果。 类标签(计算所有属性后做出的决定)。 从根到叶子的路径代表分类规则。
决策树学习的目的是产生具有强泛化能力的决策树,即处理未见过的例子的能力强。 因此,如何构建决策树是后续预测的关键! 构建决策树需要确定类标签判断的顺序,这决定了构建的决策树的性能。 决策树的分支节点应尽可能属于同一类别,即节点的“纯度”应越来越高。 只有这样,才能做出最好的决定。
经典的属性划分方法:
本实验使用了信息增益,因此下面仅介绍信息增益。
3.信息增益的计算方法
其中,D为样本集,a为样本集中的属性,Dv表示D样本集中a属性为v的样本集。
Ent(x)函数计算信息熵,它代表样本集合的纯度信息。 信息熵的计算方法如下:
其中pk表示样本中某一类别占最终结果类别的比例。 例如,有 10 个样本,其中 5 个为好样本,5 个为差样本,则 p1 = 5/10,p2 = 5/10。
一般来说,信息增益越大,利用属性进行划分所获得的“纯度提升”就越大。 因此,在选择属性节点时,优先考虑信息增益高的属性!
四、实施过程
本设计使用了 和 numpy 库,主要是利用它们来快速处理和使用数据。
首先读取数据:
可以看到数据集的标签是瓜的不同属性,表中的数据在不同属性下是不同的值等等。
if(len(set(D.好瓜)) == 1): #标记返回 return D.好瓜.iloc[0] elif((len(A) == 0) or Check(D, A[:-1])): #选择D中结果最多的为标记 cnt = D.groupby('好瓜').size() maxValue = cnt[cnt == cnt.max()].index[0] return maxValue else: A1 = copy.deepcopy(A) attr = Choose(D, A1[:-1]) tree = {attr:{}} for value in set(D[attr]): tree[attr][value] = TreeGen(D[D[attr] == value], A1) return tree
该函数是生成树的主要函数。 通过递归调用,返回下一级树结构(字典),完成决策树的生成。
在生成树过程中,终止迭代的条件有两个。 第一种是当所有输入数据源D的结果都相同时,那么将这个结果作为叶子节点返回; 二是当没有属性的时候,可以继续。 点,或者D中的样本在A的所有属性下具有相同的值,则返回D中所有案例中结果最多的一个作为叶子节点。
(D:pd.,A:list)函数是用于选择标签的函数。 它根据输入的数据源和剩余的属性列表计算相应的标签信息增益,并选择可以最大化信息增益的标签返回
def Choose(D:pd.DataFrame, A:list): result = 0.0 resultAttr = '' for attr in A: tmpVal = CalcZengYi(D, attr) if(tmpVal > result): resultAttr = attr result = tmpVal A.remove(resultAttr) return resultAttr
最终结果:
{'': {'稍微浑浊': {'touch': {'硬而光滑': '否', 'soft': '是'}}, 'clear': {'base': {'stiff ' : '否', '卷曲': '是', '轻微卷曲': {'颜色': {'青绿色': '是', '黑色': {'触摸': {'硬滑': '是'、'软':'否'}}}}}}、'模糊':'否'}}
图纸如下:
5. 程序
主程序
#!/usr/bin/python3 # -*- encoding: utf-8 -*- ''' @Description:决策树: @Date :2021/04/25 15:57:14 @Author :willpower @version :1.0 ''' import pandas as pd import numpy as np import treeplot import copy import math """ @description :计算javascript熵值 --------- @param :输入为基本pandas类型dataFrame,其中输入最后一行为实际结果 ------- @Returns :返回熵值,类型为浮点型 ------- """ def CalcShang(D:pd.DataFrame): setCnt = D.shape[0] result = 0.0 # for i in D.groupby(D.columns[-1]).size().index: #遍历每一个值 for i in set(D[D.columns[-1]]): #获取该属性下的某个值的次数 cnt = D.iloc[:,-1].value编程_counts()[i] result = result + (cnt/setCnt)*math.log(cnt/setCnt, 2) return (-1*result) """ @description :计算增益 --------- @param :输入为DataFrame数据源,然后是需要计算增益的属性值 ------- @Returns :返回增益值,浮点型 ------- """ def CalcZengYi(D:pd.DataFrame, attr:str): sumShang = CalcShang(D) setCnt = D.shape[0] result = 0.0 valus = D.groupby(attr).size() for subVal in valus.index: result = result + (valus[subVal]/setCnt)*CalcShang(D[D[attr] == subVal]) return sumShang - result """ @description :选择最佳的属性 --------- @param :输入为数据源,以及还剩下的属性列表 ------- @Returns :返回最佳属性 ------- """ def Choose(D:pd.DataFrame, A:list): result = 0.0 resultAttr = '' for attr in A: tmpVal = CalcZengYi(D, attr) if(tmpVal > result): resultAttr = attr result = tmpVal A.remove(resultAttr) return resultAttr """ @description :检查数据在每一个属性下面的值是否相同 --------- @param :输入为DataFrame以及剩下的属性列表 ------- @Returns :返回bool值,相同返回1,不同返回0 ------- """ def Check(D:pd.DataFrame, A:list): for i in A: if(len(set(D[i])) != 1): www.cppcns.com return 0 return 1 """ @description :生成树主函数 --------- @param :数据源DataFrame以及所有类型 ------- @Returns :返回生成的字典树 ------- """ def TreeGen(D:pd.DataFrame, A:list): if(len(set(D.好瓜)) == 1): #标记返回 return D.好瓜.iloc[0] elif((len(A) == 0) or Check(D, A[:-1])): #选择D中结果最多的为标记 cnt = D.groupby('好瓜').size() #找到结果最多的结果 maxValue = cnt[cnt == cnt.max()].index[0] return maxValue else: A1 = copy.deepcopy(A) attr = Choose(D, A1[:-1]) tree = {attr:{}} for value in set(D[attr]): tree[attr][value] = TreeGen(D[D[attr] == value], A1) return tree """ @description :验证集 --------- @param :输入为待验证的数据(最后一列为真实结果)以及决策树模型 ------- @Returns :无 ------- """ def Test(D:pd.DataFrame, model:dict): for i in range(D.shape[0]): data = D.iloc[i] subModel = model while(1): attr = list(subModel)[0] subModel = subModel[attr][data[attr]] if(type(subModel).__name__ != 'dict'): print(subModel, end='') break print('') name = ['色泽', '根蒂', '敲声', '纹理', '脐部', '触感', '好瓜'] df = pd.read_csv('./savedata.txt', names=name) # CalcZengYi(df, '色泽') resultTree = TreeGen(df, name) print(resultTree) # print(df[name[:-1]]) Test(df[name[:-1]], resultTree) treeplot.plot_model(resultTree,"resultTree.gv")
绘图程序
from graphviz import Digraph
def plot_model(tree, name):
g = Digraph("G", filename=name, format='png', strict=False)
first_label = list(tree.keys())[0]
g.node("0", first_label)
_sub_plot(g, tree, "0")
g.view()
root = "0"
def _sub_plot(g, tree, inc):
global root
first_label = list(tree.keys())[0]
ts = tree[first_label]
for i in ts.keys():
if isinstance(tree[first_label][i], dict):
root = str(int(root) + 1)
g.node(root, list(tree[first_label][i].keys())[0])
g.edge(inc, root, str(i))
_sub_plot(g, tree[first_label][i], root)
else:
js root = str(int(root) + 1)
g.node(root, tree[first_label][i])
g.edge(inc, root, str(i))
。/。TXT
绿色、卷曲、嘈杂、清晰、凹面、硬滑、是
黑色、卷曲、无光泽、透明、凹陷、坚硬光滑,是的
黑色、卷曲、嘈杂、清晰、凹凸、坚硬、光滑,是
绿色、卷曲、暗淡、透明、凹面、硬而滑,是
浅白、卷曲、嘈杂、清晰、凹凸、坚硬、光滑,是
绿色,微卷,嘈杂,清晰,微凹,软糯,有
黑色,微卷,吵闹,微糊状,微凹,软糯,有
黑色,微卷,有噪,清晰,微凹,坚硬光滑,是
黑色,微卷曲,无光泽,微糊状,微凹,质硬光滑,无
绿、硬、脆、清、平、软、粘、无
浅白色、僵硬、脆、毛茸茸、平坦、硬而光滑、无
浅白色、卷曲、嘈杂、模糊、扁平、软而粘、无
绿色、微卷、吵闹、微糊状、凹陷、硬而滑、无
浅白色,微卷曲,无光泽,微糊状,凹陷,质硬光滑,无
黑色、微卷、杂色、清晰、微凹、软而粘、无
浅白色、卷曲、杂乱、模糊、平坦、坚硬光滑、无
绿色,卷曲,无光泽,微糊状,微凹,质硬光滑,无
六、遇到的问题
不是:“点”
解决方案
关于机器学习中的决策树的文章到此结束。 有关决策树的更多信息,请搜索我们之前的文章或继续浏览下面的相关文章。 希望您今后能够支持我们!
本文标题:机器学习的决策树