随机森林RandomForest详解(分类森林与回归森林),以及手把手教学案例实现,图文并茂帮助你从0了解随机森林(超级详细,0基础快速上手!)

       自己原创总结,难免有错误不严谨之处,请大家理解,并欢迎指出 :)

        代码链接代码仓库(Github)

       有疑问或者错误欢迎讨论在评论区,或者Email: yuhan.huang@whu.edu.cn

        在今天,我们将会对于随机森林进行一个详解与案例展现。我们需要注意的是,随机森林是根据决策树构建的。因此,如果你对于决策树(DecisonTree)的原理不是非常了解,请先去看我之前写的两篇博客,并自己动手完成相关代码。文章链接:

决策分类树icon-default.png?t=N7T8https://blog.csdn.net/m0_62716099/article/details/141130329

决策回归树icon-default.png?t=N7T8https://blog.csdn.net/m0_62716099/article/details/141140806

  原理

        注意,以下内容是对于Youtube博主StatQuest的内容总结,有兴趣的同学可以去看原文,当然我还是要注意:我在这里写原理只是为了让大家对于算法本身有一点理解,但我们并不需要熟练掌握数学原理,因为sklearn已经给我们封装的很好了,更重要的在于会用。视频链接:StatQuest:RandomForests

        随机森林的理解其实也是比较简单。我们可以类比森林与树的关系,树是一颗,森林则是一群树 --> 随机森林则是多个决策树结果的一个统计计算。这样大家就可以对于随机森林的工作流程有一个初步的印象。大致工作流如下:

        在这里,由于工作流程还是存在一些不同点,因此我还是简单的讲解一下过程。

Bagging(BoostStrap Aggregating)          -- 一个专业名词解释

        Bagging,全程Bootstrap Aggregating,中文称作袋装法是一种集成学习技术。其核心思想就是构建多个模型,然后通过某种方式(通常来说是平均或多数投票)整合这些模型的分类(预测)结果。我们可以通过下面的图对其过程中的专业名词进行理解。而随机森林模型就是一个典型的袋装法模型。

Bootstrap采样(自举采样)

        大家一开始看见这个词可能有点陌生,不过无所谓,这只是一个专业术语,你了解下面我给你说的过程就好了。这个方法在实际的工作中显示出了优越性,因此被应用于随机森林的样本采集中。

        或许有的同学会提问了,我们在模型训练前不已经把数据处理好并划分训练集和测试集了吗,怎么又搞出来个采样呢?让我来给你解释,我们知道,在随机森林中,我们是对于多个决策树进行训练。在随机森林中,我们并不是给每一个决策树(基树)相同的数据集进行训练,对于每一个树,我们会利用自举采样给其采样一个特殊的数据集用于训练。下面我们就全用Bootstrapping来代表这个采样了。p_i = \frac{1}{n}

        Bootstrapping是一种有放回的采样,其数据集的大小是与原本的数据集的大小是一致的。其主要流程如下:

        1. 从原来的数据集中随机采样一个数据,并将其放回原本的数据集中(即原本数据集不会发生变化)。

        2. 随机采样N次(N是原来数据集的样本数),这样就为一个基类(决策树)创建了样本集。

        3. 为随机森林中的每一个决策树创建数据集。

        其大致工作流程如下,我们不需要自己实现,sklearn已经封装好了。但是我们还是需要了解一个概念:在对于一个决策树的样本采样中,我们会采样N次,每一次中对于某一个样本的采样概率为:

p_i = \frac{1}{n}

        那么,在N次采样中这个样本会被采样到的概率即为 

p = 1 - (1 - \frac{1}{n})^n

        如何理解呢? Pi(就是n分之1,主要是我懒得打公式了)这个概率代表的是一次采样中被选中的概率, 1 - pi就是不被选中的概率,n次方代表所有采样中都没有被选中的概率,那1减去这个概率不就是会被选中的概率了吗。这是一种逆向思维。我们绘制出被选中概率随样本数量n增加而变化的散点图,代码如下:

# plot line of y = 1 - (1 - 1/n)**n
steps = 100
y = [1 - (1 - 1/n)**n for n in list(range(1, steps+1))]
plt.scatter(range(1, steps+1), y, s=1)
# 设置x轴的刻度,从1开始,以1为间隔
plt.xticks([1] + list(range(10, steps+1, 10)))
plt.show()

        我们可以看见,随着样本的增加,很快其被选中的概率变下降为2/3左右,并在后面一直保存在这个值左右。因此我们可以认为:bootstrapping得到的样本实际上只有原来样本的三分之二,另外三分之一的样本是没有参与到该决策树的训练的。所以在某些情况下,我们的随机森林可以不划分训练集和测试集,对于一个决策树,可以对其未参与训练的三分之一的数据进行测试。这个测试结果在sklearn的随机森林模型中,以oob_score的参数决定。不过还是建议大家正儿八经的训练测试,我不是很懂他这个score内部的计算逻辑。

森林的训练

        随机森林的训练其实也就是每一棵决策树的训练。但是与决策树的训练不同的是,随机森林里树的训练,每一步并不会对于所有特征进行计算,然后判断出用什么特征进行结点的分割。这里我们直接看sklearn官方文档的解释:默认是随机选择根号下你的特征数个特征(sqrt(n_features))进行不纯度或者误差和的计算,然后在这sqrt(n_features)个特征中选择出最好的特征进行分割

模型的应用

        把随机森林训练完后,接下来的步骤就很简单了,对于输入的特征,森林里的每一个决策树都进行一次判断,然后把所有树的结果进行变换,得到最终结果,至于是什么变换,你别管,反正人家已经封装好了(^ ^)。

代码实现(python实现,jupyter环境)

首先我们需要导入所需要的包。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import sklearn
%matplotlib inline

RandomForestsClassifier实现

        一个模型的实现就是这么简单,只需要这么几行代码,至于参数的调整,我们根据不同的数据要有不同的调整策略,我还是建议大家去看一下官方文档,包括rfc这个sklearn的自定义类,里面也有很多属性,可以给我们展示出树的更多信息,比如rfc.estimators_, 就可以给我们看出森林里所有树的信息。这些是很有用的。大家自己要有看文档的能力,不然不会有提升的。RandomForestsClassifier官方接口文档

# load wine datasets (3 classes)
wine_data = datasets.load_wine()
train_X, test_X, train_Y, test_Y = train_test_split(wine_data.data, wine_data.target, test_size=0.33, random_state=42)

rfc = ensemble.RandomForestClassifier(
    random_state=42
)
rfc = rfc.fit(train_X, train_Y)
rfc.score(test_X, test_Y)

        接下来我们用交叉验证跟普通的决策树进行对比。主要是利用10折交叉验证,看看不同数据分布下决策树与随机森林的效果差异有多大

# compared with decision tree
dtc = sklearn.tree.DecisionTreeClassifier(random_state=42)
rfc = ensemble.RandomForestClassifier(random_state=42)

epochs = 10
score_dtc, score_rfc = [], []
for epoch in range(epochs):
    score_dtc.append(cross_val_score(dtc, wine_data.data, wine_data.target).mean())
    score_rfc.append(cross_val_score(rfc, wine_data.data, wine_data.target).mean())
    
plt.plot(score_dtc, label='decision tree classifier')
plt.plot(score_rfc, label='random forests classifier')
plt.show()

        可以看见,随机森林的效果还是明显的强。但是貌似在决策树效果很差的数据上,我们就不能继续使用随机森林了。这也很正常,毕竟决策树是随机森林的基础

Random Forests Regression代码实现

        这里我就简单的写一下模型实现的代码,效果对比和接口介绍我就不多说了,大家依然去看文档比较好,人家专门开发的写的比我好得多。

        当然 还有另一个原因,拟合问题效果确实一般,我运行了8s。。。而且效果也差,如果有机会,我绝对不会用这个。

house_data = datasets.fetch_california_housing()
train_X, test_X, train_Y, test_Y = train_test_split(house_data.data, house_data.target, test_size=0.33, random_state=42)

rfr = ensemble.RandomForestRegressor()
rfr = rfr.fit(train_X, train_Y)
score = rfr.score(test_X, test_Y)

print(score)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

香蕉也是布拉拉

随缘打赏不强求~ 谢谢大家

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值