一、实验目的
深入理解决策树、预剪枝和后剪枝的算法原理,能够使用Python语言实现带有预剪枝和后剪枝的决策树算法C4.5算法的训练与测试,并且使用五折交叉验证算法进行模型训练与评估。
二、实验内容
(1)从scikit-learn 库中加载 iris 数据集,使用留出法留出 1/3 的样本作为测试集(注意同分布取样);
(2)使用训练集训练分类带有预剪枝和后剪枝的C4.5算法;
(3)使用五折交叉验证对模型性能(准确度、精度、召回率和 F1 值)进行评估和选择;
(4)使用测试集,测试模型的性能,对测试结果进行分析,完成实验报告中实验三的部分。
三、算法步骤、代码、及结果
- 算法伪代码
输入:训练数据集 D,特征集合 A,剪枝参数(如最小样本数)。
输出:决策树模型。
递归生成树:
若 D 全属于同一类别,生成叶节点。
若 A 为空或无法进一步分裂,生成叶节点。
按照信息增益比(Information Gain Ratio)选择分裂属性。
根据分裂属性构建子节点,递归调用。
预剪枝:
在每次分裂时,计算信息增益,若低于设定阈值则停止分裂。
后剪枝:
完全生成树后,移除对测试集无显著贡献的子树。
- 算法主要代码
完整源代码\调用库方法(函数参数说明)
import numpy as np
from sklearn.model_selection import train_test_split, cross_validate
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
from sklearn.metrics import make_scorer, precision_score, recall_score, f1_score,accuracy_score
data = load_iris()
X = data.data
y = data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, stratify=y)
clf = DecisionTreeClassifier(criterion='entropy',max_depth=5,min_samples_split=4,min_samples_leaf=2,random_state=42)
path = clf.cost_complexity_pruning_path(X_train, y_train)
ccp_alphas = path.ccp_alphas
impurity = path.impurities
best_clf = None
best_f1 = 0
for ccp_alpha in ccp_alphas:
clf_temp = DecisionTreeClassifier(criterion='entropy',max_depth=5,min_samples_split=4,min_samples_leaf=2,ccp_alpha=ccp_alpha)
clf_temp.fit(X_train, y_train)
y_pred_temp = clf_temp.predict(X_train)
f1 = f1_score(y_train, y_pred_temp, average='macro')
if f1 > best_f1:
best_f1 = f1
best_clf = clf_temp
scoring = {
'accuracy': 'accuracy',
'precision': make_scorer(precision_score, average='macro'),
'recall': make_scorer(recall_score, average='macro'),
'f1': make_scorer(f1_score, average='macro')
}
cv_results = cross_validate(best_clf, X_train, y_train, cv=5, scoring=scoring)
print(f"\n交叉验证结果:")
print(f"准确率: {cv_results['test_accuracy'].mean():.4f}")
print(f"精度: {cv_results['test_precision'].mean():.4f}")
print(f"召回率: {cv_results['test_recall'].mean():.4f}")
print(f"F1值: {cv_results['test_f1'].mean():.4f}")
y_pred_test = best_clf.predict(X_test)
accuracy_test = accuracy_score(y_test, y_pred_test)
precision_test = precision_score(y_test, y_pred_test, average='macro')
recall_test = recall_score(y_test, y_pred_test, average='macro')
f1_test = f1_score(y_test, y_pred_test, average='macro')
print(f"\n测试集测试结果")
print(f"准确率: {accuracy_test:.4f}")
print(f"精度: {precision_test:.4f}")
print(f"召回率: {recall_test:.4f}")
print(f"F1值: {f1_test:.4f}")
调用的库函数
- train_test_split
来源:sklearn.model_selection
功能:按比例随机划分训练集和测试集,同时确保类别分布一致(通过 stratify 参数)。
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42, stratify=y)
参数说明:
X, y:特征数据和目标标签。
test_size=0.33:测试集占比为 1/3。
random_state=42:随机种子,用于保证结果可复现。
stratify=y:按目标标签 y 的分布进行划分,确保训练集和测试集类别分布一致。
- DecisionTreeClassifier
来源:sklearn.tree
功能:实现决策树分类器,用于训练模型并支持控制预剪枝。
pre_pruned_tree = DecisionTreeClassifier(criterion='entropy', max_depth=3, min_samples_split=10, random_state=42)
post_pruned_tree = DecisionTreeClassifier(criterion='entropy', random_state=42)
参数说明:
criterion='entropy':选择信息增益作为分裂标准。
max_depth=3:限制树的最大深度(预剪枝参数之一)。
min_samples_split=10:限制分裂所需的最小样本数(预剪枝参数之一)。
random_state=42:随机种子,保证可复现性。
- cross_validate
来源:sklearn.model_selection
功能:对模型进行五折交叉验证,评估多个性能指标。
cv_results_pre = cross_validate(pre_pruned_tree, X_train, y_train, cv=5, scoring=scoring)
参数说明:
estimator=pre_pruned_tree:要评估的模型。
X_train, y_train:训练数据。
cv=5:使用五折交叉验证。
scoring=scoring:评估指标(如准确率、精确率、召回率和 F1 值)。
- classification_report
来源:sklearn.metrics
功能:生成模型预测结果的详细分类报告,包括准确率、精确率、召回率和 F1 值。
print(classification_report(y_test, y_pred_pre))
参数说明:
y_test:真实标签。
y_pred_pre:模型预测结果。
- 训练结果截图(包括:准确率、精度(查准率)、召回率(查全率)、F1)
四、实验结果分析
- 测试结果截图(包括:准确率、精度(查准率)、召回率(查全率)、F1)
- 对比分析
从五折交叉验证和测试集的结果来看,模型在交叉验证中的表现较好,准确率、精度、召回率和F1值均较高,分别为0.9600、0.9685、0.9603和0.9605。相比之下,测试集的结果有所下降,准确率、精度、召回率和F1值分别为0.9400、0.9400、0.9400和0.9394。这表明,尽管模型在训练数据上表现良好,但在实际测试数据上的泛化能力略有下降,可能是由于训练集和测试集的数据分布存在差异,导致模型在未见过的数据上性能稍弱。
浙公网安备 33010602011771号