随机森林原理和性能分析

news2024/11/25 16:50:35

文章目录

  • 随机森林入门
  • 构造随机森林
  • 随机森林性能
  • 随机森林特点

随机森林入门

决策树入门、sklearn实现、原理解读和算法分析中针对决策树进行了详细的描述,但是其只考虑了一颗决策树的情况。俗话说,三个臭皮匠,顶个诸葛亮。本文将研究如何通过组合多颗决策树的方式,进一步提升模型的效果,即随机森林。

为了理解清楚随机森林算法背后的原理,我们先来看一个非常简单但却很有意思的实例:有3位法官需要判断被告是否有罪,最终的判断结果使用少数服从多数的方式确定。

假设每位法官判断正确的概率均为 p p p,如果只有1位法官,那么该法官判断正确的概率就是 p p p

当法官数量增加至3位时,最终能够判断正确的情况有两种:一种是3位法官均判断正确,另一种是只有一位法官判断错误,其余两位则判断正确。其总概率为
p 3 + 3 p 2 ( 1 − p ) p^3+3p^2(1-p) p3+3p2(1p)

只有3位法官判断正确的概率高于1位法官判断正确的概率时,增加法官数量才是有意义的,此时
p 3 + 3 p 2 ( 1 − p ) > p p^3+3p^2(1-p)>p p3+3p2(1p)>p
化简得到
p ( p − 1 ) ( p − 0.5 ) < 0 p(p-1)(p-0.5)<0 p(p1)(p0.5)<0
因为 p p p的基本约束是 0 ≤ p ≤ 1 0≤p≤1 0p1,结合上式可以将约束条件变为
0.5 < p < 1 0.5 < p < 1 0.5<p<1

也就是说,只要单位法官判断正确的概率超过0.5,那么增加法官数量后,就可以进一步提升判断正确的概率。

除了概率约束,上述推导过程中还隐含了另外两个约束:(1)法官们各自做独立判断,互不影响,这是计算3位法官判断正确的概率的基本前提;(2)法官对表决对象拥有共同目标,因为如果有法官有意包庇罪犯,可能会故意给出错误判断。

事实上,已经有一个定理针对该情况进行了描述,即孔多塞陪审团定理:总数为奇数的一组人(模型)将未知的世界状态分为真或假。每个人(模型)正确分类的概率为 p > 0.5 p>0.5 p>0.5,并且任何一个人(模型)分类正确的概率在统计上独立于其他人(模型)分类的正确性。定理便可以描述为:多数投票正确的概率比任何人(模型)都更高;当人数(模型数)变得足够大时,多数投票的准确率将接近100%。

构造随机森林

将孔多塞陪审团定理应用到随机森林算法中:只要多颗树是相互独立的,并且每棵树预测正确的概率超过0.5,那么随机森林算法的效果就能优于单颗决策树。

单颗决策树预测正确的概率超过0.5大概率是正确的,因为随机猜测的正确概率已经是0.5,有了训练集的学习后,可以预期其判断正确的概率超过0.5。

实现多棵树为互相独立的方式是:
(1) 通过自助采样(bootstrap sample)策略生成不同且相互独立的数据集。其具体流程如下:从原数据集中有放回地(即同一样本可以被多次抽取)重复随机抽取一个样本,抽取次数与原数据集数量相同,这样会创建一个与原数据集大小相同的数据集,但有些数据点会缺失(缺失量大约37%),有些会重复。
(2) 基于新创建的数据集来构造决策树,但是要对我们在介绍决策树时所描述的算法稍作修改。在每个结点处,算法随机选择特征的一个子集,并对其中一个特征寻找最佳测试,而不是对每个结点都寻找最佳测试。选择的特征个数由max_features参数来控制。每个结点中特征子集的选择是相互独立的,这样树的每个结点可以使用特征的不同子集来做出决策。

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

想要利用随机森林进行预测,首先需要对森林中的每棵树进行预测。此后,对于回归问题,我们对这些结果取平均值作为最终预测。对于分类问题,则采用“软投票”(soft voting)策略。也就是说,每个算法做出“软”预测,给出每个可能的输出标签的概率,对所有树的预测概率取平均值,然后将概率最大的类别作为预测结果。

以下为使用随机森林求解预测问题时的流程图。

随机森林性能

我们先通过可视化看一下随机森林和每一颗决策树的结果。以下为使用sklearn包的实现代码。

import mglearn.plots
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

from data import two_moons


if __name__ == '__main__':
    X, y = two_moons.two_moons()
    # 数据集拆分
    X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
    # 创建一个随机森林分类器,包含 5 棵树,随机种子为 2
    forest = RandomForestClassifier(n_estimators=5, random_state=2)
    # 使用训练数据拟合模型
    forest.fit(X_train, y_train)

    # 创建一个 2x3 的图像,用于显示每棵树的分割情况
    fig, axes = plt.subplots(2, 3, figsize=(20, 10))
    # 遍历每棵树,显示其分割情况
    for i, (ax, tree) in enumerate(zip(axes.ravel(), forest.estimators_)):
        ax.set_title('Tree {}, score {:.2f}'.format(i, forest.estimators_[i].score(X_train, y_train)))
        # 绘制决策树
        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=0.4)
    axes[-1, -1].set_title('Random Forest, , score {:.2f}'.format(forest.score(X_train, y_train)))
    # 在前两个子图中显示训练数据的散点图
    mglearn.discrete_scatter(X_train[:, 0], X_train[:, 1], y_train)

运行代码后,可以得到下图。随机森林模型的结果,肉眼可见地优于一颗颗独立的决策树。从得分上来看,5颗决策树的值分别为0.88、0.93、0.93、0.95和0.84,而随机森林却将得分进一步提升到了0.96。

计算特征重要性就简单多了,一行代码就行:

forest.feature_importances_

以下为输出结果

array([0.38822127, 0.61177873])

在使用单决策树求解时,我们当时提到,重要性值分别为0.1478和0.2138。

看起来差异好像挺大,但其实是因为当时没有对重要性值做归一化处理。归一化后,第一个特征的重要性值为:
0.1478 / ( 0.1478 + 0.2138 ) = 0.4087 0.1478 / (0.1478 + 0.2138)=0.4087 0.1478/(0.1478+0.2138)=0.4087
第二个特征的重要性值为:
0.2138 / ( 0.1478 + 0.2138 ) = 0.5913 0.2138 / (0.1478 + 0.2138) = 0.5913 0.2138/(0.1478+0.2138)=0.5913
现在看起来,两种方法下的差异就没那么大了。

随机森林特点

从本质上看,随机森林拥有决策树的所有优点。此外,在模型训练过程中,每一颗决策树的训练都可以并行执行,从而提升训练效率。

需要调节的重要参数有n_estimators和max_features。n_estimators指的是决策树数量,其总是越大越好。对更多的树取平均可以降低过拟合,从而得到鲁棒性更好的预测模型。不过收益是递减的,而且树越多需要的内存也越多,训练时间也越长。常用的经验法则就是“在你的时间/内存允许的情况下尽量多”。

max_features指的是每颗决策树所使用的特征数量。较小的max_features可以降低过拟合。一般来说,好的经验就是使用默认值:对于分类,默认值是max_features=sqrt(n_features);对于回归,默认值是max_features=n_features。

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

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

相关文章

C++:深入理解多态,多态实现原理及拓展

文章目录 1. 理解虚表1.1 虚表1.2 验证1.3 子类虚表1.4 相同类不同对象的虚表 2. 静态绑定和动态绑定2.1 静态绑定2.2 动态绑定 3. 多态的实现原理3.1 向上转型3.2 多继承3.3 原理 4. 拓展4.1 构造函数能不能是虚函数4.2 父类和子类的析构函数在底层的命名问题4.3 对象之间无法…

[论文阅读] (30)李沐老师视频学习——3.研究的艺术·讲好故事和论点

《娜璋带你读论文》系列主要是督促自己阅读优秀论文及听取学术讲座&#xff0c;并分享给大家&#xff0c;希望您喜欢。由于作者的英文水平和学术能力不高&#xff0c;需要不断提升&#xff0c;所以还请大家批评指正&#xff0c;非常欢迎大家给我留言评论&#xff0c;学术路上期…

SpringMVC第十一阶段:SpringMVC 拦截器执行源码解析

SpringMVC 拦截器执行源码解析&#xff1a; 1、执行doDispatcher做请求分发处理 1.1、调用getHandler()获取请求处理器&#xff0c;处理器中包含请求的方法和拦截器信息 getHandlerInternal() 根据请求地址获取对应的目标方法getHandlerExecutionChain() 获取请求地址对…

(转载)基于鱼群算法的函数寻优算法(matlab实现)

1 理论基础 1.1 人工鱼群算法概述 人工鱼群算法是李晓磊等人于2002年提出的一类基于动物行为的群体智能优化算法。该算法是通过模拟鱼类的觅食、聚群、追尾、随机等行为在搜索域中进行寻优&#xff0c;是集群体智能思想的一个具体应用。生物的视觉是极其复杂的&#xff0c;它…

Java006——对第一个Java程序HelloWorld的简单介绍

一、HelloWorld.java程序整体认识 public class HelloWorld { //创建一个名字叫HelloWorld的类&#xff08;Java中的类叫class&#xff09;public static void main(String[] args) {//主程序入口&#xff0c;类似C语言main函数System.out.println("He…

python之scipy.signal重采样

前言 在复现LiftingNet过程中&#xff0c;了解到作者对于不同转速设备的机械信号进行重采样来矫正转速&#xff0c;也就是固定长度的样本包含了相同旋转周期的设备信息&#xff0c;而非相同时间长度。po一下原文&#xff1a; 这里其实用到了阶次分析的原理&#xff0c;该样本…

【vue】生命周期,组件,插槽,依赖注入,实现分页器组件,异步组件,keep-alive

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录 生命周期总结组件例子轮播图组件 在组件中使用v-modelMixin插槽具名插槽实现一个分页器 依赖注入…

【软件测试】软件测试总结笔记(1)

软件测试理论总结 1.Introduction1.1 What is Software Bug1.2 Tester的职责和目标其他概念软件测试的分类 2.软件开发生命周期Software Development ProcessSoftware Development Lifecycle ModelsTDD - Test-Driven Development测试驱动开发&#xff08;一种敏捷开发&#x…

城市微博签到数据分享地址解码与纠偏教程

收录于合集 #开源4个 #GIS34个 #社交媒体2个 #大数据4个 哈喽大家好&#xff0c;我又来啦&#xff01;最近一直有小伙伴私戳问我要 签到数据&#xff0c;本着 开源共享的精神&#xff0c;我这次给大家分享中国多个城市2022年9月的匿名签到数据&#xff0c;欢迎大家点击在看…

用Python做兼职,轻松赚取零花钱,分享Python兼职经验

文章目录 前言一、技术方案二、接单流程三、注意事项四、总结 前言 某家电商公司需要从竞争对手的网站上获取商品信息&#xff0c;以便更好地了解市场情况和竞争对手的策略。由于该公司没有专门的技术团队&#xff0c;因此他们需要找一家专业的爬虫服务公司来帮助他们完成这项…

冈萨雷斯DIP第4章知识点

文章目录 4.1 背景4.3 取样和取样函数的傅里叶变换4.5 二变量函数的傅里叶变换4.6 二维 DFT 和 IDFT 的一些性质4.6.6 二维离散卷积定理 4.7 频率域滤波基础4.7.3 频率域滤波步骤小结4.7.4 空间域和频率域滤波之间的对应关系 4.8 使用低通频率域滤波器平滑图像4.9 使用高通滤波…

Nacos作为服务注册中心简单示例

一、服务注册与发现场景 主要包含两个服务&#xff1a; zhshl-order服务: 作为服务消费者zhsl-stock服务: 作为服务提供者 当我们启用服务发现的时候,需要进行的操作主要有三步 0、前置条件,需要先搭建好一个nacas服务&#xff0c;可以是一个集群或者是单个nacos服务。可以…

MySQL 数据定义语言 DDL

文章目录 数据定义语言 DDL表的设计范式第一范式&#xff08;1NF&#xff09;第二范式&#xff08;2NF&#xff09;第三范式&#xff08;3NF&#xff09; 创建表修改表删除表截断表 数据定义语言 DDL 前面我们学习的 DML 语言&#xff0c;主要实现对数据的增、删、改等基本操作…

零基础入门网络安全必看的5本书籍(附书单pdf)

作为一个Java转行网络安全的过来人&#xff0c;我深知自学时的种种不易&#xff0c;同时也经常有粉丝朋友问我&#xff1a;刚入门应该怎么学、有哪些书籍推荐等问题&#xff0c;今天我就把我自己的学习书单分享给大家&#xff0c;希望对大家有帮助&#xff01; 一、5本必读书籍…

JVM垃圾回收——对象进入老年代

目录 1、什么是大对象以及大对象对垃圾回收的影响 2、什么情况下对象会进入老年代 2.1 当创建对象的大小超过-XX:PretenureSizeThreshold的设定值 2.2 长期存活的对象将进入老年代 2.3 动态年龄判定 2.4 空间担保分配 什么是空间分配担保&#xff1f; 为什么要…

uploads靶场通关(1-11关)

Pass-01&#xff08;JS校验&#xff09; 看题目我们准备好我们的php脚本文件&#xff0c;命名为1.php 上传该php文件&#xff0c;发现上传失败 方法一&#xff1a;将浏览器的JavaScript禁用 然后就能上传了 方法二&#xff1a; 查看源码&#xff0c;发现只能上传以下形式的文…

【Docker】LXC所实现的隔离性、Linux Namespace等讲解

前言 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 &#x1f4d5;作者简介&#xff1a;热…

域名解析异常有哪些办法?如何实现动态域名解析?

什么是域名解析&#xff1f; 域名解析就是把域名解析成一个ip地址&#xff0c;我们大多数人都喜欢记忆域名&#xff0c;但是机器只认识IP地址&#xff0c;只要这个IP地址对应相关域名&#xff0c;这就叫域名解析。 工作中常会遇到域名解析故障&#xff0c;比如访问站点对应的…

FPGA问答系列--Vivado Schematic中的实线和虚线有什么区别?

FPGA问答系列–Vivado Schematic中的实线和虚线有什么区别&#xff1f; 前言&#xff1a;本文章为FPGA问答系列&#xff0c;我们会定期整理FPGA交流群&#xff08;包括其他FPGA博主的群&#xff09;里面有价值的问题&#xff0c;并汇总成文章&#xff0c;如果问题多的话就每周…

ChatPPT一键制作PPT,效果拉满!

&#x1f4a7; C h a t P P T 一键制作 P P T &#xff0c;效果拉满&#xff01; \color{#FF1493}{ChatPPT一键制作PPT&#xff0c;效果拉满&#xff01;} ChatPPT一键制作PPT&#xff0c;效果拉满&#xff01;&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我…