小白从零开始勇闯人工智能:机器学习初级篇(决策树)

引言

我们想一想计算机如何执行决策任务?当音乐应用推荐歌曲、电商平台建议商品,或银行系统处理贷款申请时,这些功能常依赖于一种算法进行决策。今天,我们将学习机器学习中的一种基本算法:决策树。它通过一系列规则对数据进行分类或预测,结构直观且易于理解。决策树会从数据中学习规则,并按照特征逐层划分,最终输出决策结果。

一、认识决策树------像树一样思考

1、什么是决策树

决策树是一种模拟人类逐步推理过程的经典机器学习算法,它通过构建一棵由节点和分支组成的树状结构,依据数据特征按层级进行规则判断,实现对样本的分类或回归预测,它的核心组件包括:根节点(代表整个数据集的起始判断点)、内部节点(每个节点对应一个特征属性的测试条件,将数据划分到不同分支)、叶子节点(位于树末端,代表最终的分类结果或预测值)以及连接它们的分支(表示基于判断条件所导向的不同路径),让我来举一个简单的银行贷款例子:

复制代码
          房产?
         /      \
       无        有
       /          \
     车辆?       可以贷款
    /    \
   无     有
   /       \
不可贷款  车收入?
            /    \
        >30万    <30万
          /        \
     可以贷款    不可贷款

这个树告诉我们有房产的直接可以贷款,没房产但有车的,则是由收入决定的,没房产也没车的,不能贷款。

2、决策树能做什么?

决策树可以胜任两种预测任务:分类任务:预测离散的类别标签,例如判断电信客户是否会流失(是/否)、识别一封邮件是否为垃圾邮件、或辅助进行疾病诊断(健康/患病),以及回归任务:预测连续的数值结果,例如预估房价、 forecasting 销售额或分析温度变化趋势。通过其基于规则的树形结构,决策树能够从数据特征中学习并模拟出复杂的决策边界或函数关系,使其在商业、医疗、金融等多个领域都有广泛的应用。

二、决策树的"灵魂"------三种核心算法

1、ID3算法:用"不确定性"衡量

ID3算法是一种经典的决策树生成算法,它是利用"不确定性"的减少来指导特征选择。它使用信息熵作为衡量数据集混乱程度的指标,熵值越大,表示数据的类别分布越混杂、不确定性越高。熵的计算公式为:H(U) = -Σ(p_i * log₂(p_i)),(其中p_i是第i类样本的比例。)。举一个简单的例子:假设我们有14天的数据,9天打球,5天不打球:信息增益 = 分裂前的熵 - 分裂后的加权平均熵,信息增益越大,说明用这个特征分裂效果越好。

复制代码
import math

# 计算熵值
p_play = 9/14
p_not_play = 5/14
entropy = -p_play * math.log2(p_play) - p_not_play * math.log2(p_not_play)
print(f"熵值: {entropy:.3f}")

2、C4.5算法:解决ID3的缺陷

ID3 存在的一个关键缺陷:由于 ID3 单纯依据信息增益来选择分裂特征,它会天然地偏好那些取值数量众多的特征,因为这类特征往往能产生非常纯的子集,带来很高的信息增益,但这会导致模型过拟合,缺乏泛化能力。C4.5算法是对 ID3 算法的一项重要改进:它引入了信息增益率作为新的特征选择标准,其定义为信息增益除以该特征本身的固有熵。即便一个特征取值很多、信息增益高,但如果它自身的熵也很大(表示其取值分布本身就很混乱),那么其信息增益率就会被抑制,从而更公平地评估特征的真实分类能力。

3、CART算法:最常用的现代算法

CART算法是目前广泛应用的决策树生成算法,其特点是能够同时处理分类与回归任务:在解决分类问题时,它使用基尼系数(Gini Index)作为衡量节点纯度的分裂标准,而在解决回归问题时,则使用均方误差(MSE)作为分裂标准。对于二分类问题,基尼系数的计算公式为Gini = 2 * p * (1-p),(其中p是正例的比例),基尼系数直观地反映了数据集的"不纯度",其值域在0到0.5之间(对于二分类),系数值越小,表示节点内样本的类别越趋于一致,即"纯度"越高,因此,CART算法在每一步分裂时,都会选择那个能使子节点加权基尼系数(或回归问题的均方误差)下降最多的特征及其分割点,通过这种递归的二分方式构建出一棵有强大预测能力的决策树。

三、实战:用Python构建第一棵决策树

1、环境准备

首先确保安装了必要的库:

复制代码
pip install pandas scikit-learn matplotlib numpy

2、电信客户流失预测实战

1.导入必要的库

复制代码
import pandas as pd        # 数据处理和分析
import numpy as np         # 数值计算
import matplotlib.pyplot as plt  # 数据可视化
from sklearn.model_selection import train_test_split  # 数据集划分
from sklearn.tree import DecisionTreeClassifier, plot_tree  # 决策树模型和可视化
from sklearn import metrics  # 模型评估指标

2.数据加载

复制代码
data = pd.read_excel("电信客户流失数据.xlsx")

3.数据预处理

复制代码
# 特征和目标变量分离
X = data.iloc[:, :-1]
y = data.iloc[:, -1]
# 数据集划分(80%训练,20%测试)
# stratify=y 确保训练集和测试集中正负样本比例一致
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

4.决策树模型构建

复制代码
clf = DecisionTreeClassifier(
    criterion='gini',      # 使用基尼系数作为分裂标准(CART算法)
    max_depth=3,           # 限制树的最大深度,防止过拟合
    min_samples_split=10,  # 节点至少需要10个样本才考虑分裂
    min_samples_leaf=5,    # 叶节点至少包含5个样本
    random_state=42        # 确保结果可复现
)

5.模型训练与可视化

复制代码
clf.fit(X_train, y_train)  # 训练模型
# 可视化决策树
plt.figure(figsize=(20, 10))
plot_tree(clf,
          feature_names=X.columns,  # 显示特征名
          class_names=['未流失', '流失'],  # 类别标签
          filled=True,      # 用颜色填充节点
          rounded=True,     # 圆角边框
          fontsize=10,
          proportion=True)  # 显示样本比例而不是数量

6.模型评估

复制代码
# 预测
y_pred = clf.predict(X_test)
y_pred_proba = clf.predict_proba(X_test)[:, 1]  # 预测为流失的概率

# 分类报告
print("分类报告:")
print(metrics.classification_report(y_test, y_pred, target_names=['未流失', '流失']))

# 混淆矩阵
cm = metrics.confusion_matrix(y_test, y_pred)
print("混淆矩阵:")
print(cm)

7.绘制AUC-ROC曲线

复制代码
fpr, tpr, thresholds = metrics.roc_curve(y_test, y_pred_proba)
roc_auc = metrics.auc(fpr, tpr)

plt.figure(figsize=(10, 8))
plt.plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC曲线 (AUC = {roc_auc:.3f})')
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--', label='随机猜测')
plt.xlabel('假正率')
plt.ylabel('真正率')
plt.title('ROC曲线')
plt.legend(loc="lower right")
plt.grid(True, alpha=0.3)
plt.show()

8.运行代码

四、决策树的深度探索

1、回归树:预测连续值

  1. 导入必要库

    import numpy as np
    from sklearn.tree import DecisionTreeRegressor, plot_tree
    import matplotlib.pyplot as plt

2.创建示例数据

复制代码
# 设置随机种子,确保每次运行结果相同
np.random.seed(42)

# 创建100个样本,3个特征
X_reg = np.random.rand(100, 3) * 100  # 特征值范围:0-100

# 创建目标变量(房价)
y_reg = 50 + X_reg[:,0]*0.3 + X_reg[:,1]*20 + X_reg[:,2]*0.5 + np.random.randn(100)*10

我们通过np.random.seed(42) 设置随机种子以确保结果的可重复性,随后生成了一个包含100个样本且每个样本具有3个特征的特征矩阵 X_reg,其值在0到100之间均匀随机生成,分别模拟房屋的面积(平方米)、房间数量(个)和地理位置得分,目标变量 y_reg(代表房价)则由一个预设的线性关系生成:基础房价50加上面积乘以0.3、房间数乘以20、地理位置得分乘以0.5的贡献,最后再添加一个标准差为10的正态分布随机噪声项,来模拟现实数据中的不确定性。

  1. 创建回归树模型

    创建回归树

    reg_tree = DecisionTreeRegressor(
    criterion='squared_error', # 分裂标准:均方误差
    max_depth=3, # 最大深度为3层
    min_samples_leaf=5, # 叶节点最少5个样本
    random_state=42 # 确保可重复性
    )

  2. 训练模型

    用数据训练回归树

    reg_tree.fit(X_reg, y_reg)

    获取模型得分

    score = reg_tree.score(X_reg, y_reg)
    print(f"模型R²分数: {score:.3f}")

5.可视化决策树

复制代码
# 设置图形大小
plt.figure(figsize=(12, 6))

# 绘制决策树
plot_tree(reg_tree, 
          feature_names=['面积', '房间数', '地理位置'],
          filled=True,      # 填充颜色
          rounded=True,     # 圆角矩形
          fontsize=10)      # 字体大小

# 添加标题
plt.title("房价预测回归树", fontsize=14)

# 显示图形
plt.tight_layout()
plt.show()

6.运行代码

2、关键参数详解与调优

1.导入库和初始化模型

复制代码
from sklearn.model_selection import GridSearchCV
from sklearn.tree import DecisionTreeClassifier

# 创建基础决策树模型
base_tree = DecisionTreeClassifier(random_state=42)

2.定义搜索参数

复制代码
# 简化的参数网格(为了加速搜索)
simple_grid = {
    'max_depth': [3, 4, 5],          # 树的最大深度
    'min_samples_leaf': [5, 10, 20]   # 叶子节点最少样本数
}

在通过网格搜索进行决策树模型的超参数调优时,我们定义了一个简化的参数网格 simple_grid来提升搜索效率,其中重点关注两个关键参数:其一是 max_depth,它用于控制树的最大生长深度,防止模型过度复杂,本次搜索将其候选值设定为 [3, 4, 5];其二是 min_samples_leaf,它规定了叶节点所需的最小样本数,有助于避免过拟合,本次搜索的候选值为 [5, 10, 20]。通过这个精炼的参数组合,系统可以更高效地遍历并评估不同模型配置的性能。

3.执行网格搜索

复制代码
# 创建网格搜索对象
grid_search = GridSearchCV(
    base_tree,           # 基础模型
    simple_grid,         # 参数网格
    cv=5,               # 5折交叉验证
    scoring='roc_auc'    # 使用AUC评分
)

# 在训练数据上执行搜索
grid_search.fit(X_train, y_train)

为了寻找决策树模型的最优参数组合,我们首先创建一个 GridSearchCV 对象,该对象以基础决策树模型为估计器,并传入之前定义的简化参数网格,同时指定使用交叉验证来评估每一组参数的稳健性,并以ROC曲线下面积作为模型优劣的评分标准,随后,调用该对象的 fit 方法在训练集 (X_train, y_train) 上执行全面的网格搜索,最终确定出在验证集上表现最佳的参数配置。

4.获取最佳模型

复制代码
# 获取最佳参数
best_params = grid_search.best_params_

# 获取最佳模型
best_tree = grid_search.best_estimator_

# 使用最佳参数重新训练模型(确保完全拟合)
best_tree.fit(X_train, y_train)

5.性能评估与比较

复制代码
from sklearn import metrics

# 使用调优后的模型预测
y_pred_best = best_tree.predict(X_test)

# 计算调优后准确率
best_accuracy = metrics.accuracy_score(y_test, y_pred_best)

# 计算原始模型准确率(假设已有模型clf)
original_accuracy = metrics.accuracy_score(y_test, clf.predict(X_test))

为了评估经过网格搜索调优后的决策树模型的性能,将其与未经调优的原始模型进行比较,我们首先使用调优得到的最佳模型对测试集进行预测,得到预测标签,随后,利用 accuracy_score 函数计算该最佳模型在测试集上的分类准确率,同时,为了进行对比,我们也计算出预先训练好的原始模型 clf 在相同测试集上的准确率,从而能够评估参数调优过程对模型性能的提升效果。

6.输出结果

复制代码
print(f"最佳参数: {best_params}")
print(f"最佳交叉验证AUC: {grid_search.best_score_:.3f}")

print(f"\n性能对比:")
print(f"调优前准确率: {original_accuracy:.3f}")
print(f"调优后准确率: {best_accuracy:.3f}")
print(f"提升: {(best_accuracy-original_accuracy)*100:.1f}%")

到这里我们就学完了决策树算法的基本内容了,在下一章里我们将继续学习机器学习中其他的一些常用算法。

相关推荐
LDG_AGI2 小时前
【推荐系统】深度学习训练框架(十九):TorchRec之DistributedModelParallel
人工智能·深度学习·机器学习·推荐算法
SickeyLee2 小时前
目标检测技术详解析:什么是目标检测?如何快速训练一个目标检测模型?目标检测技术的业务场景有哪些?
人工智能·语言模型
Robot侠2 小时前
ROS1从入门到精通 12:导航与路径规划(让机器人自主导航)
人工智能·机器人·自动驾驶·ros·路径规划·gazebo·导航
爱好读书2 小时前
AI生成ER图|SQL生成ER图
数据库·人工智能·sql·毕业设计·课程设计
NocoBase2 小时前
GitHub 上星星数量前 10 的 AI CRM 开源项目
人工智能·低代码·开源·github·无代码
小陈phd2 小时前
大语言模型实战(二)——Transformer网络架构解读
人工智能·深度学习·transformer
言之。2 小时前
Claude Code Commands 教学文档
人工智能
鲨莎分不晴2 小时前
读心术:对手建模与心智理论 (Agent Modeling & Theory of Mind)
人工智能·机器学习
LiYingL2 小时前
Pref-GRPO:通过成对比较实现稳定文本图像生成强化学习的新方法
人工智能