python中怎么模拟决策树
发表于:2025-12-01 作者:千家信息网编辑
千家信息网最后更新 2025年12月01日,本篇文章为大家展示了python中怎么模拟决策树,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1,程序模拟决策树特征选择的三个准则。import numpy
千家信息网最后更新 2025年12月01日python中怎么模拟决策树
本篇文章为大家展示了python中怎么模拟决策树,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
1,程序模拟决策树特征选择的三个准则。
import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom sklearn.datasets import load_irisfrom sklearn.model_selection import train_test_splitfrom collections import Counterimport mathfrom math import logimport pprint# 课本例题数据def createData(): datasets = [ ['青年', '否', '否', '一般', '否'], ['青年', '否', '否', '好', '否'], ['青年', '是', '否', '好', '是'], ['青年', '是', '是', '一般', '是'], ['青年', '否', '否', '一般', '否'], ['中年', '否', '否', '一般', '否'], ['中年', '否', '否', '好', '否'], ['中年', '是', '是', '好', '是'], ['中年', '否', '是', '非常好', '是'], ['中年', '否', '是', '非常好', '是'], ['老年', '否', '是', '非常好', '是'], ['老年', '否', '是', '好', '是'], ['老年', '是', '否', '好', '是'], ['老年', '是', '否', '非常好', '是'], ['老年', '否', '否', '一般', '否'] ] labels = ['年龄', '有工作', '有自己的房子', '信贷情况', '类别'] return datasets, labels# 计算经验熵def calc_ent(datasets): data_length = len(datasets) label_count = {} # 用于记录不同类别的个数 for i in range(data_length): label = datasets[i][-1] # 记录了当前一条数据的最后一维 if label not in label_count: # 如果第一次遇到新类别,先初始化 label_count[label] = 0 label_count[label] += 1 # 类别个数加一 # 计算熵。每次取出的p为当前datasets集合的类别的个数 ent = -sum( (p / data_length) * log(p / data_length, 2) for p in label_count.values() ) return ent# 计算条件经验熵def cond_ent(datasets, axis=0): # axis是我们选择的特征,也及时计算这个特征对集合的条件经验熵。 data_length = len(datasets) feature_sets = {} for i in range(data_length): feature = datasets[i][axis] if feature not in feature_sets: feature_sets[feature] = [] feature_sets[feature].append(datasets[i]) # 我们按照特征将数据按照字典的格式存储。 # 计算条件经验熵。 (Di/D)*H(Di)。这里每次取出的p为属于范类别的所有数据。这里的类别是axis指定的特征的分类。 cond_ent = sum((len(p)/data_length)*calc_ent(p) for p in feature_sets.values()) return cond_ent# 计算信息增益def info_gain(ent, cond_ent): return ent - cond_ent# 计算信息增益def info_gain_train(datasets): count = len(datasets[0]) - 1 ent = calc_ent(datasets) print("当前经验熵:{:.3f}\n".format(ent)) best_feature = [] for c in range(count): print("第{}个特征的条件经验熵为:{:.3f}".format(c+1, cond_ent(datasets, c))) c_info_gain = info_gain(ent, cond_ent(datasets, c)) best_feature.append((c, c_info_gain)) print("当前特征({})的信息增益为:{:.3f}".format(label[c], c_info_gain)) best = max(best_feature, key=lambda c : c[-1]) # 这里返回的是信息增益最大的元组 return bestdataset, label = createData()trainData = pd.DataFrame(dataset, columns=label)best_feature = info_gain_train(dataset)print("\n第{}个特征({})的信息增益最大,为:{:.3f}".format(best_feature[0]+1, label[best_feature[0]+1], best_feature[1]))结果
当前经验熵:0.971第1个特征的条件经验熵为:0.888当前特征(年龄)的信息增益为:0.083第2个特征的条件经验熵为:0.647当前特征(有工作)的信息增益为:0.324第3个特征的条件经验熵为:0.551当前特征(有自己的房子)的信息增益为:0.420第4个特征的条件经验熵为:0.608当前特征(信贷情况)的信息增益为:0.363第3个特征(信贷情况)的信息增益最大,为:0.420
2,程序实现ID3算法
import pandas as pdimport numpy as npimport mathfrom math import logdef create_data(): datasets = [['青年', '否', '否', '一般', '否'], ['青年', '否', '否', '好', '否'], ['青年', '是', '否', '好', '是'], ['青年', '是', '是', '一般', '是'], ['青年', '否', '否', '一般', '否'], ['中年', '否', '否', '一般', '否'], ['中年', '否', '否', '好', '否'], ['中年', '是', '是', '好', '是'], ['中年', '否', '是', '非常好', '是'], ['中年', '否', '是', '非常好', '是'], ['老年', '否', '是', '非常好', '是'], ['老年', '否', '是', '好', '是'], ['老年', '是', '否', '好', '是'], ['老年', '是', '否', '非常好', '是'], ['老年', '否', '否', '一般', '否'], ] labels = [u'年龄', u'有工作', u'有自己的房子', u'信贷情况', u'类别'] # 返回数据集和每个维度的名称 return datasets, labels# 定义节点类 二叉树class Node: def __init__(self, root=True, label=None, feature_name=None, feature=None): self.root = root # 标记当前节点是否为根节点 self.label = label # label记录当前节点的值 self.feature_name = feature_name # 记录当前特征名 self.feature = feature # 记录当前特征名在特征列表中的序号 self.tree = {} self.result = { 'label:': self.label, 'feature': self.feature, 'tree': self.tree } def __repr__(self): # 返回当前节点的信息 return '{}'.format(self.result) def add_node(self, val, node): # 添加点 self.tree[val] = node def predict(self, features): # 预测当前节点 if self.root is True: return self.label return self.tree[features[self.feature]].predict(features)class DTree: def __init__(self, epsilon=0.1): self.epsilon = epsilon # 阈值,用于判断当前信息增益是否符合大小。如果信息增益小于阈值,等同于忽略。 self._tree = {} # 熵 @staticmethod def calc_ent(datasets): data_length = len(datasets) label_count = {} for i in range(data_length): label = datasets[i][-1] if label not in label_count: label_count[label] = 0 label_count[label] += 1 ent = -sum([(p / data_length) * log(p / data_length, 2) for p in label_count.values()]) return ent # 经验条件熵 def cond_ent(self, datasets, axis=0): data_length = len(datasets) feature_sets = {} for i in range(data_length): feature = datasets[i][axis] if feature not in feature_sets: feature_sets[feature] = [] feature_sets[feature].append(datasets[i]) cond_ent = sum([(len(p) / data_length) * self.calc_ent(p) for p in feature_sets.values()]) return cond_ent # 信息增益 @staticmethod def info_gain(ent, cond_ent): return ent - cond_ent def info_gain_train(self, datasets): # 计算当前数据集中信息增益最大的特征。 count = len(datasets[0]) - 1 ent = self.calc_ent(datasets) best_feature = [] for c in range(count): c_info_gain = self.info_gain(ent, self.cond_ent(datasets, axis=c)) best_feature.append((c, c_info_gain)) # 比较大小 best_ = max(best_feature, key=lambda x: x[-1]) return best_ def train(self, train_data): """ input:数据集D(DataFrame格式),特征集A,阈值eta output:决策树T """ _ = train_data.iloc[:, :-1] # 除最后一列的所有数据 y_train = train_data.iloc[:, -1] # 仅包含最后一列 features = train_data.columns[:-1] # 除最后一个特征以外的特征 # 下面是ID3算法四步。D为训练数据集,A为特征集。 # 1 若D中实例属于同一类Ck,则T为单节点树,并将类Ck作为结点的类标记,返回T if len(y_train.value_counts()) == 1: # value_counts函数,对数据按照值进行排序,并且按照从大到小排序 return Node(root=True, label=y_train.iloc[0]) # 2 若A为空,则T为单节点树,将D中实例树最大的类Ck作为该节点的类标记,返回T if len(features) == 0: return Node( root=True, label=y_train.value_counts().sort_values( ascending=False).index[0]) # 没有特征进行划分了,所以对当前数据集所有类别进行了归类,并计数,然后排序, # 选择类别数最大的类别,估计为当前节点代表的类别 # 3 计算最大信息增益 # max_feature为信息增益最大特征名字的序号, # max_info_gain为最大信息增益 # max_feature_name为最大信息增益特征名字 max_feature, max_info_gain = self.info_gain_train(np.array(train_data)) max_feature_name = features[max_feature] # 4 信息增益小于阈值,忽略,置T为单节点树,并将D中是实例数最大的类Ck作为该节点的类标记,返回T if max_info_gain < self.epsilon: return Node( root=True, label=y_train.value_counts().sort_values( ascending=False).index[0]) # 5 构建最大信息增益点Ag的子集。 # 按照Ag的每一个可能的取值ai,将数据集D分成一个Di,每个Di中实例数最大的类作为标记,构建子节点。 # 由当前最大信息增益点及其子节点构成树,并返回 node_tree = Node( root=False, feature_name=max_feature_name, feature=max_feature) # 将train_data按照 当前最大信息增益特征不同值 划分,index指value_counts后的类别部分 feature_list = train_data[max_feature_name].value_counts().index for f in feature_list: # 去掉 最大信息增益这个特征 sub_train_df = train_data.loc[train_data[max_feature_name] == f].drop([max_feature_name], axis=1) # 6 递归生成树 # 对去掉这个特征的数据继续进行训练 sub_tree = self.train(sub_train_df) # 将当前节点加到递归上层父节点上。 # 这个算法不是从根节点,一步一步加点生成树, # 而是从根节点开始找出最大信息增益节点,这个点只是声明了一下,并没有建立联系。然后递归向下,到达叶节点之后, # 将叶节点添加到上层递归的父节点,然后父节点在train另一个子节点,然后将子节点在加入到父节点。 # 这时最初的根节点仍然是只有一个点,但是最下边的某个子树已经建立了父子关系,生成了树 node_tree.add_node(f, sub_tree) return node_tree def fit(self, train_data): self._tree = self.train(train_data) return self._tree def predict(self, X_test): return self._tree.predict(X_test)datasets, labels = create_data()data_df = pd.DataFrame(datasets, columns=labels)dt = DTree()tree = dt.fit(data_df)print(tree)print("下边预测数据:[老年, 否, 否, 一般],结果为:")print(dt.predict(['老年', '否', '否', '一般']))结果:
{'label:': None, 'feature': 2, 'tree': {'否': {'label:': None, 'feature': 1, 'tree': {'否': {'label:': '否', 'feature': None, 'tree': {}}, '是': {'label:': '是', 'feature': None, 'tree': {}}}}, '是': {'label:': '是', 'feature': None, 'tree': {}}}}下边预测数据:[老年, 否, 否, 一般],结果为:否3,sklearn模拟
import numpy as npimport pandas as pdfrom sklearn.datasets import load_irisfrom sklearn.model_selection import train_test_splitfrom sklearn.tree import DecisionTreeClassifierfrom sklearn.tree import export_graphvizimport graphvizdef create_data(): iris = load_iris() df = pd.DataFrame(iris.data, columns=iris.feature_names) df['label'] = iris.target df.columns = [ 'sepal length', 'sepal width', 'petal length', 'petal width', 'label' ] data = np.array(df.iloc[:100, [0, 1, -1]]) # print(data) return data[:, :2], data[:, -1]X, y = create_data()X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)clf = DecisionTreeClassifier()clf.fit(X_train, y_train,)print(clf.score(X_test, y_test))# 为了让下边的语句执行,首先要安装graphviz,官网下载exe或者zip都行,这种方式要配置环境变量# pycharm安装失败时,用命令行安装pip install graphviz -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com。这种方式直接安装在了Anaconda下就不用配置环境变量了# 成功后,在命令行运行dot -v看一下是否成功安装# 成功后,现在命令行运行dot - c。执行完后,在运行程序即可。tree_pic = export_graphviz(clf, out_file="mytree.pdf") # 生成了画树的graphviz语句with open('mytree.pdf') as f: dot_graph = f.read() # 我们将画树的语句取出来graph = graphviz.Source(dot_graph) # 将这些语句存储graph.view() # 画出来结果:
0.9666666666666667
最初生成的mytree.pdf文件:

通过dot画出来的文件(自动命名成Source.gv.pdf):

上述内容就是python中怎么模拟决策树,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。
特征
节点
信息
最大
数据
类别
经验
青年
条件
标记
结果
生成
决策
信贷
情况
语句
阈值
递归
成功
个数
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
中国姓氏名字数据库
如何取消宽带代理服务器勾选
服务器pc3l是什么
fbi调查中国网络安全事件
乐亭数据网络技术诚信合作
一起学习网络安全小妙招
农业银行软件开发中心 成都
数据库是结构化的数据集合对吗
电子科技大学互联网创新创业
北京火龙果网络技术有限公司
烟草生产 网络安全
总结计算机网络技术笔试题
无锡常见软件开发方法
盐城网络安全事故
湘潭配方管理软件开发
医院软件开发工程师考试
威海软件开发
我的世界吃鸡服务器电脑
移动软件开发的大专学校
至强服务器报价
服务器交换机怎么设置光口和电口
国家电网有限公司网络安全部
数据库章节名称数据类型
30岁学网络安全运维
网络安全基础数据加密
欣盟自控数据库密码是
tomcat运行达梦数据库项目
网络技术开发包含什么
简述网络安全的挑战
node服务器配置