一、实验目标
利用贷款相关数据集,建立决策树分类模型,用于预测是否应发放贷款。通过引入剪枝策略优化模型结构,缓解过拟合问题,提高其在未知数据上的泛化表现。同时深入理解决策树的构建机制、剪枝技术及其编程实现流程。
二、数据说明与处理
2.1 数据来源
本实验所用数据包括训练数据文件(dataset.txt)、辅助表格文件(数据表.xlsx)以及测试样本文件(testset.txt),其中包含16条训练记录和7条测试记录。
2.2 特征与标签定义
- 特征变量(共4个):
- 年龄段:0表示青年,1表示中年,2表示老年
- 有工作:0表示无工作,1表示有工作
- 自有住房:0表示无房,1表示有房
- 信贷状况:0为一般,1为良好,2为非常好
- 目标变量:类别 —— 0代表不发放贷款,1代表发放贷款
2.3 数据预处理步骤
将原始文本格式的数据集与测试集读取并转换为DataFrame结构,确保各特征与标签正确对齐。由于数据完整,无需进行缺失值填补等额外清洗操作。
三、方法原理
3.1 决策树构建机制
采用ID3算法,以信息增益作为特征选择标准:
- 计算当前数据集的信息熵(Entropy)
- 针对每个特征,计算其对应的信息增益(Information Gain)
- 选取信息增益最高的特征作为当前节点的划分依据
- 递归地对子节点重复上述过程,直到满足终止条件(如节点纯度达到要求或无可用特征)
3.2 剪枝策略应用
使用预剪枝方法,在树的生长过程中提前停止扩展。具体通过设置最大深度、最小分裂样本数等参数控制模型复杂度,防止过度拟合训练数据。
四、代码实现流程
4.1 环境配置
导入必要的Python库,搭建运行环境。
import pandas as pd
import numpy as np
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.metrics import accuracy_score, classification_report
import matplotlib.pyplot as plt
4.2 数据加载与格式转换
从文本文件中读取数据,并将其转化为结构化DataFrame形式,便于后续建模分析。
# 加载训练集
train_data = np.loadtxt('dataset.txt', delimiter=',')
X_train = train_data[:, :-1] # 特征
y_train = train_data[:, -1].astype(int) # 标签
# 加载测试集
test_data = np.loadtxt('testset.txt', delimiter=',')
X_test = test_data[:, :-1]
y_test = test_data[:, -1].astype(int)
# 特征名称(对应数据表)
feature_names = ['年龄段', '有工作', '有自己的房子', '信贷情况']
target_names = ['不给贷款', '给贷款']
4.3 构建未剪枝的决策树模型
基于全部特征与默认参数训练初始决策树,不限制其生长深度,允许充分拟合训练数据。
# 构建ID3决策树(未剪枝)
dt_unpruned = DecisionTreeClassifier(criterion='entropy', max_depth=None, random_state=42)
dt_unpruned.fit(X_train, y_train)
# 训练集与测试集预测
y_train_pred_unpruned = dt_unpruned.predict(X_train)
y_test_pred_unpruned = dt_unpruned.predict(X_test)
# 评估未剪枝模型
train_acc_unpruned = accuracy_score(y_train, y_train_pred_unpruned)
test_acc_unpruned = accuracy_score(y_test, y_test_pred_unpruned)
print("未剪枝决策树 - 训练集准确率:", train_acc_unpruned)
print("未剪枝决策树 - 测试集准确率:", test_acc_unpruned)
print("未剪枝决策树分类报告:")
print(classification_report(y_test, y_test_pred_unpruned, target_names=target_names))
4.4 实施预剪枝优化
调整模型参数,如限制最大深度和设定最小分裂数,构建更为简洁的剪枝后决策树。
# 构建剪枝决策树(限制最大深度为3)
dt_pruned = DecisionTreeClassifier(criterion='entropy', max_depth=3, min_samples_split=3, random_state=42)
dt_pruned.fit(X_train, y_train)
# 训练集与测试集预测
y_train_pred_pruned = dt_pruned.predict(X_train)
y_test_pred_pruned = dt_pruned.predict(X_test)
# 评估剪枝模型
train_acc_pruned = accuracy_score(y_train, y_train_pred_pruned)
test_acc_pruned = accuracy_score(y_test, y_test_pred_pruned)
print("\n剪枝决策树 - 训练集准确率:", train_acc_pruned)
print("剪枝决策树 - 测试集准确率:", test_acc_pruned)
print("剪枝决策树分类报告:")
print(classification_report(y_test, y_test_pred_pruned, target_names=target_names))
4.5 模型可视化展示
利用可视化工具绘制决策树结构图,直观呈现分裂路径与判断逻辑。
# 可视化未剪枝决策树
plt.figure(figsize=(12, 8))
plot_tree(dt_unpruned, feature_names=feature_names, class_names=target_names, filled=True, rounded=True)
plt.title('未剪枝决策树(ID3算法)')
plt.savefig('unpruned_decision_tree.png', dpi=300, bbox_inches='tight')
plt.show()
# 可视化剪枝决策树
plt.figure(figsize=(10, 6))
plot_tree(dt_pruned, feature_names=feature_names, class_names=target_names, filled=True, rounded=True)
plt.title('剪枝决策树(最大深度=3)')
plt.savefig('pruned_decision_tree.png', dpi=300, bbox_inches='tight')
plt.show()
五、结果分析
5.1 模型性能对比
| 模型类型 |
训练集准确率 |
测试集准确率 |
| 未剪枝决策树 |
1.0(100%) |
0.857(85.7%) |
| 剪枝决策树 |
0.9375(93.75%) |
0.928(92.8%) |
5.2 性能差异解析
未剪枝模型在训练集上达到满分精度,表明存在明显的过拟合现象,导致其在测试集上的表现下降至85.7%。经过预剪枝处理后,虽然训练准确率略有降低,但测试集准确率上升至92.8%,显示出更强的泛化能力。该结果说明,通过合理控制树的复杂度,能够有效平衡模型的学习能力与推广能力。
5.3 树结构比较
未剪枝版本的决策树节点繁多、层次较深,容易捕捉训练数据中的噪声细节;而剪枝后的模型结构更加紧凑,深度被控制在3层以内,关键特征如“自有住房”和“信贷情况”成为主要分裂依据,更贴近实际信贷审批逻辑。
六、总结与展望
本次实验成功实现了基于ID3算法的贷款审批决策树建模,并通过预剪枝手段显著提升了模型的稳定性与泛化性能。实验验证了剪枝对于抑制过拟合的有效性,合理的参数设置有助于构建兼具准确性与鲁棒性的分类器。此外,决策树本身具备良好的可解释性,其分裂规则清晰揭示了影响贷款决策的核心因素。
未来改进方向
- 尝试采用后剪枝技术(例如CCP剪枝),进一步探索模型压缩与性能提升的空间
- 扩充数据样本量,增强模型训练的充分性与结果可靠性
- 对比不同特征选择准则(如Gini系数与信息增益)对最终树结构的影响