从零开始学AI——4

53 阅读10分钟

前言

最近天气变化好快,笔记开头的时候还穿羽绒服,发布的时候已经穿单件了,有点难崩

第四章

4.1 决策树与最优划分

决策树是一种基于树形结构的监督学习方法,其核心思想是通过递归属性划分,将数据按照属性值划分为多个子集,最终生成纯度最高的叶子节点(即不可再划分的同类别数据集合)。以分类任务为例,其构建过程如下:

  1. 根结点包含所有样本数据和初始属性集
  2. 从当前属性集中选择最优划分属性(选择方法见4.2节),按该属性的取值将样本划分为多个子集,并:
    • 从剩余属性集中移除已选属性
    • 每个子集生成一个子节点(对应属性值作为分支条件)
  3. 递归执行划分,直到满足以下终止条件:
    • 属性耗尽:当可用属性为空时,节点转为叶节点,标记为当前样本的多数类
    • 样本同质:当前节点样本全属同一类时,转为叶节点并标记为该类;所有样本在剩余属性上取值相同时,转为叶节点并标记为当前样本的多数类
    • 空子集:当某属性值对应的子集为空时,转为叶节点并选择父节点多数类作为标记
// 递归构建决策树
TreeNode buildTree(DataSet samples, AttributeSet attributes) {
    // 终止条件1: 样本全属同一类
    if (samples.allSameClass()) 
        return new LeafNode(samples.majorityClass());
    
    // 终止条件2: 属性耗尽或样本在剩余属性上取值相同
    if (attributes.isEmpty() || samples.sameValueOnAllAttributes()) 
        return new LeafNode(samples.majorityClass());
    
    // 选择最优划分属性
    Attribute bestAttr = selectBestSplitAttribute(samples, attributes);
    
    // 创建内部节点
    InternalNode node = new InternalNode(bestAttr);
    
    // 按属性值划分样本
    for (Value value : bestAttr.values()) {
        DataSet subset = samples.splitByAttributeValue(bestAttr, value);
        
        // 终止条件3: 空子集
        if (subset.isEmpty()) {
            node.addChild(new LeafNode(samples.majorityClass()));
        } else {
            // 递归构建子树(移除已用属性)
            node.addChild(buildTree(subset, attributes.remove(bestAttr)));
        }
    }
    return node;
}

以上是伪代码实现,其核心逻辑在于选择最优划分属性。当面对多个候选属性时,如何通过量化评估优先选择区分度最高的属性,是需要解决的关键问题。

在这里我们需要一个数学指标来量化集合的纯度即信息熵。设当前样本DD中含有NN个类,第kk类样本所占比例为pkp_{k}(自然有log2pk0\log_{2}p_{k}\leq0),那么当前样本的信息熵定义为:

Ent(D)=i=1Npklog2pkEnt(D) = -\sum_{i=1}^{N} p_{k}\log_{2}p_{k}

显然当纯度越高时,熵越小;反之熵越大。

玻尔兹曼熵 物理上通过统计力学计算的熵定义为 S=kBlnΩS = k_{B}\ln\Omega,看起来确实很像

当我们选择一个属性aa时,其可能取值为VV种,因此会将数据集DD划分为VV个子集。设属性值ava^v对应的子集为DvD^v,可通过以下公式计算划分后的信息增益(即信息熵的加权总变化):

Gain(D,a)=Ent(D)v=1VDvDEnt(Dv)Gain(D,a) = Ent(D) - \sum_{v=1}^{V} \frac{|D^v|}{|D|}Ent(D^v)

重点

  1. 信息增益为正时,表明划分后整体纯度提升(但单个子集的纯度可能降低)。
  2. 选择划分属性时,需计算所有候选属性的信息增益,并选择最大值对应的属性作为最优划分依据。

但我们回过头仔细观察信息增益的计算式,如果划分的V=DV = |D|(即每个子集只含有11个样本),此时信息增益可以达到最大值。直观上很好理解:因为每个子集都"纯"得不能再纯了(完全分类)。但这样的划分真的好吗?

例如,如果样本有属性id,按id划分就会导致上述情况——这种划分毫无泛化能力,说明单纯依赖信息增益会引发过拟合问题。

为了解决这个问题,需要引入一项修正项来惩罚属性aa的取值过多情况。这项修正就是属性aa固有值(Intrinsic Value),它反映了按属性aa划分后的信息熵(划分的类别越多,系统越混乱,熵越高):

IV(a)=v=1VDvDlog2DvDIV(a) = -\sum_{v=1}^{V} \frac{|D^v|}{|D|} \log_{2} \frac{|D^v|}{|D|}

增益率(Gain Ratio)则定义为信息增益与固有值的比值:

Gain_ratio(D,a)=Gain(D,a)IV(a)Gain\_ratio(D,a) = \frac{Gain(D,a)}{IV(a)}

但需注意:增益率会偏好取值较少的属性(因为IV(a)IV(a)较小)。因此实际应用中通常分两步:

  1. 先筛选信息增益高于平均值的属性;
  2. 再从这些属性中选增益率最高的。

除了信息增益和增益率通过来计算纯度,还有一个重要指标称为基尼指数
其核心思想是:从数据集中随机抽取两个样本,它们属于不同类别的概率(假设样本量足够大,可忽略抽样方式影响)。公式为:

Gini(D)=1i=1Npi2Gini(D) = 1- \sum_{i=1}^{N} p_{i}^2

其中:

  • NN 是类别总数
  • pip_i 是第 ii 类样本的占比
    基尼指数越小,表示随机样本属于同一类的概率越高,即集合纯度越高
    在划分属性时,需计算加权基尼指数以评估划分效果:
Gini_index(D,a)=v=1VDvDGini(Dv)Gini\_index(D,a) = \sum_{v=1}^{V} \frac{|D^v|}{|D|} Gini(D^v)

最终选择使 Gini_index(D,a)Gini\_index(D,a) 最小的属性作为划分标准。
可以看到,基尼指数没有对数运算,所以它计算更快捷;但对数(定义域在(0,1](0,1])对线性变化更敏感,所以增益更适合精细的区分。

4.2 决策树的剪枝处理

在模型训练中,决策树容易因划分类别过多(例如叶子节点样本过少或分支过细)导致过拟合问题。针对该问题,剪枝是当前主流的解决方案,其核心思想是通过主动移除非关键分支合并冗余节点来降低过拟合程度,对应的两个方法即:预剪枝和后剪枝

我们生成的模型最终是为泛化能力服务的,因此需根据性能度量的变化决定是否剪枝。两种策略对比:

  1. 预剪枝

    • 触发时机:在生成决策树时实时判断
    • 逻辑:若当前划分未提升性能度量,立即停止划分并将当前结点标记为叶结点
    • 结果:生成的决策树结点更少、结构更简单
    • 优点
      • 显著降低过拟合风险
      • 减少训练时间(无需生成完整树)
      • 模型更易解释(分支和结点少)
    • 缺点
      • 基于贪心算法,可能因提前终止划分而欠拟合(无法回溯已剪枝的潜在优化路径)
  2. 后剪枝

    • 触发时机先生成完整决策树,再自底向上回溯
    • 逻辑:考察将内部结点的子树替换为叶结点能否提升性能,若可提升则替换完成剪枝
    • 优点
      • 泛化性能更强(充分利用训练数据信息)
    • 缺点
      • 计算开销大(需完整生成树后再遍历剪枝)

4.3 连续值与缺失值

在之前的决策树建模中,我们处理的都是离散型特征(如分类标签)。而现实场景中更常见的是连续型特征(如温度、价格等数值型数据)。本节将说明如何把决策树应用到连续属性上。

首先说明为什么不能直接按属性值划分:对于有限样本集,即使属性是连续的,其观测到的属性值集合也必然是有限的。理论上,每个属性值确实可以作为一个独立划分(例如 x=1.2x=1.3 各对应一个子集),但这种划分会导致分支数量爆炸——若属性值有 NN 个,则可能生成 NN 个子集。如先前所述,这种划分会过度捕捉噪声而非数据规律,显著增加过拟合风险

更优的解决方案是二分法:通过选择一个阈值 tt,将连续属性划分为两个子集(例如 xtx \leq tx>tx > t)。这种方法既能保持划分的有效性,又能控制模型复杂度,从而降低过拟合。

如何选择阈值?我们从现有样本在属性AA上的取值入手,将属性值从小到大排序得到集合{a1,a2,,am}\{a_1,a_{2},\dots,a_{m}\}关键点在于:
只要阈值tt满足ai<t<ai+1a_{i}<t<a_{i+1}(即位于两个相邻属性值之间),就能将数据划分为两个子集:

  • 小于等于aia_i的样本集合DtD_{t}^-
  • 大于aia_i的样本集合Dt+D_{t}^+

由于tt只需满足区间条件,因此通常选择相邻值的平均值作为候选阈值,属性AA候选阈值集合为:

TA={ai+ai+12  1im1}T_{A} = \left\{ \frac{a_{i}+a_{i+1}}{2} \ \bigg|\ 1\leq i \leq m-1 \right\}

既然有了候补阈值,接下来当然就是遍历所有阈值,计算信息增益、增益率或者基尼指数即可。

数据划分方法
除了常见的二分法(将数据划分为两个子集),还可以采用多路划分(将数据划分为多个区间/子集)。但实际应用中,二分法通常已能取得足够好的效果,且实现更简单因此优先推荐二分法

现在我们讨论样本中属性数据缺失的问题。由于数据采集限制法律法规要求隐私保护措施,部分样本的某些属性值会出现空值(即缺失)。如果直接放弃这类样本,会导致数据利用率显著降低。因此,需要采用合适的缺失值处理方法来最大限度利用现有数据。

如果我们需要在决策树构建中处理缺失数据,会面临两个核心问题:

  1. 最优属性划分时如何处理缺失属性的样本
  2. 确定最优属性后,缺失值样本应分配到哪个子集

一个好的解决方案是:

  1. 忽略缺失样本:在计算最优划分属性(如信息增益、基尼指数)时,仅使用完整样本进行评估。
  2. 按比例分配缺失样本:划分子集后,将缺失样本同时分配到所有子集,并根据各子集的样本比例赋予权重,其背后思想是当前子集划分的样本数越多,那么缺失样本在该子集的可能越大。

具体说来,延用之前的符号定义,新设:

  • D~\tilde{D} 表示无缺失值的样本集
  • D~v\tilde{D}^v 表示无缺失样本集中属性AA取值为ava^v的子集
  • D~k\tilde{D}_k 表示无缺失样本集中分类为第kk类的子集

对于每个样本,赋予初始权重 wx=1w_{\mathbf{x}}=1,并定义以下关键比例:

ρ=xD~wxxDwx,p~k=xD~kwxxD~wx,r~v=xD~vwxxD~wx\begin{align} \rho &= \frac{\sum_{\mathbf{x}\in \tilde{D}}w_{\mathbf{x}}}{\sum_{\mathbf{x}\in D}w_{\mathbf{x}}}, \quad \tilde{p}_{k} = \frac{\sum_{\mathbf{x}\in \tilde{D}_{k}}w_{\mathbf{x}}}{\sum_{\mathbf{x}\in \tilde{D}}w_{\mathbf{x}}}, \quad \tilde{r}_{v} = \frac{\sum_{\mathbf{x}\in \tilde{D}^v}w_{\mathbf{x}}}{\sum_{\mathbf{x}\in \tilde{D}}w_{\mathbf{x}}} \end{align}

其中:

  • ρ\rho 为无缺失样本的加权占比
  • p~k\tilde{p}_{k} 为无缺失样本中第kk类的加权比例
  • r~v\tilde{r}_{v} 为无缺失样本中属性A=avA=a^v加权比例

信息增益的推广公式为:

Gain(D,A)=ρGain(D~,A)Gain(D,A) = \rho \cdot Gain(\tilde{D},A)

划分时的缺失值处理:若样本x\mathbf{x}在属性AA上缺失,则将其权重按比例分配为 r~vwx\tilde{r}_{v} w_{\mathbf{x}} 到各子集(对应属性值ava^v)。

4.4 多变量决策树

在传统决策树构建过程中,始终通过选择单变量作为最优划分属性。对于dd维样本空间,叶节点的生成本质上是通过沿单一属性轴进行划分,这等价于在样本空间中生成平行于坐标轴的一小段超平面(例如二维空间中的垂直线/水平线)平面两边对应不同的类。这种划分方式具有强可解释性,但存在明显局限:现实适应性差:当真实决策边界是斜面(如x1+x2=5x_1 + x_2 = 5)时,单变量决策树需用多段if-else规则(平行于轴的曲面)逼近,导致模型复杂度骤增且会分裂出过多子集导致过拟合

若直接使用部分变量的线性组合iwixi\sum_{i}w_{i}x_{i}进行划分(例如采用形如 0.5A+0.7B0.5A + 0.7B 的表达式而非单一变量 AA 的取值,而这个组合也被称为线性分类器),此时决策边界将不再平行于坐标轴。这种方法的优势包括:

  1. 更贴近现实数据的分布规律
  2. 能用更少的结点和更浅的树深表达复杂模型
  3. 潜在提升模型的泛化能力
    这种基于多变量线性组合划分的决策树称为多变量决策树。显然多变量决策树会显著增大计算开销,且要求划分规则更复杂,同时会降低模型解释性

典型的多变量决策树算法包括:

  • OC1(Oblique Classifier 1)
  • 基于线性分类器的最小二乘法
  • 神经网络

本文由博客一文多发平台 OpenWrite 发布!