python决策树剪枝_决策树剪枝问题&python代码

决策树在生长过程中有可能长得过于茂盛,对训练集学习的很好,但对新的数据集的预测效果不好,即过拟合,此时生成的模型泛化能力较差。因此,我们需要对决策树进行剪枝,使得生成的模型具有较强的泛化能力。

为了检测剪枝前后模型的分类效果是否提升,我们需要将全部数据集划分为三个子集:训练集、验证集(剪枝集)、测试集。

训练集:用于生成决策树。

验证集:用于检验剪枝前后模型分类效果变动情况。

测试集:当模型完全确定后,用于检验模型在新样本数据上的分类效果。

决策树剪枝的主要方法包括两大类:后剪枝、预剪枝。

1.后剪枝

指先允许决策树自由生长,然后对其进行修剪。主要剪枝思想是将“子树”替换为叶子节点,即取消某个内部节点将其变为叶子节点,观察模型的分类效果是否有提升。

(1)后剪枝的优点:

后剪枝比预剪枝会保留更多的节点,不容易出现“欠拟合”问题。

(2)后剪枝的缺点:

因为是先生成树,再对树进行剪枝,因此,时间开销比预剪枝大。

(3)常用的是,先构建一棵决策树,然后根据特征重要性,筛选出重要的特征,再构建新的决策树。

具体操作,参见我的另一篇文章:Cara:随机森林Python实战​zhuanlan.zhihu.com

(4)一些后剪枝算法包括:REP(Reduced-Error Pruning)、PEP(Pesimistic-Error Pruning)、CCP(cost complexity pruning)。

①REP(Reduced-Error Pruning):自下而上剪枝,即将叶子节点合并到上位节点中去。

现有一个生成好的决策树如下,共1~10个节点。

Step 1: 尝试将叶子节点4删掉,则叶节点8、9、10合并为一个节点(命名为节点11),节点11的类别我们用节点8、9、10包含的样本中数量最多的那个类来确定(大多数原则来确定),然后,节点11与节点5一起成为节点2的叶子节点。然后,测试剪枝后的决策树在验证集上的表现,若分类效果(可以用分类的准确率度量)更好或者效果没有变差,则将节点4删掉(如下图),若表现不好则保留原树的形状。剪枝后效果如下:

STEP2:同理,尝试将节点3删掉,则叶子节点6和7会成为合并为一个节点(命名为节点12),节点12会成为节点1的叶子节点,然后,测试剪枝后的决策树在验证集上的表现。若分类效果更好或者效果没有变差,则将节点3删掉。

以此类推,形成最简决策树。

评价:REP是最简单的后剪枝方法之一,不过由于需要使用验证集,如果本身数据量较少,剪枝效果也不会很好。

②PEP(Pesimistic Error Pruning):没看懂,不敢说话……

③CCP(Cost Complexity Pruning):原理没看很明白……下面put一个github上比较流行的实操方法。

CCP思想已经被写入python的sklearn库下的tree模块的DecisionTreeClassifier类,在对类进行实例化时可以根据如下提示进行相关设置,重点中的重点在于如何选择一个较优的ccp_alpha值。

小例子:使用sklearn库中自带的数据集breast_cancer进行决策树剪枝演示。

#导入工程

from sklearn.tree import DecisionTreeClassifier

from sklearn.model_selection import train_test_split

from sklearn.datasets import load_breast_cancer

import matplotlib as plt

from sklearn.metrics import accuracy_score

#数据拆分为特征集和标签列

X,y = load_breast_cancer(return_X_y=True)

#数据拆分为训练集和测试集

X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=8)

#实例化决策树,参数全部用默认值

clf = DecisionTreeClassifier(random_state=0)#默认是基于Gini值生成决策树

#拟合样本数据

clf.fit(X_train,y_train)

#对测试集进行预测

pred = clf.predict(X_test)

#对预测结果进行打分

print(accuracy_score(y_test,pred))

#结果:0.9090909090909091

#绘制出生成的决策树

plt.rcParams['savefig.dpi'] = 200 #图片像素

plt.rcParams['figure.dpi'] = 200 #分辨率

# 默认的像素:[6.0,4.0],分辨率为100,图片尺寸为 600*400

from sklearn import tree

tree.plot_tree(clf,filled=True)

不剪枝时,采用默认参数生成的决策树,共8层,因此,树的深度为8:

#以下代码主要目的是找到较优的ccp_alpha,然后就可以在DecisionTreeClassifier类实例化的时候设置ccp_alpha参数为找到的ccp_alpha值。

path = clf.cost_complexity_pruning_path(X_train, y_train)

ccp_alphas, impurities = path.ccp_alphas, path.impurities

print(ccp_alphas)

'''

[0. 0.00232752 0.00375587 0.00375587 0.00391236 0.00438185

0.00629975 0.00730308 0.00946792 0.01198161 0.01788007 0.04055896

0.31844825]

'''

clfs = []

for ccp_alpha in ccp_alphas:

clf = DecisionTreeClassifier(random_state=0, ccp_alpha=ccp_alpha)

clf.fit(X_train, y_train)

clfs.append(clf)

print("Number of nodes in the last tree is: {} with ccp_alpha: {}".format(

clfs[-1].tree_.node_count, ccp_alphas[-1]))

#返回:Number of nodes in the last tree is: 1 with ccp_alpha: 0.3184482456829032

#绘制不同ccp_alpha取值下,clf在训练样本和测试样本上的精确度

train_scores = [clf.score(X_train, y_train) for clf in clfs]

test_scores = [clf.score(X_test, y_test) for clf in clfs]

from matplotlib import pyplot

plt.rcParams['savefig.dpi'] = 80 #图片像素

plt.rcParams['figure.dpi'] = 200 #分辨率

# 默认的像素:[6.0,4.0],分辨率为100,图片尺寸为 600*400

fig, ax = pyplot.subplots()

ax.set_xlabel("alpha")

ax.set_ylabel("accuracy")

ax.set_title("Accuracy vs alpha for training and testing sets")

ax.plot(ccp_alphas, train_scores, marker='o', label="train",

drawstyle="steps-post")

ax.plot(ccp_alphas, test_scores, marker='o', label="test",

drawstyle="steps-post")

ax.legend()

pyplot.show()

不同ccp_alpha取值,对应的clf的测试集正确率和训练集正确率如同所示:

根据该图可以发现,当alpha介于0.05~0.3之间时,对应的决策树分类器在测试集的正确率和训练集的正确率均比较高,正确率稳定在0.90~0.95之间。

#重新生成决策树,根据ccp_alpha进行剪枝

clf2 = DecisionTreeClassifier(random_state=0, ccp_alpha=0.006)

clf2.fit(X_train,y_train)

pred2=clf2.predict(X_test)

print(accuracy_score(y_test, pred2))

#结果:0.916083916083916

#绘制剪枝后的决策树

tree.plot_tree(clf2,filled=True)

剪枝后的树如下,共6层:

2.预剪枝

指在决策树生成之前,就设置一些参数来限制决策树的生长,如设定树的最大深度、叶子节点最小数量等。

在python中,sklearn库下的tree模块,可以加载DecisionTreeClassifier类,该类在实例化时可以设置以下参数进行预剪枝:

预剪枝由于过多的人为设定,可能导致生成的模型存在“欠拟合”问题,即生成的模型对数据的反映不够,模型对训练集的预测效果不佳,对测试集的预测效果也不佳。

(1)设定树的最大深度

该方法会在起初设置一个计数器,这里命名为counter,并设置初始值为0。在决策树生长过程中,会重点关注两个问题:①数据集是否pure了?即y标签是否只有1个类别。②决策树是否达到设定的最大深度。

如果数据集pure,则将数据集设为叶子节点。

如果数据集不pure,就会接着问树是否达到最大深度。

如果数据集不pure且树没有达到最大深度,就会从多个属性中根据某种指标(信息增益、Gini指标)选择出最佳划分节点,并对counter加1。然后再判断划分后的子集分别是否pure,以此类推。

如果数据集不pure,但是树达到最大深度,这时,就会强制将数据集设为叶子节点,代价就是生成的树存在“欠拟合”问题。

(2)设定叶子节点最小数量

参考:https://www.youtube.com/watch?v=SLOyyFHbiqo​www.youtube.com【机器学习】算法原理详细推导与实现(七):决策树算法 - TTyb - 博客园​www.cnblogs.com

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值