剪枝理论学习请参考如下网址:机器学习算法——决策树4(剪枝处理)_Vicky_xiduoduo的博客-CSDN博客_剪枝 机器学习
不管是预剪枝还是后剪枝,都需要对决策树进行“泛化能力”的评估。本节的实例讲解采用留出法评估决策树的泛化能力。故需要预留一部分数据用作“训练集”,一部分用作“验证集/测试集”。将西瓜2.0数据集随机划分成两部分,如下表所示。
色泽 | 根蒂 | 敲声 | 纹理 | 脐部 | 触感 | 好瓜 |
青绿 | 蜷缩 | 浊响 | 清晰 | 凹陷 | 硬滑 | 是 |
乌黑 | 蜷缩 | 沉闷 | 清晰 | 凹陷 | 硬滑 | 是 |
乌黑 | 蜷缩 | 浊响 | 清晰 | 凹陷 | 硬滑 | 是 |
青绿 | 稍蜷 | 浊响 | 清晰 | 稍凹 | 软粘 | 是 |
乌黑 | 稍蜷 | 浊响 | 稍糊 | 稍凹 | 软粘 | 是 |
青绿 | 硬挺 | 清脆 | 清晰 | 平坦 | 软粘 | 否 |
浅白 | 稍蜷 | 沉闷 | 稍糊 | 凹陷 | 硬滑 | 否 |
乌黑 | 稍蜷 | 浊响 | 清晰 | 稍凹 | 软粘 | 否 |
浅白 | 蜷缩 | 浊响 | 模糊 | 平坦 | 硬滑 | 否 |
青绿 | 蜷缩 | 沉闷 | 稍糊 | 稍凹 | 硬滑 | 否 |
色泽 | 根蒂 | 敲声 | 纹理 | 脐部 | 触感 | 好瓜 |
青绿 | 蜷缩 | 沉闷 | 清晰 | 凹陷 | 硬滑 | 是 |
浅白 | 蜷缩 | 浊响 | 清晰 | 凹陷 | 硬滑 | 是 |
乌黑 | 稍蜷 | 浊响 | 清晰 | 稍凹 | 硬滑 | 是 |
乌黑 | 稍蜷 | 沉闷 | 稍糊 | 稍凹 | 硬滑 | 否 |
浅白 | 硬挺 | 清脆 | 模糊 | 平坦 | 硬滑 | 否 |
浅白 | 蜷缩 | 浊响 | 模糊 | 平坦 | 软粘 | 否 |
青绿 | 稍蜷 | 浊响 | 稍糊 | 凹陷 | 硬滑 | 否 |
本节先讲预剪枝。
以ID3算法生成决策树,生成的决策树如图1所示(实现代码参考:机器学习算法——决策树6(划分属性选择实例)_Vicky_xiduoduo的博客-CSDN博客)。
图1 基于表1生成的未剪枝决策树
基于图1,我们会选取“脐部”来对训练集进行划分,并产生三个分支,即平坦、凹陷、稍凹。
是否应该进行这个划分?预剪枝需要对划分前后的性能进行估计。
在划分之前,所有样例集中在根节点,若不进行划分,则根据决策树算法,该节点将被标记为叶节点,其类别标记为训练样例数最多的类别,假设这个叶节点标记为“好瓜”,那么看验证集表2,只有{4,5,8}分类正确,{9,11,12,13}分类错误,则验证集的精度为
用“脐部”划分之后,如图2所示。节点②包含的编号为{1,2,3,14},③包含的编号为{6,7,15,17}、④包含的编号为{10,16}.因此,三个节点被标记为{好瓜,好瓜,坏瓜}。此时,验证集中{4,5,8,11,12}的样例被分类正确。验证集精度为,于是用“脐部”进行划分得以确定。
根据构成的决策树的第二层进行划分决策:
然后决策树对“色泽”进行划分,编号{5}的验证集样本分类结果由正确转为错误,使得验证集精度为,于是预剪枝策略将禁止节点“色泽”划分。
然后对“根蒂”进行划分,划分后验证集精度仍为71.4%,不能提升精度,所以禁止节点“根蒂”划分。
对“坏瓜”,其所训练样例已属于同一类,不再进行划分。
综上,这是一棵仅有一层划分的决策树,亦称为“决策树桩”。预剪枝决策树可能会带来“欠拟合”风险。
图2 生成的预剪枝决策树
预剪枝代码实现过程中其实就是调参过程。
在sklearn中,实际就是调整以下几个训练参数:
min_samples_leaf :叶子节点最小样本数。
min_samples_split :节点分枝最小样本个数
max_depth :树分枝的最大深度
min_weight_fraction_leaf :叶子节点最小权重和
min_impurity_decrease :节点分枝最小纯度增长量
max_leaf_nodes :最大叶子节点数
一般来说,只调这三个 :max_depth,min_samples_leaf,min_samples_split
根据调参,预剪枝决策树采用Max_depth=1,min_samples_leaf=3。
用sklearn实现,代码如下:
import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.tree import DecisionTreeClassifier
from sklearn.tree import export_graphviz
import graphviz
import matplotlib.pyplot as plt
import numpy as np
train_data = pd.read_csv('D:/Machine_Learning/西瓜数据集2.0划分出的训练集.csv', encoding='GBK')
test_data = pd.read_csv('D:/Machine_Learning/西瓜数据集2.0划分出的验证集.csv', encoding='GBK')
test = []
#进行ID3拟合
#创建LabelEncodet()对象,用于序列化
label=LabelEncoder()
for col in train_data[train_data.columns[:-1]]:
train_data[col] = label.fit_transform(train_data[col])
label_test=LabelEncoder()
for col in test_data[test_data.columns[:-1]]:
test_data[col] = label.fit_transform((test_data[col]))
#使用id3构建决策树
id3 = DecisionTreeClassifier(criterion='entropy',
random_state=30,
max_depth=1,
min_samples_leaf=3
)
id3 = id3.fit(train_data.iloc[:, :-1].values.tolist(), train_data.iloc[:, -1].values)
score_test = float(id3.score(test_data.iloc[:, :-1].values.tolist(),test_data.iloc[:, -1].values))
print(score_test)#精确度
#画出决策树
labels = ['色泽', '根蒂', '敲击', '纹理', '脐部', '触感']
dot_data = export_graphviz(id3,
feature_names=labels,
class_names=['好瓜', '坏瓜'],
filled=True,
rounded=True,
fontname="Microsoft YaHei")
graph = graphviz.Source(dot_data)
graph.render("tree5")
得到的图形如下: