【机器学习:决策树】

1、简介

在机器学习中,有一个非常重要的常用结构就是树,对机器学习中树的理解可以类比数据结构中的树,其实是一个道理。以改种方式实现的算法有很多,比如随机森林、GBDT、XGBoost等。这种树形结构在机器学习中称为决策树

决策树是一种树形结构,树中每个内部节点表示一个特征上的判断,每个分支代表一个判断结果的输出,每个叶子节点代表一种分类结果。决策树通过分裂降低数据,提升分类纯度。

决策树非常适用于处理离散型数据,使用的类似于贪心算法

接下来简单讲一下它的建立过程:

  1. 特征选择:选取有较强分类能力的特征。
  2. 决策树生成:根据选择的特征生成决策树。
  3. 决策树也易过拟合,采用剪枝的方法缓解过拟合。

2、熵

上面提到决策树通过分裂降低数据,提升分类纯度。熵在热力学中主要衡量能量分散程度和系统的不可逆性。在信息论中,信息熵是1948年由克劳德·香农提出,用于量化系统的不确定性或信息量,其中熵增是有序(确定性)→无序(不确定性),模型学习难度越大。熵减是混乱→有序(信息处理),模型学习的核心目标。

在机器学习中,信息熵的计算方式为:

其中 P(xi) 表示数据中类别出现的概率,H(x) 表示信息的信息熵值。

举个例子,假设我们有一个数据样本α(AAAABBCD),现在让我们计算它的信息熵,根据公式:其中A 出现的概率为12\frac{1}{2}21,B 出现的概率为141\over441,C、D 出现的概率为181\over881,计算如下:
H(β)=−∑i=0nP(xi)log⁡2P(xi)=(−12log⁡212)+(−14log⁡214)+(−18log⁡218)∗2 H(β) = -\sum\limits_{i=0}^{n} P(x_i) \log_2 P(x_i) = \left(-\frac{1}{2} \log_2 \frac{1}{2}\right) + \left(-\frac{1}{4} \log_2 \frac{1}{4}\right) + \left(-\frac{1}{8} \log_2 \frac{1}{8}\right) *2 H(β)=−i=0∑nP(xi)log2P(xi)=(−21log221)+(−41log241)+(−81log281)∗2
=12×1+14×2+18×3×2=1.75 = \frac{1}{2} \times1+ \frac{1}{4} \times 2 + \frac{1}{8} \times 3 \times 2= 1.75 =21×1+41×2+81×3×2=1.75

3、信息增益

信息增益:(Information Gain, IG)它基于信息论中的熵概念,用来评估通过某个特征对数据集进行分割后所带来的纯度提升或不确定性减少的程度。简单来说,信息增益越大,表示使用该特征进行划分能更有效地降低数据集的混乱程度。
g(D,a)=H(D)−H(D∣A) g(D, a) = H(D) - H(D|A) g(D,a)=H(D)−H(D∣A)

g(D, a) :表示在数据集 ( D ) 上使用属性 ( a ) 进行划分的信息增益。

H(D) :表示数据集 ( D ) 的熵,衡量了数据集的不确定性或混乱程度。

H(D|A) :表示在已知属性 ( A ) 的条件下,数据集 ( D ) 的条件熵,即在给定属性 ( A ) 的情况下数据集的剩余不确定性。

即:信息增益=熵−条件熵信息增益 = 熵 - 条件熵信息增益=熵−条件熵

条件熵:

条件熵是所有分类占比与对应子集熵的加权和。计算公式是:
H(D∣A)=∑i=1n∣Di∣∣D∣H(Di)=∑i=1n∣Di∣∣D∣∑k=1K∣Cik∣∣Di∣log⁡2∣Cik∣∣Di∣H(D|A) = \sum_{i=1}^{n} \frac{|D_i|}{|D|} H(D_i) = \sum_{i=1}^{n} \frac{|D_i|}{|D|} \sum_{k=1}^{K} \frac{|C_{ik}|}{|D_i|} \log_2 \frac{|C_{ik}|}{|D_i|}H(D∣A)=i=1∑n∣D∣∣Di∣H(Di)=i=1∑n∣D∣∣Di∣k=1∑K∣Di∣∣Cik∣log2∣Di∣∣Cik∣

示例:

对于以下数据,已知6个样本,根据特征a:α 部分对应的目标值为: AAAB,β 部分对应的目标值为:BB

条件为α熵为H(Dα)H(D_α)H(Dα): −34log⁡234−14log⁡214≈0.81-\frac{3}{4} \log_2 \frac{3}{4} - \frac{1}{4} \log_2 \frac{1}{4} \approx 0.81−43log243−41log241≈0.81

条件为β熵为H(Dβ)H(D_β)H(Dβ):−22log⁡222=0-\frac{2}{2} \log_2 \frac{2}{2} = 0−22log222=0

α占了464\over664,β占了262\over662

那么特征a条件熵H(D∣a)H(D|a)H(D∣a)为:46×0.81+26×0=0.54\frac{4}{6} \times 0.81 + \frac{2}{6} \times 0 = 0.5464×0.81+62×0=0.54

目标值信息熵为:−36log⁡236−36log⁡236=1-\frac{3}{6} \log_2 \frac{3}{6} - \frac{3}{6} \log_2 \frac{3}{6} = 1−63log263−63log263=1

那么信息增益的计算为:

信息增益:熵 -- 条件熵: 1.0 -- 0.54 = 0.46

4、ID3、C4.5

ID3决策树和C4.5决策树是经典的决策树结构。

ID3 采用的是信息增益来划分特征节点,即上一小节讲的计算方式。

ID3树由于其计算特性,会偏向于选择种类多的特征作为分裂依据,因为这样会让它的信息增益最大化,这将导致整棵树依赖少数特征,过拟合。

C4.5就是解决ID3策略的不足,采用信息增益率作为决策选择标准。

信息增益率:

计算方式概述:信息增益率 = 信息增益 / 特征熵

数学表达式为
Gain_Ratio(D,a)=Gain(D,a)IV(a)\text{Gain\_Ratio}(D, a) = \frac{\text{Gain}(D, a)}{\text{IV}(a)}Gain_Ratio(D,a)=IV(a)Gain(D,a)

其中IV(a)=−∑v=1n∣Dv∣∣D∣log⁡2∣Dv∣∣D∣\text{IV}(a) = -\sum_{v=1}^{n} \frac{|D^v|}{|D|} \log_2 \frac{|D^v|}{|D|}IV(a)=−v=1∑n∣D∣∣Dv∣log2∣D∣∣Dv∣,表示特征 (a) 的固有值(Intrinsic Value),也称为特征熵

它相当于对信息增益进行修正,增加一个惩罚系数;特征取值个数较多时,惩罚系数较小;特征取值个数较少时,惩罚系数较大。
惩罚系数:数据集D以特征a作为随机变量的熵的倒数。

5、CART

CART(Classification and Regression Tree,分类与回归树)是一种经典的决策树算法。采用基尼指数,计算量小。Cart既能处理分类问题(生成分类树),也能处理回归问题(生成回归树)。CART划分的为二叉树,对于特征有多个分类的情况,采用选取一类 为一组 剩余类为非该类组;对于特征连续的情况,使用每两个类别值的中位数作为分割点,分割样本,分别计算基尼指数,选择合适的一个阈值。

基尼值:

从数据集D中随机抽取两个样本,其类别标记不一致的概率。Gini(D)值越小,数据集D的纯度越高。
Gini(D)=∑k=1∣y∣∑k′≠kpkpk′=1−∑k=1∣y∣pk2\text{Gini}(D) = \sum_{k=1}^{|y|} \sum_{k' \neq k} p_k p_{k'} = 1 - \sum_{k=1}^{|y|} p_k^2Gini(D)=k=1∑∣y∣k′=k∑pkpk′=1−k=1∑∣y∣pk2

  • Gini(D)\text{Gini}(D)Gini(D) 表示数据集 DDD的基尼系数
  • ∣y∣|y|∣y∣ 表示类别的总数
  • pkp_kpk表示样本属于第 kkk 个类别的概率(或比例)
  • pk′p_{k'}pk′表示样本属于第k′k'k′ 个类别的概率(或比例),其中 k′≠kk' \neq kk′=k

基尼指数Gini_index(D):
Gini_index(D,a)=∑v=1V∣Dv∣∣D∣⋅Gini(Dv) \text{Gini\index}(D,a) = \sum{v=1}^V \frac{|D^v|}{|D|} \cdot \text{Gini}(D^v) Gini_index(D,a)=v=1∑V∣D∣∣Dv∣⋅Gini(Dv)

其中:

  • Gini_index(D,a)\text{Gini\_index}(D,a)Gini_index(D,a) 表示特征 aaa 的基尼指数
  • VVV 表示特征 aaa 可能取值的个数
  • ∣D∣|D|∣D∣ 表示数据集 DDD 的样本总数
  • ∣Dv∣|D^v|∣Dv∣ 表示特征 aaa 取第 vvv 个值的样本数量
  • Gini(Dv)\text{Gini}(D^v)Gini(Dv) 表示特征 aaa 取第 vvv 个值的子数据集 DvD^vDv 的基尼系数

选择使划分后基尼系数最小的属性作为最优化分属性。

在分类问题中CART树的特征选择评估标准为基尼指数,CART树同样也可以用于回归任务中,回归任务中参考的标准是均方误差。使用均方误差(MSE) 作为划分标准。

回归树与分类树的不同:

  1. CART 分类树预测输出的是一个离散值,CART 回归树预测输出的是一个连续值。
  2. CART 分类树使用基尼指数作为划分、构建树的依据,CART 回归树使用平方损失划分,以均方误差评估。
  3. 分类树使用叶子节点多数类别作为预测类别,回归树则采用叶子节点里均值作为预测输出。

6、决策树剪枝

决策树剪枝是一种防止决策树过拟合的一种正则化方法;提高其泛化能力。剪枝的操作是把子树的节点全部删掉,使用用叶子节点来替换。决策树剪枝是一种防止决策树过拟合的一种正则化方法;提高其泛化能力。剪枝的操作是把子树的节点全部删掉,使用用叶子节点来替换。
预剪枝:指在决策树生成过程中,对每个节点在划分前先进行估计,若当前节点的划分不能带来决策树泛化性能提升,则停止划分并将当前节点标记为叶节点;

  1. 优点:减少了决策树的训练、测试时间开销
  2. 缺点:欠拟合的风险

后剪枝

是先从训练集生成一棵完整的决策树,然后自底向上地对非叶节点进行考察,若将该节点对应的子树替换为叶节点能带来决策树泛化性能提升,则将该子树替换为叶节点。

  1. 优点:泛化性能往往优于预剪枝
  2. 缺点:训练时间开销比未剪枝的决策树和预剪枝的决策树都要大得多。

7、CART树相比于其他决策树的优势

• 二叉树结构:简化了树的结构,减少了计算复杂度。

• 分类和回归统一:适用于分类和回归任务,灵活性更高。

• 损失函数优化:通过基尼指数(分类)和均方误差(回归)进行分裂优化,能更好地避免过拟合。

• 缺失值处理:对缺失值的处理较为直接和灵活。

• 后剪枝策略:有效降低过拟合,优化模型性能。

• 易于理解和解释:树形结构清晰,决策过程易于解释。

示例:

python 复制代码
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score, confusion_matrix, classification_report

data = pd.read_csv('./train.csv')

x = data[['Pclass', 'Sex', 'Age']]
print(x.shape)

y = data['Survived']
x = x.copy()

x.fillna(x['Age'].mean(), inplace=True)

x = pd.get_dummies(x)
x.drop(columns=['Sex_female'], inplace=True)

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=6, stratify=y)

ssm = StandardScaler()
x_train = ssm.fit_transform(x_train)
x_test = ssm.transform(x_test)

dtc = DecisionTreeClassifier(criterion='gini', splitter='best')
dtc.fit(x_train, y_train)
prediction = dtc.predict(x_test)

print(accuracy_score(y_test, prediction))
print(precision_score(y_test, prediction))
print(recall_score(y_test, prediction))
print(f1_score(y_test, prediction))
print(roc_auc_score(y_test, prediction))
print(confusion_matrix(y_test, prediction))
print(classification_report(y_test, prediction))

plt.figure(figsize=(100, 50))
plot_tree(dtc, filled=True)
plt.savefig('./tree.png')
相关推荐
roman_日积跬步-终至千里1 小时前
【计算机视觉(6)】边缘与直线检测基础篇:从Canny到Hough变换
人工智能·计算机视觉
张彦峰ZYF1 小时前
AI赋能原则4解读思考:AI 不是“可选的加分项”,而是重构生存方式的基础设施
人工智能·ai·ai赋能与落地
weixin_421585011 小时前
模型组装:new_model = tf.keras.Model(inputs=输入张量, outputs=输出张量)
人工智能·深度学习
沃达德软件1 小时前
警务大数据可视化展示
大数据·人工智能·信息可视化
paopao_wu1 小时前
ComfyUI遇上Z-Image(3):文生图/图生图
人工智能·ai·文生图·图生图·comfyui·z-image·we
小白|1 小时前
OpenHarmony + Flutter 混合开发实战:深度集成 AI Kit 实现端侧图像识别与智能分析
人工智能·flutter
✎ ﹏梦醒͜ღ҉繁华落℘1 小时前
编程基础--数据结构
数据结构·算法
小毅&Nora1 小时前
【后端】【C++】泛型算法:从传统到C++20 Ranges的进化之旅
算法·c++20·泛函算法
ULTRA??1 小时前
最小生成树kruskal算法实现python,kotlin
人工智能·python·算法