自己搭建一棵决策树【长文预警】
忙了一个周末就写到了“构建决策树”这一步,还没有考虑划分测试集、验证集、“缺失值、连续值”,预剪枝、后剪枝的部分,后面再补吧(挖坑)
第二节内容:验证集划分\k折交叉检验 机器学习——编程从零实现决策树【二】-优快云博客
目录
完整的代码指路
DrawPixel/decisionTree.ipynb at main · ndsoi/DrawPixel (github.com)
1、信息
1)基本算法过程
2)信息熵和信息增益的计算方式
2、做点假设,简化运算
① 为了选择最优的属性进行划分,我们需要计算信息增益,而计算信息增益需要用到信息:
1、选取的属性attr有多少种取值?
(用西瓜分类的例子,考虑属性”纹理“,就有3种取值——”清晰“、”稍糊“和”模糊“)
2、每种取值有哪些数据?这些数据中有多少是A类别的,又有多少是B类别的..?
比如对原始数据集考虑”纹理=清晰“的数据,那么有7个是好瓜,有2个是坏瓜
② 计算完信息增益之后,我们选信息增益最大的属性,按照这个属性划分数据集,生成子结点
注意这里的划分数据集,事实上我们在完成①.2问题的时候就已经“划分了”一次数据集,只是我们没有记录下来,类似这样的“冗余”计算有很多,为了尽量减少“重复”计算,我重规划算法的步骤如下:
1、设总共有class_num个类别,假设我们初始化结点node的时候就知道了这个数据集的如下信息:
数据集 self.data
属性集 self.attr
该数据集内样本数量最多的类别 self.max
该数据集内每个类别的样本数量 self.cal_class 是一个列表,每一个元素是|Dv|
2、基于假设1:
计算Ent(D):
def Ent(D,cal_class):
sum = len(D) # 样本总数
# 求占比
re = 0
for k in cal_class:
pk_class = k/sum
if pk_class != 0:
re -= pk_class* math.log(pk_class,2)
return re
3、拆解算法过程
0)结点类
class Node():
def __init__(self,D,A,max,cal_class,class_num):
self.data = D
self.attr = A
self.class_num = class_num
self.cal_class = cal_class
self.max = max
self.label = 0 # 0表示非叶结点 1表示叶结点
self.Class = 0 # 默认一个
self.flag = "init"
1)同类样本判断
若要判断D中的样本是否同属于一个类别:只需要判断self.max的数量是否等于class_num
def isSameClass(self):
if self.cal_class[self.max] == len(self.data):
return True
return False
2)数据集能否再拆解
若D中样本不属于同一类,那么接下来要看D中的样本是否还能再分解:
def isNoAttr(self