24.12.06
实验三:C4.5(带有预剪枝和后剪枝)算法实现与测试
一、实验目的
深入理解决策树、预剪枝和后剪枝的算法原理,能够使用Python语言实现带有预剪枝 和后剪枝的决策树算法C4.5算法的训练与测试,并且使用五折交叉验证算法进行模型训练 与评估。
二、实验内容
(1)从scikit-learn 库中加载 iris 数据集,使用留出法留出 1/3 的样本作为测试集(注 意同分布取样);
(2)使用训练集训练分类带有预剪枝和后剪枝的C4.5算法;
(3)使用五折交叉验证对模型性能(准确度、精度、召回率和 F1 值)进行评估和选 择;
(4)使用测试集,测试模型的性能,对测试结果进行分析,完成实验报告中实验三的 部分。
三、算法步骤、代码、及结果
1. 算法伪代码
1. 导入必要的库
- 从 sklearn.datasets 导入 load_iris
- 从 sklearn.model_selection 导入 train_test_split 和 cross_val_score
- 从 sklearn.tree 导入 DecisionTreeClassifier
- 从 sklearn.metrics 导入 accuracy_score, precision_score, recall_score, f1_score
2. 加载数据集并拆分
- 加载 iris 数据集 (X, y)
- 使用 train_test_split 将数据集按 2:1 比例分为训练集 (X_train, y_train) 和测试集 (X_test, y_test),确保 stratify=y 以保证标签分布一致
3. 定义 C4.5 决策树模型(模拟预剪枝)
- 初始化 DecisionTreeClassifier
- max_depth: 设置决策树的最大深度
- min_samples_split: 设置内部节点划分所需的最小样本数
- min_samples_leaf: 设置叶节点的最小样本数
4. 使用训练集训练模型
- 使用 X_train 和 y_train 拟合模型
5. 五折交叉验证
- 使用 cross_val_score 对模型进行五折交叉验证,分别计算
- 准确度
- 精度
- 召回率
- F1 值
- 记录每个指标的平均值
6. 在测试集上评估模型性能
- 使用 X_test 进行预测,得到预测值 y_pred
- 计算以下评估指标:
- 准确度 (accuracy_score)
- 精度 (precision_score)
- 召回率 (recall_score)
- F1 值 (f1_score)
7. 分析模型在五折交叉验证和测试集上的性能差异
2. 算法主要代码
完整源代码\调用库方法(函数参数说明)
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
# 1. 加载数据集
iris = load_iris()
X = iris.data
y = iris.target
# 2. 数据集拆分:训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, stratify=y, random_state=42)
# 3. 初始化决策树模型,模拟 C4.5 预剪枝
model = DecisionTreeClassifier(
criterion='entropy', # 使用信息增益率,模拟 C4.5
max_depth=5, # 限制最大深度
min_samples_split=4, # 每个节点最少样本数
min_samples_leaf=2 # 叶子节点最少样本数
)
# 4. 训练模型
model.fit(X_train, y_train)
# 5. 五折交叉验证
accuracy_scores = cross_val_score(model, X_train, y_train, cv=5, scoring='accuracy')
precision_scores = cross_val_score(model, X_train, y_train, cv=5, scoring='precision_macro')
recall_scores = cross_val_score(model, X_train, y_train, cv=5, scoring='recall_macro')
f1_scores = cross_val_score(model, X_train, y_train, cv=5, scoring='f1_macro')
print(f"五折交叉验证结果:")
print(f"准确度:{accuracy_scores.mean():.4f}")
print(f"精度:{precision_scores.mean():.4f}")
print(f"召回率:{recall_scores.mean():.4f}")
print(f"F1值:{f1_scores.mean():.4f}")
# 6. 在测试集上评估
y_pred = model.predict(X_test)
test_accuracy = accuracy_score(y_test, y_pred)
test_precision = precision_score(y_test, y_pred, average='macro')
test_recall = recall_score(y_test, y_pred, average='macro')
test_f1 = f1_score(y_test, y_pred, average='macro')
print(f"测试集性能:")
print(f"准确度:{test_accuracy:.4f}")
print(f"精度:{test_precision:.4f}")
print(f"召回率:{test_recall:.4f}")
1. criterion
- 作用:指定用于划分的评价准则。
- 取值:
'gini':使用基尼系数(Gini impurity)作为划分标准。'entropy':使用信息增益(entropy)作为划分标准,类似于 C4.5。- 默认值:
'gini' - 作用:指定节点划分策略。
- 取值:
'best':在所有特征中选择最优划分。'random':在随机特征子集中选择最优划分。- 默认值:
'best' - 作用:控制树的最大深度,用于预剪枝,防止过拟合。
- 取值:正整数或
None。 None表示树的深度不限制。- 默认值:
None - 作用:控制一个节点分裂所需的最小样本数,用于预剪枝。
- 取值:整数或浮点数。
- 如果是整数,表示最小样本数。
- 如果是浮点数,表示总样本数的某一比例。
- 默认值:
2 - 作用:叶节点上最少样本数,用于预剪枝。
- 取值:整数或浮点数。
- 如果是整数,表示叶节点最小样本数。
- 如果是浮点数,表示叶节点中样本占总样本数的比例。
- 默认值:
1 - 作用:叶节点中样本权重的最小占比,用于预剪枝。
- 取值:浮点数,范围
[0, 0.5]。 - 默认值:
0.0 - 作用:用于分裂的最大特征数。
- 取值:
- 整数:指定的特征数。
- 浮点数:特征占总特征数的比例。
'auto':选择所有特征。'sqrt':选择sqrt(n_features)个特征。'log2':选择log2(n_features)个特征。None:使用所有特征。- 默认值:
None - 作用:控制随机数生成,以保证结果的可重复性。
- 取值:整数或
None。 - 默认值:
None - 作用:限制最大叶节点数,用于预剪枝。
- 取值:正整数或
None。 None表示不限制叶节点数。- 默认值:
None - 作用:控制分裂节点时的最小不纯度下降。
- 取值:浮点数,范围
>=0。 - 默认值:
0.0 - 作用:指定类别权重,用于处理类别不平衡问题。
- 取值:
None:不调整类别权重。'balanced':根据样本数自动调整权重,使每个类别的权重与其样本数成反比。- 字典形式:自定义类别权重。
- 默认值:
None - 作用:用于后剪枝(代价复杂度剪枝)。
- 取值:非负浮点数。
- 默认值:
0.0
2. splitter
3. max_depth
4. min_samples_split
5. min_samples_leaf
6. min_weight_fraction_leaf
7. max_features
8. random_state
9. max_leaf_nodes
10. min_impurity_decrease
11. class_weight
12. ccp_alpha (剪枝参数)
3. 训练结果截图(包括:准确率、精度(查准率)、召回率(查全率)、F1)

四、实验结果分析
1. 测试结果截图(包括:准确率、精度(查准率)、召回率(查全率)、F1)

2. 对比分析
1. 准确度 (Accuracy)
五折交叉验证:0.9300
测试集:0.8600
分析:准确度从五折交叉验证的 93% 下降到测试集的 86%,这是一个显著的差距。五折交叉验证是在训练集上进行的,而测试集是新的数据集,因此测试集的表现下降说明模型可能存在一定的过拟合。虽然模型在训练集上表现较好,但在测试集上预测效果有所下降。
2. 精度 (Precision)
五折交叉验证:0.9384
测试集:0.8690
分析:精度从 93.84% 下降到 86.90%。精度度量的是模型预测的正类中有多少是真正的正类,精度下降表明在测试集中,模型的错误正类预测数量有所增加。该结果进一步支持了模型在新数据上的泛化性能不如训练集的结论。
3. 召回率 (Recall)
五折交叉验证:0.9302
测试集:0.8627
分析:召回率从 93.02% 降低到 86.27%。召回率表示在所有正类中,模型识别了多少个正类。召回率下降意味着在测试集上,模型对正类的识别率有所下降。这表明模型在测试集上的泛化性能有一定的不足,导致其无法捕获尽可能多的正类样本。
4. F1 值
五折交叉验证:0.9384
测试集:0.8617
分析:F1 值从 93.84% 下降到 86.17%,表明模型在测试集上整体的分类能力有所减弱。F1 值结合了精度和召回率,下降幅度与精度和召回率的下降幅度一致,进一步验证了测试集上表现的下降。
总结
泛化能力不足:模型在五折交叉验证中的表现优于在测试集上的表现,这表明模型在训练集上可能出现了过拟合,导致泛化到新数据的能力不强。
浙公网安备 33010602011771号