当前位置: 首页 > news >正文

【人工智能-18】机器学习:决策树、随机森林

上一期【人工智能-17】机器学习:KNN算法、模型选择和调优、朴素贝叶斯分类

文章目录

  • 一、决策树
    • 1.使用理由
    • 2.技术
  • 二、随机森林
    • 1.使用理由
    • 2.原理核心:Bagging + 随机特征子集
    • 3.优点和缺点

一、决策树

决策树是一种监督学习算法,主要用于分类(预测离散标签,如“是/否”、“猫/狗/鸟”)和回归(预测连续值,如房价、温度)任务。

它的模型结构像一棵倒置的树:

  • 根节点 (Root Node): 包含整个数据集,代表最开始要判断的特征。

  • 内部节点 (Internal Node / Decision Node): 代表一个特征或属性上的测试。基于测试结果,数据被分割到不同的子节点。

  • 分支 (Branches): 代表一个特征测试的可能结果(例如,特征“年龄”的分支可能是“年龄<30”和“年龄>=30”)。

  • 叶节点 (Leaf Node / Terminal Node): 代表最终的决策结果(分类标签或回归值)。数据到达叶节点后不再分割。

构建决策树的过程就是通过一系列“如果…那么…”的规则,将复杂的数据集逐步分割成更小、更“纯净”的子集,直到达到停止条件(如子集足够纯净、达到最大深度、包含样本数太少等)。

1.使用理由

高度可解释性: 这是决策树最核心的优势!生成的树结构可以被直观地可视化和理解,决策规则清晰透明(白盒模型),容易向非技术人员解释预测背后的逻辑。这在需要理解模型决策过程的应用中(如金融风控、医疗诊断辅助)至关重要。

对数据预处理要求相对较低:

  • 能直接处理分类特征和数值特征(数值特征需要选择分割点)。

  • 对特征的尺度(量纲)不敏感(因为决策是基于值比较,而不是距离计算)。

  • 对缺失值有一定容忍度(可以通过特定策略处理,如分配到出现频率最高的分支,或单独创建分支)。

能够捕捉特征之间的非线性关系: 通过树的分支结构,可以自然地建模特征之间复杂的相互作用和非线性模式。

计算效率较高(训练和预测): 训练算法(如ID3, C4.5, CART)相对高效,预测新样本的速度非常快,只需要沿着树从根节点走到一个叶节点即可。

2.技术

决策树构建的核心在于如何选择“最佳”特征和分割点来分裂节点,目标是让分裂后的子节点尽可能“纯净”。衡量“纯净度”的标准主要有两种:

  • 基于信息增益 (Information Gain )
    1. 信息熵 (Entropy): 衡量数据集 D 的不确定性(混乱度)。熵越高,表示数据类别越混杂;熵为0,表示所有样本都属于同一类。公式核心思想:对每个类别 k,计算其占比 p_k,然后求和 -p_k * log2(p_k)p_k 越平均(接近0.5),熵越大。
    2. 信息增益 (IG): 衡量使用某个特征 A 对数据集 D 进行分割后,不确定性减少的程度。
      • 计算分裂数据集 D 的熵 H(D)
      • 根据特征 A 的每个可能取值(或分割点)将 D 分成若干子集 D_v
      • 计算分裂所有子集的熵的加权平均值 H(D|A)(权重是子集样本数占总样本数的比例)。
      • 信息增益 IG(D, A) = H(D) - H(D|A)
    3. 特征选择: 选择能带来最大信息增益的特征进行当前节点的分裂。信息增益越大,意味着使用该特征分裂后,子集变得更“纯净”(不确定性降低得最多)。
    4. 缺点: 信息增益倾向于选择取值数目多的特征(如“身份证号”),因为分裂后子集纯度容易更高(极端情况每个样本一个子集,熵为0),但这会导致过拟合且没有泛化能力。
    5. 改进:信息增益率 (Gain Ratio - C4.5算法): 引入一个惩罚项,称为“分裂信息” SplitInfo(A),它衡量按特征 A 分裂时产生的分支数量的多少(分支越多,SplitInfo(A) 越大)。信息增益率 GR(D, A) = IG(D, A) / SplitInfo(A)。这抑制了对取值多特征的偏好。
  • 基于基尼指数 (Gini Index / Gini Impurity )
    1. 基尼指数: 衡量从数据集 D 中随机抽取两个样本,它们属于不同类别的概率。概率越大,基尼指数越高,数据越不纯。公式核心思想:对每个类别 k,计算其占比 p_k,然后求和 1 - Σ(p_k²)p_k 越平均(接近0.5),基尼指数越高(最大0.5);p_k 越偏向0或1(纯),基尼指数越低(最小0)。
    2. 特征选择:
      • 计算分裂数据集 D 的基尼指数 Gini(D)
      • 根据特征 A 的每个可能取值(或分割点)将 D 分成若干子集 D_v
      • 计算分裂所有子集的基尼指数的加权平均值 Gini(D|A)
      • 选择能使 Gini(D|A) 最小(即分裂后子集纯度提升最大)的特征进行分裂。等价于选择能使基尼指数减少量(基尼增益)最大的特征。
    3. 特点: 基尼指数计算比熵稍快(不用算log),实践中效果通常与信息增益/信息增益率相似。CART算法使用基尼指数,并且其构建的树是二叉树(每次分裂只产生两个子节点),对数值特征处理更自然(寻找一个最佳分割点)。
# 决策树 对葡萄酒进行分类
# 基于信息增益的决策树
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
# 获取数据
x,y = load_wine(return_X_y=True)# 划分数据集
x_train,x_test,y_train,y_test = train_test_split(x,y,train_size=0.8,random_state=22)# 模型训练
# 当模型训练时,criterion参数可以指定信息增益的计算方式,默认是gini,也可以指定为entropy
model = DecisionTreeClassifier(criterion='entropy')
model.fit(x_train,y_train)
print('准确率\n',model.score(x_test,y_test))
print('预测结果\n',model.predict(x_test))# 基于基尼指数的决策树
# 当criterion='gini'时,使用基尼指数
gini = DecisionTreeClassifier(criterion='gini')
gini.fit(x_train,y_train)
print('准确率\n',gini.score(x_test,y_test))
print('预测结果\n',gini.predict(x_test))

二、随机森林

  • 随机森林是一种基于Bagging(Bootstrap Aggregating)集成学习思想,并引入了随机特征选择的算法。它的核心是构建多棵决策树(称为“森林”),并通过投票(分类)或平均(回归)的方式结合这些树的预测结果,从而获得比单一决策树更优、更稳定的性能。
  • 简单来说:随机森林 = Bagging + 随机特征子集 + 决策树(通常是CART树)。

1.使用理由

  • 显著提高泛化能力,减少过拟合: 这是使用随机森林最根本的理由。单一决策树容易过拟合。通过集成大量略微不同且不完全过拟合的树,随机森林能够有效地降低模型的方差(Variance),提高在未知数据上的预测精度和鲁棒性。
  • 提升预测准确性和稳定性: 通过“众人智慧”(多棵树投票/平均),随机森林通常能获得比单棵决策树以及其他许多单一模型更高的预测准确率。同时,它对训练数据的小扰动不敏感,结果更稳定。
  • 处理高维特征: 在每棵树分裂节点时只考虑随机选取的部分特征(而不是全部),这在高维数据中非常有效,能降低计算量并减少不相关特征的干扰。
  • 提供特征重要性评估: 随机森林可以方便地计算出每个特征对预测结果的相对重要性,有助于特征选择和理解数据。
  • 保留决策树的部分优点: 虽然可解释性不如单棵树,但仍然能处理混合类型特征、对量纲不敏感、能捕捉非线性关系等。

2.原理核心:Bagging + 随机特征子集

随机森林的训练过程如下:

  1. Bagging (Bootstrap Aggregating):
    • 从原始训练集 D有放回地随机抽取 N 个样本(形成一个Bootstrap样本集 D_i)。这意味着每个样本集 D_i 的大小与 D 相同,但包含重复样本,且平均约有 63.2% 的原始样本会被抽中,剩下的约 36.8% 成为该树的袋外样本 (Out-Of-Bag, OOB),可用于评估该树的性能或特征重要性。
    • 重复上述过程 T 次,得到 T 个不同的 Bootstrap 训练集 {D_1, D_2, ..., D_T}
  2. 构建决策树 (使用随机特征子集):
    • 对于每个 Bootstrap 训练集 D_i,独立地训练一棵决策树。
    • 关键点:在训练每棵树的每个内部节点进行分裂时不是从所有 M 个特征中选择最优特征,而是先随机选取 m 个特征m 通常远小于 M,如 m = sqrt(M)m = log2(M) + 1),然后从这 m 个特征中选择最优特征进行分裂。
    • 让树完全生长或接近完全生长(通常不剪枝或轻微剪枝),以达到低偏差(Bias)。通过集成来降低方差。
  3. 聚合预测 (Aggregation):
    • 分类任务: 对于新样本,让 T 棵树分别进行预测,然后采用多数投票法(Majority Voting)决定最终的类别标签。
    • 回归任务: 对于新样本,让 T 棵树分别进行预测,然后取所有预测值的平均值作为最终预测值。

核心思想:

  • Bagging: 通过 Bootstrap 抽样引入样本扰动,构建多样化的树(减少因数据扰动引起的方差)。
  • 随机特征子集: 在节点分裂时随机选择特征子集,强制树之间产生差异(降低树与树之间的相关性),进一步增加模型的多样性(减少因特征选择相关性引起的方差)。
  • 集成: 结合多个独立、多样化且具有低偏差的弱学习器(树)的预测结果,通过“平均”效应显著降低整体模型的方差,提高泛化能力。
# 随机森林
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split,GridSearchCV# 获取数据
x,y = load_wine(return_X_y=True)# 划分数据集
x_train,x_test,y_train,y_test = train_test_split(x,y,train_size=0.8,random_state=22)# 模型训练
# n_estimators: 树的数量 默认100 max_depth: 树的最大深度 默认None criterion: 决策树属性划分算法选择 默认gini enteropy是信息增益
Model = RandomForestClassifier(n_estimators=100,max_depth=None,criterion='gini') 
param_grid = {'max_depth':[3,5,10,20],'n_estimators':[100,200,300,400,500]}
# 使用超参数网格搜索,寻找最佳参数
enstimators = GridSearchCV(Model,param_grid=param_grid,cv=5)
enstimators.fit(x_train,y_train)# 模型评估
print('准确率:\n',enstimators.score(x_test,y_test))
print('预测结果:\n',enstimators.predict(x_test))# 获取最佳参数
print('最佳参数:\n',enstimators.best_params_)
# 获取最佳模型
print('最佳模型:\n',enstimators.best_estimator_)

3.优点和缺点

  • 优点:
    • 高精度: 通常在分类和回归任务中表现出色,预测准确性高。
    • 鲁棒性强: 对噪声数据和异常值不太敏感。
    • 不易过拟合: 得益于Bagging和特征随机性,即使树很深,整体模型也较难过拟合(相比单棵树)。
    • 处理高维特征: 能有效处理特征数量很多的数据集。
    • 提供特征重要性: 可以评估特征对预测的贡献度。
    • 并行化训练: 每棵树的训练是完全独立的,可以轻松并行化,加速训练过程。
    • 内置验证: 袋外样本 (OOB) 可以用于无偏估计模型的泛化误差,无需额外验证集。
    • 保留决策树部分优点: 处理混合特征、非线性关系等。
  • 缺点:
    • 模型可解释性降低: 虽然比“黑箱”模型(如神经网络)稍好,但由成百上千棵树组成的森林难以直观解释单个预测(牺牲了单棵树的最大优势)。
    • 训练时间和内存消耗较大: 需要训练多棵树,尤其是在树很深或树的数量 T 很大时。预测速度虽然单次很快,但需要遍历所有树,比单棵树慢 T 倍(但仍通常很快)。
    • 可能产生偏差较大的模型: 如果数据噪声很大或特征与目标关系很弱,随机森林可能会学到有偏差的模型(虽然方差低)。
    • 对某些类型的数据关系(如线性关系)可能不如专门模型高效: 虽然能处理,但可能不如线性模型简单直接。
    • 超参数需要调整: 树的数量 T、每次分裂考虑的特征数 m、树的最大深度等超参数需要调整以获得最佳性能(尽管通常比SVM等调参简单,且 T 越大一般越好,但有计算成本)。
http://www.dtcms.com/a/316453.html

相关文章:

  • 什么情况下浮动IP(Floating IP)会“漂移”(Drift)
  • 浮动IP(Floating IP)的删除通常需要满足什么条件
  • 小程序点击菜单栏实现样式动态切换
  • 对于包含大量文件的程序的便捷makefile操作
  • RK3568 Linux驱动学习——字符设备驱动开发
  • windows内核研究(软件调试-内存断点)
  • 永磁同步电机无速度算法--具有电流测量误差鲁棒性的永磁同步电机无传感器控制的自适应广义复矢量观测器
  • 二叉树算法
  • 02-算法
  • Java后端高频面试题
  • EP02:【DL 第二弹】张量的索引、分片、合并以及维度调整
  • 如何选择正确的体育/电竞数据接口服务商?
  • 力扣148:排序链表
  • Android 开发中,HandlerThread、IntentService 和 AsyncTask区别对比
  • Pytorch基础入门2
  • C++面向对象编程基础:从类定义到封装机制详解
  • 【Linux网络编程】socket基础
  • 风丘助力混合动力汽车工况测试:精准采集整车信号解决方案
  • Datawhale AI夏令营 第三期 task2 稍微改进
  • P1026 [NOIP 2001 提高组] 统计单词个数
  • 计算机网络:详解路由器如何转发子网数据包
  • Java JDBC连接池深度解析与实战指南
  • SAP PP CK466
  • 解决docker load加载tar镜像报json no such file or directory的错误
  • jQuery中Ajax返回字符串处理技巧
  • Window.structuredClone() 指南
  • 基于深度学习钢铁表面缺陷检测系统(yolov8/yolov5)
  • 《算法导论》第 3 章 - 函数的增长
  • 本地配置运行https协议
  • Spring依赖注入:从原理到实践的自学指南