sklearn基础篇(七)-- 随机森林(Random forest)

news2025/1/13 10:32:28

        上一节我们提到决策树的一个主要缺点在于经常对训练数据过拟合。随机森林是解决这个问题的一种方法。随机森林是属于集成学习,其核心思想就是集成多个弱分类器以达到一个强分类器的效果。

1 bagging的原理

        随机森林采用Bagging的思想,所谓的Bagging可以用下面这张图表示:

        从上图可以看出,Bagging的弱学习器之间的确没有boosting那样的联系。它的特点在“随机采样”。那么什么是随机采样?

        随机采样(bootsrap)就是从我们的训练集里面采集固定个数的样本,但是每采集一个样本后,都将样本放回。也就是说,之前采集到的样本在放回后有可能继续被采集到。对于我们的Bagging算法,一般会随机采集和训练集样本数m一样个数的样本。这样得到的采样集和训练集样本的个数相同,但是样本内容不同。如果我们对有m个样本训练集做T次的随机采样,,则由于随机性,T个采样集各不相同。

温馨提示:这和GBDT的子采样是不同的。GBDT的子采样是无放回采样,而Bagging的子采样是放回采样。

        对于一个样本,它在某一次含 m m m个样本的训练集的随机采样中,每次被采集到的概率是 1 m \frac{1}{m} m1。不被采集到的概率为 1 − 1 m 1−\frac{1}{m} 1m1。如果 m m m次采样都没有被采集中的概率是 ( 1 − 1 m ) m (1−\frac{1}{m})^m (1m1)m。当 m → ∞ m\to\infty m时, ( 1 − 1 m ) m → 1 e ≈ 0.368 (1−\frac{1}{m})^m\to\frac{1}{e}\approx 0.368 (1m1)me10.368。也就是说,在bagging的每轮随机采样中,训练集中大约有36.8%的数据没有被采样集采集中。

        对于这部分大约36.8%的没有被采样到的数据,我们常常称之为袋外数据(Out Of Bag, 简称OOB)。这些数据没有参与训练集模型的拟合,因此可以用来检测模型的泛化能力。

        bagging对于弱学习器没有限制,这和Adaboost一样。但是最常用的一般也是决策树和神经网络。

        bagging的集合策略也比较简单,对于分类问题,通常使用简单投票法,得到最多票数的类别或者类别之一为最终的模型输出。对于回归问题,通常使用简单平均法,对T个弱学习器得到的回归结果进行算术平均得到最终的模型输出。

        由于Bagging算法每次都进行采样来训练模型,因此泛化能力很强,对于降低模型的方差很有作用。当然对于训练集的拟合程度就会差一些,也就是模型的偏倚会大一些。

        Bagging 的算法描述如下图所示:


2 随机森林算法

        随机森林(Random Forest,以下简称RF)是Bagging算法的进化版,也就是说,它的思想仍然是bagging,但是进行了独有的改进。我们现在就来看看RF算法改进了什么。

        首先,RF使用了CART决策树作为弱学习器。第二,在使用决策树的基础上,RF对决策树的建立做了改进,对于普通的决策树,我们会在节点上所有的 n n n个样本特征中选择一个最优的特征来做决策树的左右子树划分,但是RF通过随机选择节点上的一部分样本特征,这个数字小于 n n n,假设为 n s u b n_{sub} nsub,然后在这些随机选择的 n s u b n_{sub} nsub个样本特征中,选择一个最优的特征来做决策树的左右子树划分。这样进一步增强了模型的泛化能力。

        如果 n s u b = n n_{sub}=n nsub=n,则此时RF的CART决策树和普通的CART决策树没有区别。 n s u b n_{sub} nsub越小,则模型约健壮,当然此时对于训练集的拟合程度会变差。也就是说 n s u b n_{sub} nsub越小,模型的方差会减小,但是偏倚会增大。在实际案例中,一般会通过交叉验证调参获取一个合适的 n s u b n_{sub} nsub的值。

        随机森林本质上是许多决策树的集合,其中每棵树都和其他树略有不同。随机森林背后的思想是,每棵树的预测可能都相对较好,但可能对部分数据过拟合。如果构造很多树,并且每棵树的预测都很好,但都以不同的方式过拟合,那么我们可以对这些树的结果取平均值来降低过拟合。既能减少过拟合又能保持树的预测能力,这可以在数学上严格证明。

        为了实现这一策略,我们需要构造许多决策树。每棵树都应该对目标值做出可以接受的预测,还应该与其他树不同。随机森林的名字来自于将随机性添加到树的构造过程中,以确保每棵树都各不相同。随机森林中树的随机化方法有两种:一种是通过选择用于构造树的数据点,另一种是通过选择每次划分测试的特征。我们来更深入地研究这一过程。

        构造随机森林。想要构造一个随机森林模型,你需要确定用于构造的树的个数(RandomForestRegressor或RandomForestClassifier的n_estimators参数)。比如我们想要构造10棵树。这些树在构造时彼此完全独立,算法对每棵树进行不同的随机选择,以确保树和树之间是有区别的。

        接下来,基于这个新创建的数据集来构造决策树。但是,要对我们在介绍决策树时描述的算法稍作修改。在每个结点处,算法随机选择特征的一个子集,并对其中一个特征寻找最佳测试,而不是对每个结点都寻找最佳测试。选择的特征个数由max_features参数来控制。每个结点中特征子集的选择是相互独立的,这样树的每个结点可以使用特征的不同子集来做出决策。

        由于使用了自助采样,随机森林中构造每棵决策树的数据集都是略有不同的。由于每个结点的特征选择,每棵树中的每次划分都是基于特征的不同子集。这两种方法共同保证随机森林中所有树都不相同。

        在这个过程中的一个关键参数是max_features。如果我们设置max_features等于n_features,那么每次划分都要考虑数据集的所有特征,在特征选择的过程中没有添加随机性(不过自助采样依然存在随机性)。如果设置max_features等于1,那么在划分时将无法选择对哪个特征进行测试,只能对随机选择的某个特征搜索不同的阈值。因此,如果max_features较大,那么随机森林中的树将会十分相似,利用最独特的特征可以轻松拟合数据。如果max_features 较小,那么随机森林中的树将会差异很大,为了很好地拟合数据,每棵树的深度都要很大。


3 sklearn实现

3.1 模型介绍

        在scikit-learn中,RF的分类器是RandomForestClassifier,回归器是RandomForestRegressor。RF的参数也包括两部分,第一部分是Bagging框架的参数,第二部分是一棵CART决策树的参数。具体的参数参考随机森林分类器的函数原型:

sklearn.ensemble.RandomForestClassifier(
        n_estimators=10, criterion='gini',
        max_depth=None,min_samples_split=2, 
        min_samples_leaf=1, min_weight_fraction_leaf=0.0,
        max_features='auto', max_leaf_nodes=None,
        min_impurity_split=1e-07,bootstrap=True,
        oob_score=False, n_jobs=1, 
        random_state=None, verbose=0,
        warm_start=False, class_weight=None)

1. Bagging框架参数

        下面来看看RF重要的Bagging框架的参数,由于RandomForestClassifierRandomForestRegressor参数绝大部分相同,这里会将它们一起讲,不同点会指出。

  • n_estimators: 弱学习器(决策树)的个数。一般来说n_estimators太小,容易欠拟合,n_estimators太大,计算量会太大,并且n_estimators到一定的数量后,再增大n_estimators获得的模型提升会很小,所以一般选择一个适中的数值。默认是100。
  • oob_score:即是否采用袋外样本来评估模型的好坏。默认False。推荐设置为True,因为袋外分数反应了一个模型拟合后的泛化能力。
  • criterion: 即CART树做划分时对特征的评价标准。分类模型和回归模型的损失函数是不一样的。分类RF对应的CART分类树默认是基尼系数gini,另一个可选择的标准是信息增益(information gain)。回归RF对应的CART回归树默认是均方差mse,另一个可以选择的标准是绝对值差mae。一般来说选择默认的标准就已经很好的。

        从上面可以看出, RF重要的框架参数比较少,主要需要关注的是n_estimators,即森林中决策树的个数。

2. 决策树参数
        下面我们再来看RF的决策树参数:

  • RF划分时考虑的最大特征数 max_features: 就是之前提到的“在每个节点处,从M中随机选择m个特征维度”中的那个m。默认是"auto",意味着每个节点在划分时随机考虑 ( n ) \sqrt(n) ( n)个特征;如果是"log2"意味着划分时随机考虑 l o g 2 N log_2N log2N个特征;如果是整数,代表考虑的特征绝对数。如果是浮点数,代表考虑特征百分比,即考虑百分比*总特征维度数取整后的特征数。一般用默认的"auto"就可以了;如果特征数非常多,可以灵活使用刚才描述的其他取值来控制划分时考虑的最大特征数,以控制决策树的生成时间。
  • 决策树最大深度max_depth: 默认可以不输入,如果不输入的话,决策树在建立子树的时候不会限制子树的深度。一般来说,数据少或者特征少的时候可以不管这个值。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。常用的可以取值10-100之间。
  • 内部节点再划分所需最小样本数min_samples_split: 这个值限制了子树继续划分的条件,如果某节点的样本数少于min_samples_split,则不会继续再划分。默认是2。如果样本量数量级非常大,则推荐增大这个值。
  • 叶子节点最少样本数min_samples_leaf: 这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝,只保留原来的父节点。默认是1。如果样本量数量级非常大,则推荐增大这个值。
  • 叶子节点最小的样本权重和min_weight_fraction_leaf:这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝,只保留原来的父节点。 默认是0,就是不考虑权重问题。如果我们有较多样本有缺失值,或者分类树样本的分布类别非常不平衡,就会引入样本权重,这时我们就要注意这个值了。
  • 最大叶子节点数max_leaf_nodes: 通过限制最大叶子节点数,可以防止过拟合,默认是"None”,即不限制最大的叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征非常多的话,可以加以限制,具体的值可以通过交叉验证得到。
  • 节点划分最小不纯度min_impurity_split: 这个值限制了决策树的增长,如果某节点的不纯度(基于基尼系数,均方差)小于这个阈值,则该节点不再生成子节点。即为叶子节点 。一般不推荐改动,默认值1e-7。

        上面决策树参数中最重要的包括最大特征数max_features, 最大深度max_depth, 内部节点再划分所需最小样本数min_samples_split和叶子节点最少样本数min_samples_leaf

3.2 案例分析

        导入常用的库:

import mglearn
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

        下面将由5棵树组成的随机森林应用到前面研究过的two_moons数据集上:

from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split


X, y = make_moons(n_samples=100, noise=0.25, random_state=3)
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=42)

forest = RandomForestClassifier(n_estimators=5, random_state=2)
forest.fit(X_train, y_train)

        作为随机森林的一部分,树被保存在estimator_属性中。我们将每棵树学到的决策边界可视化,也将它们的总预测(即整个森林做出的预测)可视化。

fig, axes = plt.subplots(2, 3, figsize=(20, 10))
for i, (ax, tree) in enumerate(zip(axes.ravel(), forest.estimators_)):
    ax.set_title("tree {}".format(i))
    mglearn.plots.plot_tree_partition(X_train, y_train, tree, ax=ax)

mglearn.plots.plot_2d_separator(forest, X_train, fill=True, ax=axes[-1, -1], alpha=.4)
axes[-1, -1].set_title("Random Forest")
mglearn.discrete_scatter(X_train[:, 0], X_train[:, 1], y_train)

        可以清楚地看到,这5棵树学到的决策边界大不相同。每棵树都犯了一些错误,因为这里画出的一些训练点实际上并没有包含在这些树的训练集中,原因在于自助采样。

        随机森林比单独每一棵树的过拟合都要小,给出的决策边界也更符合直觉。在任何实际应用中,我们会用到更多棵树(通常是几百或上千),从而得到更平滑的边界。

        我们将包含100棵树的随机森林应用在乳腺癌数据集上:

from sklearn.datasets import load_breast_cancer

cancer = load_breast_cancer()

X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, random_state=0)
forest = RandomForestClassifier(n_estimators=100, random_state=0)
forest.fit(X_train, y_train)

print("Accuracy on training set: {:.3f}".format(forest.score(X_train, y_train)))         
print("Accuracy on test set: {:.3f}".format(forest.score(X_test, y_test)))              

Accuracy on training set: 1.000
Accuracy on test set: 0.972

        在没有调节任何参数的情况下,随机森林的精度为97%,比线性模型或单棵决策树都要好。我们可以调节max_features 参数,或者像单棵决策树那样进行预剪枝。但是,随机森林的默认参数通常就已经可以给出很好的结果。

        与决策树类似,随机森林也可以给出特征重要性,计算方法是将森林中所有树的特征重要性求和并取平均。一般来说,随机森林给出的特征重要性要比单棵树给出的更为可靠。

def plot_feature_importances_cancer(model):
    n_features = cancer.data.shape[1]
    plt.barh(range(n_features), model.feature_importances_, align='center')
    plt.yticks(np.arange(n_features), cancer.feature_names)
    plt.xlabel("Feature importance")
    plt.ylabel("Feature")

plot_feature_importances_cancer(forest)

        与单棵树相比,随机森林中有更多特征的重要性不为零。与单棵决策树类似,随机森林也给了“worst radius”(最大半径)特征很大的重要性,但从总体来看,它实际上却选择“worst perimeter”(最大周长)作为信息量最大的特征。由于构造随机森林过程中的随机性,算法需要考虑多种可能的解释,结果就是随机森林比单棵树更能从总体把握数据的特征。


小结

RF的主要优点有:

  • 训练可以高度并行化,对于大数据时代的大样本训练速度有优势。个人觉得这是的最主要的优点。
  • 由于可以随机选择决策树节点划分特征,这样在样本特征维度很高的时候,仍然能高效的训练模型。
  • 在训练后,可以给出各个特征对于输出的重要性
  • 由于采用了随机采样,训练出的模型的方差小,泛化能力强。
  • 相对于Boosting系列的Adaboost和GBDT,RF实现比较简单。
  • 对部分特征缺失不敏感。

RF的主要缺点有:

  • 在某些噪音比较大的样本集上,RF模型容易陷入过拟合。
  • 取值划分比较多的特征容易对RF的决策产生更大的影响,从而影响拟合的模型的效果。

参考

  • Bagging与随机森林算法原理:https://www.cnblogs.com/pinard/p/6156009.html
  • 随机森林(Random Forest):https://blog.csdn.net/qq_34106574/article/details/82016442
  • 随机森林:https://www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm#inter

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/10731.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HDFS的高级功能

3.6 HDFS的高级功能 3.6.1 安全模式 安全模式(Safemode)是HDFS所处的一种特殊状态。处于这种状态时,HDFS只接受读数据请求,不能对文件进行写、删除等操作。安全模式是保证一个系统保密性、完整性及可使用性的一种机制&#xff0…

精彩回顾:CACTER邮件数据防泄露EDLP亮相2022世界互联网大会

2022年世界互联网大会乌镇峰会于11月11日胜利闭幕。 本届峰会是世界互联网大会国际组织成立后的首届年会,以“共建网络世界 共创数字未来—携手构建网络空间命运共同体”为主题,共设置1场全体会议和20场分论坛,围绕全球网络空间热点问题展开讨…

【猿创征文】Vue3 企业级优雅实战 - 组件库框架 - 6 搭建example环境

本系列已更新文章: 分享一个实用的 vite vue3 组件库脚手架工具,提升开发效率 开箱即用 yyg-cli 脚手架:快速创建 vue3 组件库和vue3 全家桶项目 Vue3 企业级优雅实战 - 组件库框架 - 1 搭建 pnpm monorepo Vue3 企业级优雅实战 - 组件库框架…

线程池相关总结

多线程之线程池总结 1. 概述: 线程池(Thread Pool):把一个或多个线程通过统一的方式进行调度和重复使用的技术,统一管理,避免了因线程过多而带来使用上的开销和不可控。 作用: 降低资源消耗…

SpringBoot进阶学习(二)---配置高级

第三方bean属性绑定 在要绑定的类上添加ConfigurationProperties(prefix “”)&#xff0c;prefix为对应的配置类中的内容&#xff0c;在添加注解ConfigurationProperties时候会产生错误&#xff0c;如&#xff1a; 这时候添加依赖&#xff1a; <dependency><groupI…

计算机网络 5 - 链路层

第6章 链路层和局域网(Link Layer and LANs)6.2 差错检测 和 纠正奇偶校验校验和CRC 循环冗余校验6.3 多路访问协议信道划分 MAC协议随机存取MAC协议6.4 LAN 局域网MAC地址 和 ARP无效的MAC帧格式Ethernet 以太网交换机第6章 链路层和局域网(Link Layer and LANs) 6.2 差错检测…

H5基本开发1——(H5简单概述)

html概述 HTML是用来描述网页的一种语言 HTML指的是超文本标记语言Hyper Text Markup Language&#xff0c;是一种用于创建网页的标准标记语言 标记语言是一套标记标签markup tag HTML使用标记标签来描述网页 HTML文档的后缀名&#xff1a;.html或者.htm&#xff0c;两种后缀名…

Deep Leakage from Gradients

Summary 对于分布式学习&#xff0c;特别是相关之前共享梯度的学习&#xff0c;提出了一种攻击方式&#xff08;DLG&#xff09;。通过窃取client之间传递的梯度反推出&#xff08;也是使用机器学习迭代的方式&#xff09;原始的输入。并在图像分类、Masked Language Model方面…

代谢ADMET在线网页预测工具SwissADME 、SOMP 、BioTransformer

药物代谢(Drug Metabolism)指药物在体内多种药物代谢酶&#xff08;尤其肝药酶&#xff09;的作用下&#xff0c;化学结构发生改变的过程&#xff1b;包括分解代谢和合成代谢 1、概念 药物的代谢反应大致可以分为氧化(oxidation)、还原(reduction)、水解(hydrolysis)和结合(co…

Android 增加布局圆角功能,支持背景裁切圆角

前言 我们Android开发同学最常见、频繁画UI时会遇到有角度的布局。例如: 通常,我们都会在drawble文件夹下创建Shape.xml去实现对吧?当然这样的代码实现方式没毛病。但是,项目大了业务繁杂,工程中会出现很多此类文件,显得非常臃肿,而且不方便复用,不利于研发效率…

22、7大参数自定义线程池(核心线程数,最大核心线程数。。。拒绝策略(4种))

7大参数自定义线程池&#xff08;核心线程数&#xff0c;最大核心线程数。。。拒绝策略&#xff08;4种&#xff09;&#xff09; 第一步&#xff1a;我们首先看单例线程池的源码 第二步&#xff1a;多个固定线程的线程池源码 第三步&#xff1a;可变的线程数的线程池源码 开启…

相控阵天线(三):直线阵列低副瓣综合(切比雪夫、泰勒分布、SinZ-Z和Villeneuve分布)

目录阵列天线综合方法概述切比雪夫阵列综合泰勒阵列综合高斯分布、二项式分布、SinZ-Z和Villeneuve分布切比雪夫、泰勒和Villeneuve综合比较切比雪夫、泰勒和Villeneuve分布的口径效率比较切比雪夫综合python代码示例阵列天线综合方法概述 直线阵列天线的综合是在预先给定辐射…

C++15 ---继承2:重载与覆盖、隐藏、拷贝构造函数、赋值运算符重载、静态数据成员

一、重载与覆盖的特征 1、重载 成员函数被重载的特征: (1&#xff09;相同的范围&#xff08;在同一个类中)&#xff1b; (2&#xff09;函数名字相同&#xff1b; (3&#xff09;参数不同&#xff1b; (4&#xff09; virtual关键字可有可无。 2、覆盖 覆盖是指派生类函数…

STM32CubeMX环境安装(保姆级)

目录 JAVA环境安装 安装包 文件夹设置 运行exe STM32CubeMX下载 第一步 第二步 第三步 第四步 第五步 第六步 第七步 第八步 注意&#xff0c;我们使用STM32CubeMX需要安装JAVA环境&#xff01;&#xff01;&#xff01; JAVA环境安装 安装包 JAVA下载链接&…

《FFmpeg Basics》中文版-02-显示帮助和功能

正文 关于FFmpeg程序的帮助和其他信息都显示在空格和连字符之后输入的各种选项&#xff0c;示例显示了FFmpeg工具的用法&#xff0c;但是相同的选项对于ffplay、ffprobe和ffserver是有效的。参数是区分大小写的。FFmpeg组件的开发速度很快&#xff0c;从2012年11月开始&#x…

MicroPython——有点东西,但是不多

引言 之前做过一个树莓派驱动墨水屏的项目&#xff0c;本来想整理出来与大家分享的&#xff0c;但是由于树莓派已经成了理财产品&#xff0c;所以为了让这个项目更加具有实践意义&#xff0c;最近我打算把这个项目移植到ESP32上。在树莓派上我使用的是Python编写的代码&#x…

C++简单工厂模式详解

C简单工厂模式详解1.问题引入2.编写代码思路的迭代2.1 main函数主体内编写全部代码2.2 修改上述问题后的main函数代码2.3 引入面向对象后的代码2.4 加上继承和多态后的代码3.C简单工厂代码4.总结4.1 简单工厂模式适用场景4.2收获1.问题引入 编写一个计算器程序代码&#xff0c…

论文笔记:Region Representation Learning via Mobility Flow

2017 CIKM 1 摘要和介绍 使用出租车出行数据学习区域向量表征 同时考虑时间动态和多跳位置转换——>通过flow graph和spatial graph学习表征出租车交通流可以作为区域相似度的一种 A区域和B区域之间流量大 ——>A和B的特征更相关——>用一个/很相似的vector来表征他…

如何实现基于场景的接口自动化测试用例?来看看大佬的方案

自动化本身是为了提高工作效率&#xff0c;不论选择何种框架&#xff0c;何种开发语言&#xff0c;我们最终想实现的效果&#xff0c;就是让大家用最少的代码&#xff0c;最小的投入&#xff0c;完成自动化测试的工作。 基于这个想法&#xff0c;我们的接口自动化测试思路如下…

R语言七天入门教程七:项目实战

R语言七天入门教程七&#xff1a;项目实战 在完成之前R语言基础知识的学习后&#xff0c;今天的内容是项目实战&#xff0c;通过完成一些小项目来巩固知识。 一、矩阵运算计算器&#xff08;变量与运算符练习&#xff09; 1、问题描述 给定矩阵A和B&#xff0c;计算矩阵相加…