一、决策树介绍

1.1 算法核心

本次实验针对贷款审批场景,采用ID3 决策树算法,以信息增益为特征选择准则:

  • 信息熵:衡量贷款数据集的类别不纯度,公式为 H(D)=−∑k=1K​pk​log2​pk​(pk​为 “给贷款”/“不给贷款” 的样本占比);
  • 信息增益:划分后信息熵的减少量,公式为 Gain(D,a)=H(D)−∑v=1V​∣D∣∣Dv∣​H(Dv)(a为贷款特征,如 “有自己的房子”;Dv为特征a取v值的子集);
  • 核心逻辑:优先选择信息增益最大的特征作为节点划分依据,递归构建树形模型。

二、实践代码部分

1. 数据加载与预处理
# 1. 导入依赖库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.metrics import accuracy_score, confusion_matrix

# 配置中文字体
plt.rcParams["font.family"] = ["SimHei", "Microsoft YaHei"]
plt.rcParams["axes.unicode_minus"] = False

# 2. 数据加载与预处理
def load_and_preprocess_data():
    columns = ["年龄段", "有工作", "有自己的房子", "信贷情况", "类别"]
    train_data = pd.read_csv("dataset.txt", sep=",", header=None, names=columns)
    test_data = pd.read_csv("testset.txt", sep=",", header=None, names=columns)
    
    X_train = train_data.drop("类别", axis=1)
    y_train = train_data["类别"]
    X_test = test_data.drop("类别", axis=1)
    y_test = test_data["类别"]
    
    print("-"*30) 
    print("数据基本信息")
    print("-"*30)
    print(f"训练集样本数:{len(train_data)},测试集样本数:{len(test_data)}")
    print("特征编码规则:")
    print("- 年龄段:青年(0)/中年(1)/老年(2)")
    print("- 有工作/有自己的房子:否(0)/是(1)")
    print("- 信贷情况:一般(0)/好(1)/非常好(2)")
    print("- 类别:不给贷款(0)/给贷款(1)")
    return X_train, X_test, y_train, y_test
2. 模型构建与训练
# 3. 模型构建与训练
def build_and_train_model(X_train, y_train):
    dt_model = DecisionTreeClassifier(
        criterion="entropy",
        random_state=42
    )
    dt_model.fit(X_train, y_train)
    print("\n" + "-"*30)
    print("模型训练完成")
    print("-"*30)
    print(f"训练集拟合准确率:{dt_model.score(X_train, y_train):.4f}")
    return dt_model

# 4. 手动计算指标
def calculate_metrics(y_true, y_pred, class_names):
    cm = confusion_matrix(y_true, y_pred)
    n_classes = len(class_names)
    precision = []
    recall = []
    f1_score = []
    support = []
    
    for i in range(n_classes):
        tp = cm[i, i]
        fp = cm[:, i].sum() - tp
        fn = cm[i, :].sum() - tp
        sup = cm[i, :].sum()
        support.append(sup)
        
        prec = tp / (tp + fp) if (tp + fp) != 0 else 0.0
        rec = tp / (tp + fn) if (tp + fn) != 0 else 0.0
        f1 = 2 * (prec * rec) / (prec + rec) if (prec + rec) != 0 else 0.0
        
        precision.append(prec)
        recall.append(rec)
        f1_score.append(f1)
    
    macro_prec = np.mean(precision)
    macro_rec = np.mean(recall)
    macro_f1 = np.mean(f1_score)
    weighted_prec = np.average(precision, weights=support)
    weighted_rec = np.average(recall, weights=support)
    weighted_f1 = np.average(f1_score, weights=support)
    accuracy = accuracy_score(y_true, y_pred)
    
    return (precision, recall, f1_score, support, 
            macro_prec, macro_rec, macro_f1,
            weighted_prec, weighted_rec, weighted_f1,
            accuracy)
3. 指标手动计算
# 5. 分类报告
def evaluate_model(dt_model, X_test, y_test):
    y_pred = dt_model.predict(X_test)
    class_names = ["不给贷款", "给贷款"]
    
    (precision, recall, f1_score, support,
     macro_prec, macro_rec, macro_f1,
     weighted_prec, weighted_rec, weighted_f1,
     accuracy) = calculate_metrics(y_test, y_pred, class_names)
    
    print("\n" + "-"*30)
    print("模型评估结果")
    print("-"*30)
    print(f"测试集准确率:{accuracy:.4f}")
    
    print("\n分类报告:")
    header = f"{'':<12} {'精确率':<8} {'召回率':<8} {'F1分数':<8} {'支持数'}"
    print(header)
    print("-" * 45) 
    for i, name in enumerate(class_names):
        line = f"{name:<12} {precision[i]:<8.2f} {recall[i]:<8.2f} {f1_score[i]:<8.2f} {support[i]}"
        print(line)
    print()
    print(f"{'准确率':<12} {'':<8} {'':<8} {'':<8} {accuracy:.2f}         {sum(support)}")
    print(f"{'宏观平均':<12} {macro_prec:<8.2f} {macro_rec:<8.2f} {macro_f1:<8.2f} {sum(support)}")
    print(f"{'加权平均':<12} {weighted_prec:<8.2f} {weighted_rec:<8.2f} {weighted_f1:<8.2f} {sum(support)}")
    
    return accuracy
4. 决策树可视化
# 6. 决策树可视化
def visualize_tree(dt_model, X_train):
    plt.figure(figsize=(15, 10))
    plot_tree(
        dt_model,
        filled=True,
        rounded=True,
        feature_names=X_train.columns,
        class_names=["不给贷款", "给贷款"],
        fontsize=10
    )
    plt.title("贷款审批决策树", fontsize=15, pad=20)
    plt.savefig("贷款审批决策树.png", dpi=300, bbox_inches="tight")
    plt.show()
    print("\n决策树可视化文件已保存:贷款审批决策树.png")

# 主函数执行
if __name__ == "__main__":
    X_train, X_test, y_train, y_test = load_and_preprocess_data()
    dt_model = build_and_train_model(X_train, y_train)
    accuracy = evaluate_model(dt_model, X_test, y_test)
    visualize_tree(dt_model, X_train)

三、实验结果

3.1 终端输出

3.2 可视化结果

四、实验报告

4.1 实验目的

  1. 掌握 ID3 决策树算法的核心原理:信息增益计算、特征选择逻辑;
  2. 完成贷款审批数据集的端到端分类实验,掌握数据加载、模型训练、评估的完整流程;

4.2 实验环境

  • 操作系统:Windows
  • 开发工具:Visual Studio Code
  • 编程语言:Python
  • 依赖库:pandas、numpy、scikit-learn 、matplotlib

4.3 实验原理

本次实验基于 ID3 算法,通过计算 “年龄段”“有工作”“有自己的房子”“信贷情况” 4 个特征的信息增益,优先选择信息增益最大的特征作为根节点,递归划分数据集:

  1. 若 “有自己的房子 = 是”,直接判定为 “给贷款”;
  2. 若 “有自己的房子 = 否”,则以 “有工作” 为下一层节点,“有工作 = 是” 判定为 “给贷款”,“有工作 = 否” 进一步按 “信贷情况” 划分;
  3. 当子集样本类别一致或无剩余特征时,停止划分,形成叶节点。

4.4 实验步骤

  1. 环境配置:安装所需 Python 依赖库,无需额外安装字体;
  2. 数据准备:将训练集dataset.txt、测试集testset.txt放入代码同级目录;
  3. 数据加载:通过pandas读取数据集,分离特征与标签,打印数据基本信息;
  4. 模型构建:初始化 ID3 决策树分类器,设置信息熵准则与随机种子;
  5. 模型训练:使用训练集拟合模型,输出训练集拟合准确率;
  6. 模型评估:手动计算分类指标,输出纯中文分类报告与测试集准确率;
  7. 可视化:绘制全中文决策树,保存高分辨率图片并展示;
  8. 结果分析:整理终端输出与可视化结果,总结实验结论。

五、实验总结

1. 模型效果

本次实验用 ID3 算法训练的决策树在测试集上达到了 88% 的准确率,能有效根据 “是否有房、是否有工作” 等核心特征判断是否给贷款,符合实际信贷场景的逻辑。

2. 结论

  • 贷款决策中“是否有自己的房子” 是最核心的特征 (信息增益最大);
  • 若需进一步提升准确率,可尝试增加训练样本量、调整树的最大深度。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐