在机器学习中,决策树是一种常用的分类和回归算法。然而,决策树容易过拟合,导致模型在训练集上表现很好,但在未知数据上泛化能力差。为了防止这种情况,可以采用剪枝技术来控制决策树的复杂度。本文将介绍如何通过调整成本复杂性参数(ccp_alpha)来实现决策树的剪枝,并展示不同参数值对模型性能的影响。
成本复杂性剪枝是一种常用的决策树剪枝方法。它通过递归地找到最“弱”的节点来进行剪枝,这个“弱”节点由一个有效的alpha值来表征。在scikit-learn库中,可以通过DecisionTreeClassifier.cost_complexity_pruning_path
方法来获取在剪枝过程中每一步的有效alpha值和对应的叶子节点的总不纯度。随着alpha值的增加,剪枝的程度也会增加,从而使得叶子节点的总不纯度增加。
首先,使用乳腺癌数据集来训练一个决策树模型。然后,通过cost_complexity_pruning_path
方法获取不同alpha值下叶子节点的总不纯度,并绘制出总不纯度与有效alpha值的关系图。从图中可以看出,随着alpha值的增加,更多的树节点被剪枝,从而使得叶子节点的总不纯度增加。
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
# 加载数据集
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
# 训练决策树模型并获取剪枝路径
clf = DecisionTreeClassifier(random_state=0)
path = clf.cost_complexity_pruning_path(X_train, y_train)
ccp_alphas, impurities = path.ccp_alphas, path.impurities
接下来,使用不同的有效alpha值来训练决策树模型,并记录下每个模型的节点数量和树的深度。通过绘制节点数量和树深度与alpha值的关系图,可以观察到随着alpha值的增加,树的节点数量和深度都在减少。
# 训练不同alpha值下的决策树模型
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)
# 计算每个模型的节点数量和树深度
node_counts = [clf.tree_.node_count for clf in clfs]
depth = [clf.tree_.max_depth for clf in clfs]
# 绘制节点数量和树深度与alpha值的关系图
fig, ax = plt.subplots(2, 1)
ax[0].plot(ccp_alphas, node_counts, marker="o", drawstyle="steps-post")
ax[0].set_xlabel("alpha")
ax[0].set_ylabel("number of nodes")
ax[0].set_title("Number of nodes vs alpha")
ax[1].plot(ccp_alphas, depth, marker="o", drawstyle="steps-post")
ax[1].set_xlabel("alpha")
ax[1].set_ylabel("depth of tree")
ax[1].set_title("Depth vs alpha")
fig.tight_layout()
plt.show()
最后,比较了不同alpha值下模型在训练集和测试集上的准确率。当alpha值设置为0时,模型在训练集上过拟合,准确率达到100%,但在测试集上的准确率只有88%。随着alpha值的增加,更多的树节点被剪枝,从而使得模型在测试集上的泛化能力得到提高。在这个例子中,当alpha值设置为0.015时,测试集上的准确率达到最大值。
# 计算不同alpha值下模型在训练集和测试集上的准确率
train_scores = [clf.score(X_train, y_train) for clf in clfs]
test_scores = [clf.score(X_test, y_test) for clf in clfs]
# 绘制准确率与alpha值的关系图
fig, ax = plt.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()
plt.show()