机器学习——决策树(四)后剪枝

观前提示 :这是本人决策树相关的第四篇博文,前3篇的内容如下:

1、建造训练集的决策树【完成结点类编写和建树过程】

2、用验证集评估模型、选出泛化较好的数据划分方式训练模型

3、预剪枝

读者可根据需要从上方《机器学习》专栏中查阅对应文章

第四章是后剪枝的内容,用到了许多前文相关的代码

完整代码 都被集成到了colab的notebook当中,读者可以直接 运行。

指路:DrawPixel/decisionTree.ipynb at main · ndsoi/DrawPixel (github.com)

目录

1、后剪枝的理论部分

2、编程实践

1、划分训练集和验证集

​编辑2、生成训练集完整的决策树

3、收集所有的非叶结点

4、处理分支结点:划分or剪枝?


1、后剪枝的理论部分

作用:减少分支,提高模型的泛化能力

对比预剪枝:优势:防止训练不充分导致欠拟合;劣势:开销较大、时间较长

算法过程:

  1. 后剪枝先从训练集生成一棵完整决策树
  2. 从完整的决策树底层的非叶子结点出发,由下至上,对每一个分支结点(非叶子结点)考虑:
    1. 如果划分:验证集精度=a
    2. 如果不划分,令当前结点的label=1,class=max,验证集精度=b 比较a和b的大小:
      1. 如果a>b 则划分,令当前结点label = 0
      2. 如果a<=b 则不划分,令当前结点的label=1

2、编程实践

1、划分训练集和验证集

python 复制代码
train_data = D[0:3]+D[5:7]+[D[9]]+D[13:]
val_data = D[3:5]+[D[7]]+D[8:13]
print("训练集")
show(train_data)
print("验证集")
show(val_data)

2、生成训练集完整的决策树

python 复制代码
root_v5 = TreeGenerate(train_data,Attr)
drawTree(root_v5)

drawTree显示:

手绘更明确:

3、收集所有的非叶结点

python 复制代码
def collectAllNoLeaf(root):
  NoLeafQ = queue.Queue()
  NoLeafS = []
  if root.label == 1:
    # 根结点本身是叶子,那就没有讨论空间了
    print(f"根结点本身是叶子")
    return NoLeafS
  
  NoLeafQ.put(root)
  NoLeafS.append(root)

  while NoLeafQ.empty() == False:
    # 当前层的结点数目
    n = NoLeafQ.qsize()
    for i in range(n):
      cur = NoLeafQ.get()
      # cur结点的子结点的数目
      for value,node in cur.subDs.items():
        if node.label != 1:
          # 子结点不是叶子结点
          
          NoLeafS.append(node)
          NoLeafQ.put(node)
  return NoLeafS
NoLeafnodes = collectAllNoLeaf(root_v5) 

按层遍历了决策树,所有越底层的分支结点越在NoLeafnodes列表的后面

4、处理分支结点:划分or剪枝?

python 复制代码
# 倒叙遍历
def train_v5(NoLeafnodes,root,val_data):
  n = len(NoLeafnodes)

  for i in range(n):

    cur = NoLeafnodes[n-1-i]
    # 沿用predict_v4 精度计算方法
    res_o,acc_o = predict_v4(root,val_data)
    print(f"划分的预测序列{res_o}")
    # 假如当前不划分
    cur.label = 1
    cur.Class = cur.max
    # 计算精度
    res_d,acc_d = predict_v4(root,val_data)
    print(f"不划分的预测序列{res_d}")
    if acc_o > acc_d:
      # 划分的精度更高
      print(f"划分的精度更高,划分了以后{acc_o}\t不划分{acc_d}")
      cur.label = 0
    else:
      print(f"不划分的精度更高,划分了以后{acc_o}\t不划分{acc_d}")
  return root

r = train_v5(NoLeafnodes,root_v5,val_data)
drawTree(r)

结果:

剪枝后的决策树为:

从最后打印的信息可以看到,虽然剪枝后决策树的分类精度还是0.875 ,但模型得到了简化

相关推荐
Work(沉淀版)2 小时前
DAY 40
人工智能·深度学习·机器学习
A林玖6 小时前
【机器学习】主成分分析 (PCA)
人工智能·机器学习
molunnnn6 小时前
DAY 15 复习日
机器学习
pen-ai7 小时前
【统计方法】基础分类器: logistic, knn, svm, lda
算法·机器学习·支持向量机
FrankHuang8888 小时前
使用高斯朴素贝叶斯算法对鸢尾花数据集进行分类
算法·机器学习·ai·分类
阔跃生物8 小时前
Nature Methods | OmiCLIP:整合组织病理学与空间转录组学的AI模型
人工智能·深度学习·机器学习
武子康8 小时前
AI炼丹日志-28 - Audiblez 将你的电子书epub转换为音频mp3 做有声书
人工智能·爬虫·gpt·算法·机器学习·ai·音视频
Morpheon9 小时前
从线性代数到线性回归——机器学习视角
线性代数·机器学习·数学建模·线性回归
Blossom.11810 小时前
量子通信:从科幻走向现实的未来通信技术
人工智能·深度学习·目标检测·机器学习·计算机视觉·语音识别·量子计算
Espresso Macchiato10 小时前
Leetcode 3568. Minimum Moves to Clean the Classroom
剪枝·广度优先遍历·leetcode medium·堆排·leetcode周赛452·leetcode 3568