一、决策树模型
决策树是一种基于树形结构的监督学习算法,通过一系列规则(if-then条件)对数据进行分类或回归。其结构包含:

根节点:包含完整数据集的最顶层节点

内部节点:表示特征测试的分支决策点

叶节点:最终的分类/回归结果

2. 核心算法原理
(1) 特征选择准则
ID3算法(分类树):
使用 信息增益(Information Gain)选择特征
信息增益=H(D)−H(D∣A)信息增益=H(D)−H(D∣A)
其中 H(D)H(D) 是数据集的经验熵

C4.5算法:
改进ID3,采用 增益率(Gain Ratio)避免偏向多值特征
增益率=信息增益特征固有值增益率=特征固有值信息增益​

CART算法(分类与回归):

分类:使用 基尼系数(Gini Index)
Gini=1−∑k=1Kpk2Gini=1−∑k=1K​pk2​

回归:最小化 均方误差(MSE)

(2) 剪枝策略
预剪枝:在树生长过程中提前停止(如限制深度、设置最小样本数)

后剪枝:先生成完整树,再自底向上剪枝(如代价复杂度剪枝)

二、决策树特点:
特点    说明
可解释性    树结构直观,适合业务解释(优于黑盒模型如神经网络)
数据要求    可处理数值型和类别型特征,对缺失值敏感(需预处理)
计算复杂度    训练时间复杂度:O(n×m×log⁡n)O(n×m×logn)(n样本数,m特征数)
过拟合风险    容易生成过深树,需通过剪枝/随机森林等方法控制
三、实际应用场景
分类问题

银行:信用评分模型

医疗:疾病诊断(如乳腺癌良恶性判断)

回归问题

房价预测

销售额预估

特征重要性分析
通过计算特征在树中的分裂次数或信息增益量,评估特征贡献度

四、优缺点:
优点    缺点
无需特征缩放    对噪声数据敏感
可处理非线性关系    容易过拟合(需剪枝)
支持多输出任务    不稳定(数据微小变化可能导致树结构剧变)

五、实际实现:

通过一系列条件判断是否给予贷款。


通过特征映射建立数字与业务含义的对应关系(如0=青年, 1=中年, 2=老年)

规则提炼:

批准贷款的典型路径:
有自己的房子=是 → 直接批准
有自己的房子=否 + 有工作=是 → 批准

拒绝贷款的典型路径:
有自己的房子=否 + 有工作=否

代码实现:import numpy as np
import pandas as pd
from sklearn.tree import DecisionTreeClassifier, export_text, plot_tree
from sklearn.metrics import classification_report, confusion_matrix
import matplotlib.pyplot as plt
 
# 设置中文字体显示
plt.rcParams['font.sans-serif'] = ['SimHei']  
plt.rcParams['axes.unicode_minus'] = False
 
# 特征映射字典
feature_mapping = {
    '年龄段': {0: '青年', 1: '中年', 2: '老年'},
    '有工作': {0: '否', 1: '是'},
    '有自己的房子': {0: '否', 1: '是'},
    '信贷情况': {0: '一般', 1: '好', 2: '非常好'},
    '类别': {0: '拒绝贷款', 1: '批准贷款'}
}
 
# 加载数据函数
def load_data(file_path):
    """从txt文件加载数据,最后一列为标签"""
    data = np.loadtxt(file_path, delimiter=',')
    X = data[:, :-1]  # 特征
    y = data[:, -1]   # 标签
    return X, y
 
# 文件路径(根据实际位置修改)
dataset_path = r"C:dataset.txt"
testset_path = r"C:testset.txt"
 
# 加载数据
try:
    X_train, y_train = load_data(dataset_path)
    X_test, y_test = load_data(testset_path)
except FileNotFoundError as e:
    print(f"文件加载失败,请检查路径: {e}")
    exit()
 
# 特征名称(按数据列顺序)
feature_names = ['年龄段', '有工作', '有自己的房子', '信贷情况']
class_names = list(feature_mapping['类别'].values())
 
# 创建决策树模型(基于基尼系数)
clf = DecisionTreeClassifier(
    criterion='gini',     # 分裂标准
    max_depth=3,          # 最大深度
    min_samples_split=2,  # 节点分裂最小样本数
    random_state=42       # 随机种子
)
 
# 训练模型
clf.fit(X_train, y_train)
 
# 可视化决策树
plt.figure(figsize=(16, 10))
plot_tree(clf, 
          feature_names=feature_names,
          class_names=class_names,
          filled=True,      # 填充颜色
          rounded=True,     # 圆角边框
          impurity=True,   # 显示不纯度
          proportion=True)  # 显示样本比例
plt.title("贷款审批决策树(基于基尼系数)")
plt.show()
 
# 输出文本形式的决策规则
tree_rules = export_text(clf, feature_names=feature_names)
print("决策树规则:\n" + tree_rules)
 
# 在测试集上评估
y_pred = clf.predict(X_test)
 
print("\n测试集性能评估:")
print(classification_report(y_test, y_pred, target_names=class_names))
 
print("\n混淆矩阵:")
print(confusion_matrix(y_test, y_pred))
 
# 测试样本详细分析
def explain_prediction(sample_idx):
    """解释单个样本的预测过程"""
    sample = X_test[sample_idx]
    print(f"\n测试样本 {sample_idx} 详细分析:")
    print("特征值:")
    for i, name in enumerate(feature_names):
        print(f"  {name}: {feature_mapping[name][int(sample[i])]}")
    
    print(f"\n实际类别: {feature_mapping['类别'][int(y_test[sample_idx])]}")
    print(f"预测类别: {feature_mapping['类别'][int(y_pred[sample_idx])]}")
    print("类别概率:", clf.predict_proba([sample])[0])
    
    # 决策路径
    print("\n决策路径:")
    feature = clf.tree_.feature
    threshold = clf.tree_.threshold
    node_indicator = clf.decision_path([sample])
    leaf_id = clf.apply([sample])[0]
    
    path = []
    for node_id in node_indicator.indices[node_indicator.indptr[0]:
                                    node_indicator.indptr[1]]:
        if leaf_id == node_id:
            continue
        if sample[feature[node_id]] <= threshold[node_id]:
            threshold_sign = "<="
        else:
            threshold_sign = ">"
        path.append(
            f"{feature_names[feature[node_id]]} {threshold_sign} {threshold[node_id]:.2f}"
        )
    print(" -> ".join(path))
 
# 分析测试集第一个样本
explain_prediction(0)
 
# 特征重要性分析
print("\n特征重要性:")
importance = pd.DataFrame({
    '特征': feature_names,
    '重要性': clf.feature_importances_
}).sort_values('重要性', ascending=False)
print(importance)

运行截图:

性能报告:

                      precision recall   f1-score  support
   拒绝贷款      1.00     1.00      1.00          3
   批准贷款      1.00     1.00      1.00          4
特征重要性:

      特征                重要性
2   有自己的房子   0.60
1   有工作              0.40
0   年龄段              0.00
3   信贷情况          0.00
 

更多推荐