机器学习——决策树(手动代码)

news/2024/10/23 4:49:20/

1. 构造决策树

1.1 构造思路

首先,构造决策树的过程如下:
① 按特征划分群体,并计算衡量指标(信息增益、信息增益率、基尼系数)
② 选取衡量指标表现最好的特征,对群体进行划分,并构建第一层树
③ 重复①②步骤,当特征全被分完,或是类别唯一确定后,停止划分(还可以是其他条件)

1.2 构造困惑

在思考构造决策树的时候,我忽然有个问题:同一个层级的不同群体,需要继续向下划分出各自的子群体时,是按相同的特征划分,还是按照各自的条件熵最大那个特征来分?
在这里插入图片描述

尝试想了想同一层级的群体按相同特征,继续向下划分时,这个衡量的指标就要层层嵌套为条件熵的加权平均值。。。而且划分的层级越多,例如4个层级,那衡量的指标就要变为条件熵的加权平均条件熵的加权平均条件熵的加权平均条件熵…、、
尽可能地让整颗决策树的划分更纯
forget about it
套娃的路子,可以走,但没这必要
还是直接根据“贪心算法”的思路,走好这一步,再走好下一步,每一步都走好了,那总体也是好的
【在一定情况下,但有时候贪心算法并不能达到全局最优,无所谓,至少比乱走的好】

1.3 程序设计的难点

  • 用什么数据结构来设计决策树?存储划分的群体?

    👉选取二叉树,显然是不行的,因为在决策树中特征值是应分尽分,不同特征有不同数量的特征值,因此二叉树只有左右两个叉,不适用
    👉选取字典,目测应该是可以的,但考虑要迭代递归去逐级划分,可以考虑多叉树

多叉树这个东西呢…属实是自己乱来了,但实践后发现其实还挺好用的

我并不是一开始就把所有的结构都想的十分清楚明白,只是大概画了个草图设计了一下,纪念一下我的草图
鬼都看不懂的草图,我自己现在也不知道当时是怎么想的
在这里插入图片描述

实际最后设计出的多叉树结构大致如下
在这里插入图片描述

1.4 手动代码

import math
import numpy as np
import pandas as pd
# 获取所需数据
datas = pd.read_excel('./datas1.xlsx')
important_features = ['推荐类型','推荐分值', '专业度','回复速度']
datas_1 = datas[important_features]
Y = datas_1['推荐类型']
X = datas_1.drop('推荐类型',axis=1)
Y_feature = "推荐类型"# 构建一个树节点
class Node_1():def __init__(self,value):self.value = valueself.select_feat = Noneself.sons = {}
# 根据节点,构建一个树
class Tree():def __init__(self):self.root = Nonedef get_value_1(self,datas_arg,node_arg=None):# 明确当前节点数据node = node_argif self.root == None:node = Node_1(datas_arg)self.root = node# 明确当前节点的划分特征、子节点们: 计算各特征划分后的信息增益,并选出信息增益最大的特征gain_dicts = {}for i in X.columns:groups = datas_arg.groupby(i)groups = [groups.get_group(j) for j in set(datas_arg[i])]if len(groups) > 1:  # 特征可分gain_dicts[i] = self.get_gain(datas_arg,groups,Y_feature)# 明确停止划分的条件,即停止迭代的条件:无可划分的属性,或是最大的条件熵为0if  (not gain_dicts) or max(gain_dicts.values()) == 0:returnselect_feat = max(gain_dicts,key=lambda x:gain_dicts[x])node.select_feat = select_featgroup_feat = datas_arg.groupby(select_feat)for j in set(datas_arg[select_feat]):node_son_value = group_feat.get_group(j)node_son = Node_1(node_son_value)node.sons[j] = node_sonfor key,node_single in node.sons.items():self.get_value_1(node_single.value,node_single)# 获取熵def get_ent(self,datas,feature):p_values = datas[feature].value_counts(normalize=True)p_updown = 1/p_valuesent = (p_values*(p_updown).apply(np.log2)).sum()return ent# 获取条件熵def get_condition_ent(self,datas_list,feature):proportions = [len(i) for i in datas_list]proportions = [i/sum(proportions) for i in proportions]ents = [self.get_ent(i,feature) for i in datas_list]condition_ent = np.multiply(ents,proportions).sum()return condition_ent# 获取信息增益def get_gain(self,datas_all,datas_group,feature):condition_ent = self.get_condition_ent(datas_group,feature)ent_all = self.get_ent(datas_all,feature)gain = ent_all - condition_entreturn gain# 探访决策树,并进行预测分类def predict(self,data,root):if not root.select_feat:p_values = root.value[Y_feature].value_counts(normalize=True)Y_predict.append(p_values.idxmax())returnfeat = root.select_featnext_node = root.sons[data[feat]]self.predict(data,next_node)def pre_print(self, root):if root is None:returnprint(root.select_feat)print(root.value)for key,node_son in root.sons.items():self.pre_print(node_son)a = Tree()
a.get_value_1(datas_1)
Y_predict = []
def func(data):a.predict(data,a.root)datas_1.apply(func,axis=1)
accurency = sum(Y_predict==Y)/len(Y)
print(f"分类准确率:{accurency*100}%")

在这里插入图片描述
总体表现还不错,有推荐分值的情况下,推荐类型会是百分百的正确
没有推荐分值的情况下,推荐类型勉强还可以【跟朴素贝叶斯差不多】

2. 剪枝

没做剪枝…懒得

当即使分到的决策树,没有达到分类最纯粹的状态也没关系,可以直接按叶子节点的类别概率来预测分类

但是不剪枝会不会对条件熵的计算有影响呢?

这倒是没考量过,maybe,无所谓啦
以后遇到需要真的剪枝了,再剪吧


http://www.ppmy.cn/news/659666.html

相关文章

将两页A4 pdf文档合并到一页A4页面上打印的方法

在实验室打印论文, 直接把pdf打印感觉比较浪费, 许多白边框都没有有效利用, 而且打印出来的页数很多, 显得不紧凑, 而且多而繁杂。 于是想要把pdf页面合并拼接打印, 比如: “将两页A4 pdf文档合…

A3的PDF试卷怎么对半拆分成A4打印?

有时在网上下载的PDF格式的电子试卷是A3版的,但是一般的打印机或打印纸都是A4规格的,那么如何能将A3的PDF试卷改成A4后再打印呢? 分两种情况来解决,第一种将A3缩放到A4后打印;第二种每一页拆分成2页后再打印&#xff…

php针式打印机打多张,如何将多页内容打印在一张A4纸上

将多页内容打印在一张A4纸上的实现方法:首先打开所需要更改的EXCEL表格,点击界面左上角的“WPS表格”按键;然后在上方工具栏找到“页面设置”选项并左键点击;最后设置整个工作表打印在一页并点击右下角确定。 如果是word&#xff…

itextPdf~将PDF页面大小转为A4格式

本文章向大家介绍将PDF页面大小转为A4格式---itextPdf实现,主要包括将PDF页面大小转为A4格式---itextPdf实现使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。 将PDF页面大小转为A4格式&…

横向的Excel输出为pdf自动分成两页怎么办?不分页,铺满整张纸的方法来了

我们工作中有时候会需要把Excel转换成pdf,一般我们用WPS的“输出为pdf”功能就可以转了。但是有些横向的Excel转换的时候,会自动分成两页,这并不是我们想要的效果。怎么才能不分成两页呢? 首先我们有一个Excel: 使用…

如何利用计算机打印较大的字,如何在一张A4纸上打印一个超大字?

是不是很想打印超大字?要是硬件上去了,就什么话也不用说了,可惜的是,手中只有一个A4的打印机。怎么办?还是有办法的,用Microsoft Office 2003就可以。 我由于学校工作的原因,打印机只能打A4的纸,有时又想打超大字,不得不用现有的条件来做。于是就从Microsoft Office 2…

如何在一张A4纸上合并打印多张发票

在处理日常文档时,我们经常需要合并多个PDF文件,然后在1张A4纸上多页打印。最常见的就是打印发票 现在发票大都是电子发票,但是报销时一般要求一张A4纸打印两张发票,以便节省纸张。但每次操作都很麻烦,这次推荐大家一…

打印小册子(一张A4纸4页内容)步骤分享

1、打开word格式说明书,另存为pdf格式(如果文件是pdf格式忽略步骤1) 2、用wps打开pdf文件 3、打印→打印方式:小册子→小册子子集:仅正面→装订:左→打印 4、等待打印→打印完成后→放纸(打印出…