使用 Python 和 Scikit-Learn PlatoBlockchain 数据智能的随机森林算法权威指南。 垂直搜索。 人工智能。

使用 Python 和 Scikit-Learn 的随机森林算法权威指南

介绍

随机森林算法是最灵活、最强大和广泛使用的算法之一 分类和回归, 作为一个 决策树的集合.

如果您不熟悉这些 - 不用担心,我们将涵盖所有这些概念。

在这份深入的实践指南中,我们将构建一个 直觉 关于决策树的工作原理,集成如何增强单个分类器和回归器,什么是随机森林,并使用 Python 和 Scikit-Learn 通过端到端的小型项目构建随机森林分类器和回归器,并回答一个研究问题。

假设您目前是分析女性数据的研究小组的一员。 该小组收集了 100 条数据记录,并希望能够通过将女性分为几类来组织这些初始记录:怀孕或未怀孕,以及生活在农村或城市地区。 研究人员想了解每个类别中有多少女性。

有一种计算结构可以做到这一点,它是 结构体。 通过使用树结构,您将能够代表每个类别的不同部门。

决策树

你如何填充树的节点? 这是哪里 决策树 成为焦点。

首先,我们可以根据怀孕来划分记录,然后,我们可以根据居住在城市或农村地区来划分。 请注意,我们可以按不同的顺序执行此操作,首先按女性居住的区域划分,然后按怀孕状况划分。 由此,我们可以看出树具有固有的层次结构。 除了组织信息外,树还以分层方式组织信息——信息出现的顺序很重要,因此会导致不同的树。

下面是已描述的树的示例:

树形图中,有7个方格,最上面的那个方格一共100个女人,这个最上面的方格连着下面的两个方格,按照未怀孕的78人和怀孕的22人来划分,从前面的两个方块中有四个方块; 两个连接到上面的每个方格,根据她们的区域划分妇女,对于未怀孕的人,45 人住在城市地区,33 人住在农村地区,对于怀孕的人,14 人住在农村地区,8 人住在城市地区。 只需看一棵树,就很容易理解这些划分并了解每个“层”是如何从前面的层派生出来的,那些层就是树 各级,水平描述了 深度 树的:

使用 Python 和 Scikit-Learn PlatoBlockchain 数据智能的随机森林算法权威指南。 垂直搜索。 人工智能。

在上图中观察第一层树是 水平0 其中只有一个正方形,其次是 水平1 那里有两个正方形,并且 水平2 那里有四个正方形。 这是一个 深度2 树。

在第 0 层是起源树的正方形,第一个,称为 根节点, 这个根有两个 子节点 在第 1 级,即 父节点 到第 2 层中的四个节点。看到我们到目前为止一直提到的“正方形”实际上被称为 节点; 并且每个先前的节点都是以下节点的父节点,这些节点是其子节点。 具有相同父节点的每一层的子节点称为 兄弟姐妹,如下图所示:

使用 Python 和 Scikit-Learn PlatoBlockchain 数据智能的随机森林算法权威指南。 垂直搜索。 人工智能。

在上图中,我们还将级别 1 显示为 内部节点,一旦它们位于根节点和最后一个节点之间,它们就是 叶节点. 叶子节点是树的最后一部分,如果我们要说从最初的 100 名妇女中,有多少人怀孕并生活在农村地区,我们可以通过查看叶子来做到这一点。 所以叶子上的数字可以回答第一个研究问题。

如果有新的女性记录,以前用来对她们进行分类的树现在用来决定女性是否可以参与研究,它还会起作用吗? 这棵树将使用相同的标准,如果怀孕并居住在农村地区,女性将可以参与。

使用 Python 和 Scikit-Learn PlatoBlockchain 数据智能的随机森林算法权威指南。 垂直搜索。 人工智能。

通过查看上图,我们可以看到每个树节点的问题的答案——“她是参与者吗?”、“她怀孕了吗?”、“她住在农村吗?”——是的,是的,是的,所以这棵树似乎可以导致一个决定,在这种情况下,这个女人可以参与研究。

这是 本质 中的决策树,以手动方式完成。 使用机器学习,我们可以构建一个模型,自动为我们构建这棵树,从而最大限度地提高最终决策的准确性。

请注意: 计算机科学中有几种类型的树,如二叉树、一般树、AVL 树、splay 树、红黑树、b 树等。这里,我们重点介绍什么是决策树. 如果这取决于一个人的答案 or 没有 每个节点的问题,因此每个节点都有 最多两个孩子,当排序时“较小”的节点在左边,这将决策树分类为 二叉树.

在前面的示例中,观察树如何 分类 作为参与者或非参与者的新数据,或者问题也可以更改为——“有多少参与者?”、“有多少人怀孕了?”、“有多少人住在农村地区?”——引导我们找到 数量 住在农村地区的怀孕参与者。

当数据被分类时,这意味着树正在执行 分类 任务,当找到数据量时,树正在执行 回归 任务。 这意味着决策树可用于两种任务——分类和回归。

既然我们了解了决策树是什么、如何使用它以及用什么术语来描述它,我们就可以想知道它的局限性了。

了解随机森林

如果一些参与者生活在城乡之间,这个决定会发生什么变化? 这棵树会将此记录添加到农村还是城市? 似乎很难将这些数据放入我们目前拥有的结构中,因为它相当清晰。

另外,如果一个住在船上的女人参与研究,会被认为是农村还是城市? 与之前的案例一样,考虑到树中的可用选项,这是一个具有挑战性的数据点分类。

通过更多地考虑决策树示例,我们能够看到它可以正确地对新数据进行分类,因为它已经遵循树已有的模式——但是当存在与定义树的初始数据不同的记录时,树状结构过于死板,使得记录无法分类。

这意味着决策树的可能性可以是严格的和有限的。 理想的决策树将更加灵活,能够容纳更细微的看不见的数据。

解决方案: 正如“两双眼睛比一只眼睛看得更清楚”一样,两个模型通常比一个模型得出更准确的答案。 考虑到知识表示的多样性(编码在树结构中),多个相似树之间略有不同的结构的刚性不再是限制性的,因为一棵树的缺点可以由另一棵树“弥补”。 通过结合许多 一起,我们得到一个 森林.

关于最初问题的答案,我们已经知道它会被编码在树叶中——但是当我们有很多棵树而不是一棵树时会发生什么变化呢?

如果将树组合起来进行分类,则结果将由大多数答案定义,这称为 多数投票; 在回归的情况下,森林中每棵树给出的数字将是 平均.

集成学习和模型集成

这种方法被称为 合奏学习. 在应用集成学习时,您可以将任何算法混合在一起,只要您能确保输出可以被解析并与其他输出组合(手动或使用现有库)。 通常,您将多个相同类型的模型集成在一起,例如多个决策树,但您不仅限于加入相同模型类型的集成。

集成是一种切实可行的方法,可以更好地概括问题,并获得轻微的性能提升。 在某些情况下,集成模型会产生 显著 预测能力的增加,有时只是轻微的。 这取决于您正在训练和评估的数据集,以及模型本身。

将决策树连接在一起产生 显著 对单个树的性能提升。 这种方法在研究和应用机器学习社区中得到普及,并且非常普遍,以至于决策树的集合被通俗地命名为 森林,以及正在创建的常见类型的森林(随机特征子集上的决策树森林)推广了这个名称 随机森林.

考虑到广泛的使用,像 Scikit-Learn 这样的库已经实现了包装器 RandomForestRegressor并且 RandomForestClassifiers,建立在他们自己的决策树实现之上,以允许研究人员避免构建他们自己的集成。

让我们深入随机森林吧!

随机森林算法是如何工作的?

以下是执行随机森林算法时涉及的基本步骤:

  1. 从数据集(称为 N 记录)。 数量将取决于数据集的宽度,越宽,越大 N 可。 这是 随机 算法名称中的一部分从何而来!
  2. 基于这些构建决策树 N 随机记录;
  3. 根据为算法定义的树的数量,或者森林中的树的数量,重复步骤 1 和 2。这会从一组随机数据记录中生成更多的树;
  4. 在第 3 步之后,是最后一步,即预测结果:
    • 在分类的情况下:森林中的每棵树都会预测新记录所属的类别。 之后,新记录被分配到赢得多数票的类别。
    • 在回归的情况下:森林中的每棵树都为新记录预测一个值,最终的预测值将通过对森林中所有树预测的所有值取平均值来计算。

适合随机特征子集的每棵树都必然不知道其他一些特征,这是通过集成纠正的,同时保持较低的计算成本。

忠告:由于随机森林使用决策树作为基础,因此了解决策树的工作原理并单独进行一些练习以建立对其结构的直觉非常有帮助。 在组成随机森林时,您将设置树的最大深度、叶节点所需的最小样本数、确定内部分裂的下注标准等值,以帮助整体更好地适应数据集,并推广到新的点。 在实践中,您通常会使用随机森林、梯度提升或极端梯度提升或其他基于树的方法,因此很好地掌握单个决策树的超参数将有助于建立强大的调优直觉。

有了对树如何工作的直觉,以及对随机森林的理解——唯一剩下的就是练习构建、训练和调整它们的数据!

使用 Scikit-Learn 构建和训练随机森林模型

到目前为止使用的例子涉及怀孕、生活区和妇女是有原因的。

2020 年,来自孟加拉国的研究人员注意到孕妇的死亡率仍然很高,特别是生活在农村地区的孕妇。 因此,他们使用物联网监控系统来 分析孕产妇健康风险. 物联网系统从孟加拉国农村地区的不同医院、社区诊所和孕产妇保健中心收集数据。

然后将收集的数据组织成逗号分隔值 (csv) 文件并上传到 UCI 的机器学习库.

这是我们将用来练习和尝试了解孕妇是否患有 , 中等 or 死亡风险。

备注: 你可以下载数据集 此处.

使用随机森林进行分类

因为我们想知道女人是否有 , 中等 or 死亡风险,这意味着我们将进行三级分类。 当一个问题有两个以上的类别时,它被称为 多类 问题,而不是 二进制 问题(你在两个类之间进行选择,通常 01).

在第一个示例中,我们将使用随机森林分类器和 Python 的 Scikit-Learn 实现多类分类模型。

我们将按照通常的机器学习步骤来解决这个问题,即加载库、读取数据、查看汇总统计数据和创建数据可视化以更好地理解它。 然后,预处理和拆分数据,然后生成、训练和评估模型。

导入库

我们将使用 Pandas 来读取数据,使用 Seaborn 和 Matplotlib 来可视化它,并使用 NumPy 来提供强大的实用方法:

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
导入数据集

以下代码导入数据集并将其加载到 python 中 DataFrame:

dataset = pd.read_csv("../../datasets/random-forest/maternal_health_risk.csv")

要查看数据的前五行,我们执行 head() 命令:

dataset.head()

输出:

    Age SystolicBP  DiastolicBP BS      BodyTemp    HeartRate   RiskLevel
0   25  130         80          15.0    98.0        86          high risk
1   35  140         90          13.0    98.0        70          high risk
2   29  90          70          8.0     100.0       80          high risk
3   30  140         85          7.0     98.0        70          high risk
4   35  120         60          6.1     98.0        76          low risk

在这里我们可以看到研究过程中收集的所有属性。

  • 年龄:以年为单位的年龄。
  • 收缩压:以毫米汞柱为单位的血压上限值,是怀孕期间的一个重要属性。
  • DiastolicBP:以 mmHg 为单位的较低血压值,这是怀孕期间的另一个重要属性。
  • BS:以摩尔浓度表示的血糖水平,mmol/L。
  • HeartRate:静息心率,以每分钟心跳次数为单位。
  • RiskLevel:怀孕期间的风险等级。
  • BodyTemp:体温。

现在我们对正在测量的内容有了更多了解,我们可以查看数据类型 info():

dataset.info()

结果是:


RangeIndex: 1014 entries, 0 to 1013
Data columns (total 7 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   Age          1014 non-null   int64  
 1   SystolicBP   1014 non-null   int64  
 2   DiastolicBP  1014 non-null   int64  
 3   BS           1014 non-null   float64
 4   BodyTemp     1014 non-null   float64
 5   HeartRate    1014 non-null   int64  
 6   RiskLevel    1014 non-null   object 
dtypes: float64(2), int64(4), object(1)
memory usage: 55.6+ KB

从看 RangeIndex 行,我们可以看到有 1014 条记录,而列 Non-Null Count 通知数据没有任何缺失值。 这意味着,我们不需要对缺失数据做任何处理!

Dtype 列,我们可以看到每个变量的类型。 目前, float64 列这样的 BSBodyTemp 具有可能在任何范围内变化的数值,例如 15.0、15.51、15.76、17.28,使它们 数值连续 (您始终可以将 0 添加到浮点数,无限)。 另一方面,变量如 Age, SystolicBP, DiastolicBPHeartRate 是类型 int64,这意味着数字仅按单位变化,例如 11、12、13、14 – 我们不会得到 77.78 的心率,它是 77 或 78 – 这些是 数值离散 值。 而我们也有 RiskLevelobject 类型,这通常表示变量是文本,我们可能需要将其转换为数字。 由于风险级别从低到高,类别之间存在隐含的顺序,这表明它是一个 绝对序数 变量。

备注:重要的是要查看每个数据的类型,并根据其上下文查看它是否有意义。 例如,有一半的心率单位没有意义,因此这意味着整数类型足以用于离散值。 如果没有发生,您可以使用 Pandas 更改数据类型 astype() 财产—— df['column_name'].astype('type').

查看数据类型后,我们可以使用 describe() 在一些描述性统计数据处取一个峰值,例如每列的平均值、标准偏差、分位数、最小和最大数据值:

dataset.describe().T 

上面的代码显示:

            count   mean        std         min     25%     50%     75%     max
Age         1014.0  29.871795   13.474386   10.0    19.0    26.0    39.0    70.0
SystolicBP  1014.0  113.198225  18.403913   70.0    100.0   120.0   120.0   160.0
DiastolicBP 1014.0  76.460552   13.885796   49.0    65.0    80.0    90.0    100.0
BS          1014.0  8.725986    3.293532    6.0     6.9     7.5     8.0     19.0
BodyTemp    1014.0  98.665089   1.371384    98.0    98.0    98.0    98.0    103.0
HeartRate   1014.0  74.301775   8.088702    7.0     70.0    76.0    80.0    90.0
RiskLevel   1014.0  0.867850    0.807353    0.0     0.0     1.0     2.0     2.0

请注意,对于大多数列, 意味着 价值观远非 标准偏差 (std) – 这表明数据不一定遵循良好的统计分布。 如果是这样,它将在预测风险时帮助模型。 这里可以做的是对数据进行预处理,使其更具代表性,就好像它是来自全世界人口的数据,或者更多 标准化. 但是,将随机森林模型用于 分类, 是固有的树结构可以很好地处理尚未归一化的数据,一旦将其除以每个变量在每个树级别中的值。

此外,因为我们使用的是树,并且结果类将通过投票获得,我们本质上不是在不同的值之间进行比较,而是在相同类型的值之间进行比较,因此在这种情况下不需要将特征调整到相同的比例. 这意味着随机森林分类模型是 尺度不变,并且您不需要执行特征缩放。

在这种情况下,我们可以采取的数据预处理步骤是将分类 RiskLevel 列变成一个数字。

可视化数据

改造前 RiskLevel,让我们还通过散点图查看每对特征的点组合以及通过直方图曲线可视化点的分布情况来快速可视化数据。 为此,我们将使用 Seaborn 的 pairplot() 它结合了两个图。 它为每个特征组合生成两个图,并显示根据风险级别用颜色编码的点 hue 属性:

g = sns.pairplot(dataset, hue='RiskLevel')
g.fig.suptitle("Scatterplot and histogram of pairs of variables color coded by risk level", 
               fontsize = 14, 
               y=1.05); 

上面的代码生成:

使用 Python 和 Scikit-Learn PlatoBlockchain 数据智能的随机森林算法权威指南。 垂直搜索。 人工智能。

看图时,理想的情况是曲线和点之间有明显的分离。 正如我们所看到的,这三种类型的风险类别大多是混合的,因为树木在划分点之间的空间时会在内部画线,我们可以假设森林中更多的树木可能能够限制更多的空间并更好地对点进行分类。

完成基本的探索性数据分析后,我们可以预处理 RiskLevel 列。

分类数据预处理

可以肯定只有三类 RiskLevel 在我们的数据中,并且没有错误地添加其他值,我们可以使用 unique() 显示列的唯一值:

dataset['RiskLevel'].unique()

输出:

array(['high risk', 'low risk', 'mid risk'], dtype=object)

检查类,下一步是将每个值转换为数字。 由于分类之间存在顺序,我们可以使用值 0、1 和 2 来表示 , 中等 风险。 有很多方法可以更改列值,遵循 Python 的 简单胜于复杂 座右铭,我们将使用 .replace() 方法,并简单地用它们的整数表示替换它们:

dataset['RiskLevel'] = dataset['RiskLevel'].replace('low risk', 0).replace('mid risk', 1).replace('high risk', 2)

替换值后,我们可以将数据划分为将用于训练模型的数据, 功能 or X,以及我们想要预测的, 标签 or y:

y = dataset['RiskLevel']
X = dataset.drop(['RiskLevel'], axis=1)

一旦 Xy 集合准备好了,我们可以使用 Scikit-Learn 的 train_test_split() 将它们进一步划分为训练集和测试集的方法:

from sklearn.model_selection import train_test_split

SEED = 42
X_train, X_test, y_train, y_test = train_test_split(X, y, 
                                                    test_size=0.2, 
                                                    random_state=SEED)

建议: 如果要使结果可重现,请记住使用随机状态种子。 我们使用了随机状态种子,因此您可以重现与指南中相同的结果。

在这里,我们使用 20% 的数据进行测试,80% 的数据用于训练。

训练 RandomForestClassifier

查看我们的 Git 学习实践指南,其中包含最佳实践、行业认可的标准以及随附的备忘单。 停止谷歌搜索 Git 命令,实际上 学习 它!

Scikit-Learn 在 sklearn.ensemble 模块。 用于分类的决策树集合,其中多数表决被实现为 RandomForestClassifier.

有了训练集和测试集,我们可以导入 RandomForestClassifier 类并创建模型。 首先,让我们通过设置创建一个包含三棵树的森林 n_estimators 参数为 3,并且每棵树具有三个级别,通过设置 max_depth到2:

from sklearn.ensemble import RandomForestClassifier

rfc = RandomForestClassifier(n_estimators=3, 
                             max_depth=2,
                             random_state=SEED)

请注意: 的默认值 n_estimators is 100. 这提高了整体的预测能力和泛化能力,但我们正在创建一个更小的整体,以便更容易地对其进行可视化和检查。 只有 3 棵树——我们可以可视化和检查它们 手动 进一步建立我们对个体树及其相互依赖性的直觉。 同样适用于 max_depth,这是 None,这意味着树可以越来越深以根据需要适应数据。

为了围绕数据拟合模型——我们称 fit() 方法,传入训练特征和标签:


rfc.fit(X_train, y_train)

y_pred = rfc.predict(X_test)

我们现在可以将预测标签与真实标签进行比较,以评估模型的表现! 在评估模型之前,让我们看一下集成。

为了更深入地了解模型,我们可以可视化每棵树以及它们如何划分数据。 这可以通过使用 tree 内置于 Scikit-Learn 中的模块,然后遍历集成中的每个估计器:


from sklearn import tree

features = X.columns.values 
classes = ['0', '1', '2'] 



for estimator in rfc.estimators_:
    print(estimator)
    plt.figure(figsize=(12,6))
    tree.plot_tree(estimator,
                   feature_names=features,
                   class_names=classes,
                   fontsize=8, 
                   filled=True, 
                   rounded=True)
    plt.show()

上面的代码显示了树状图:

使用 Python 和 Scikit-Learn PlatoBlockchain 数据智能的随机森林算法权威指南。 垂直搜索。 人工智能。
使用 Python 和 Scikit-Learn PlatoBlockchain 数据智能的随机森林算法权威指南。 垂直搜索。 人工智能。
使用 Python 和 Scikit-Learn PlatoBlockchain 数据智能的随机森林算法权威指南。 垂直搜索。 人工智能。

请注意这三棵树的不同之处。 第一个开始于 BS 功能,第二个 DiastolicBP,第三个与 BS 再次。 尽管第三个着眼于不同数量的样本。 在右分支上,前两棵树也决定使用 Age 在叶子级别,而第三棵树以 BS 特征。 仅需三个估算器,就可以清楚地了解按比例放大如何提供丰富多样的知识表示,这些知识可以成功地集成到高精度模型中。

森林中的树木越多,模型就越多样化。 但是,有一个收益递减点,因为许多树适合随机的特征子集,所以会有相当多的相似树在整体中没有提供太多多样性,并且将开始具有 太多的投票权 并使整体在训练数据集上过度拟合,从而损害对验证集的泛化。

早些时候有一个关于拥有更多树木以及它如何改善模型结果的假设。 让我们看看结果,生成一个新模型,看看假设是否成立!

评估 RandomForestClassifier

Scikit-Learn 通过提供 DummyClassifier, 输出预测 不使用输入功能 (完全随机输出)。 如果你的模型比 DummyClassifier, 一些 学习正在发生! 为了最大化学习——你可以使用一个自动测试各种超参数 RandomizedSearchCV or GridSearchCV. 除了拥有基线外,您还可以从多个指标的角度评估模型的性能。

一些可用于评估算法的传统分类指标是精度、召回率、f1-score、准确性和混淆矩阵。 以下是对它们每个的简要说明:

  1. 平台精度:当我们的目标是了解我们的分类器认为哪些正确的预测值是正确的。 Precision 会将那些真阳性值除以预测为阳性的样本;

$$
精度 = frac{文本{真阳性}}{文本{真阳性} + 文本{假阳性}}
$$

  1. 记得:通常与精度一起计算,以了解我们的分类器识别了多少真阳性。 召回率是通过将真阳性除以任何应该被预测为阳性的值来计算的。

$$
召回率 = frac{文本{真阳性}}{文本{真阳性} + 文本{假阴性}}
$$

  1. F1分数: 是平衡的还是 谐波均值 精度和召回率。 最小值为 0,最大值为 1。当 f1-score 等于 1,这意味着所有类都被正确预测了——这是一个很难用真实数据获得的分数(几乎总是存在例外)。

$$
文本{f1-分数} = 2* 压裂{文本{精度} * 文本{召回}}{文本{精度} + 文本{召回}}
$$

  1. 混淆矩阵:当我们需要知道我们正确或错误的样本数量时 每堂课. 正确且正确预测的值称为 真正的积极,那些被预测为阳性但不是阳性的被称为 误报. 相同的命名法 真正的负面假阴性 用于负值;

  2. 准确性:描述了我们的分类器有多少预测是正确的。 最低准确度值为 0,最高准确度值为 1。该值通常乘以 100 以获得百分比:

$$
准确度 = frac{text{正确预测数}}{text{预测总数}}
$$

请注意: 要将机器学习应用于任何真实数据,几乎不可能获得 100% 的准确度。 如果您看到 100% 准确度的分类器,甚至是接近 100% 的结果,请保持怀疑并进行评估。 这些问题的一个常见原因是数据泄漏(将部分训练测试直接或间接地泄漏到测试集中)。 对于什么是“良好的准确性”并没有达成共识,主要是因为它取决于您的数据——有时,70% 的准确性会很高! 有时,这将是一个非常低的准确性。 一般来说, 超过 70% 对于许多模型来说已经足够了,但这要由领域研究人员来确定。

您可以执行以下脚本导入必要的库并查看结果:

from sklearn.metrics import classification_report, confusion_matrix

cm = confusion_matrix(y_test, y_pred)
sns.heatmap(cm, annot=True, fmt='d').set_title('Maternal risks confusion matrix (0 = low risk, 1 = medium risk, 2 = high risk)')

print(classification_report(y_test,y_pred))

输出将如下所示:

                precision    recall  f1-score   support

           0       0.53      0.89      0.66        80
           1       0.57      0.17      0.26        76
           2       0.74      0.72      0.73        47

    accuracy                           0.58       203
   macro avg       0.61      0.59      0.55       203
weighted avg       0.59      0.58      0.53       203

使用 Python 和 Scikit-Learn PlatoBlockchain 数据智能的随机森林算法权威指南。 垂直搜索。 人工智能。

在分类报告中,观察到召回率很高,0.89 类为 0,2 类的精度和召回率都很高,0.74、0.72 – 而对于 1 类,它们都很低,特别是召回率 0.17 和精度 0.57 . 所有三个类别的召回率和精确率之间的关系分别在 F1 得分,这是召回率和精确率之间的调和平均值——模型正在做 还好啦 对于 0 级,对于 1 级来说相当糟糕,对于 2 级来说还不错。

该模型在识别 中等风险个案.

我们的随机森林分类器只有 3 棵树的准确度是 0.58 (58%)——这意味着它得到了超过一半的结果。 这是一个低准确度,也许可以通过添加更多树来提高。

通过查看混淆矩阵,我们可以看到大多数错误是在将 52 条中等风险的记录分类为低风险时,这进一步说明了 1 类的低召回率。它偏向于将中等风险患者分类为低风险风险患者。

可以检查以产生更多洞察力的另一件事是分类器在预测时最考虑哪些特征。 这是一个重要的步骤 可解释的机器学习系统,并有助于识别和减轻模型中的偏差。

要看到这一点,我们可以访问 feature_importances_ 分类器的属性。 这将为我们提供百分比列表,因此我们还可以访问 feature_names_in_ 属性以获取每个特征的名称,将它们组织在一个数据框中,将它们从最高到最低排序,并绘制结果:


features_df = pd.DataFrame({'features': rfc.feature_names_in_, 'importances': rfc.feature_importances_ })


features_df_sorted = features_df.sort_values(by='importances', ascending=False)


g = sns.barplot(data=features_df_sorted, x='importances', y ='features', palette="rocket")
sns.despine(bottom = True, left = True)
g.set_title('Feature importances')
g.set(xlabel=None)
g.set(ylabel=None)
g.set(xticks=[])
for value in g.containers:
    g.bar_label(value, padding=2)

使用 Python 和 Scikit-Learn PlatoBlockchain 数据智能的随机森林算法权威指南。 垂直搜索。 人工智能。

注意分类器主要是如何考虑 血糖,然后是一些舒张压、体温和一点年龄来做出决定,这也可能与 1 类的低召回率有关,也许中等风险数据与未被识别的特征有关模型考虑了很多。 您可以尝试更多地使用特征重要性来调查这一点,看看模型的变化是否影响正在使用的特征,以及某些特征与预测类别之间是否存在显着关系。

终于到了生成一个包含更多树的新模型以查看它如何影响结果的时候了。 让我们创造 rfc_ 有 900 棵树、8 个级别和相同种子的森林。 结果会改善吗?

rfc_ = RandomForestClassifier(n_estimators=900, 
                             max_depth=7,
                             random_state=SEED)
rfc_.fit(X_train, y_train)
y_pred = rfc_.predict(X_test)

计算和显示指标:

cm_ = confusion_matrix(y_test, y_pred)
sns.heatmap(cm_, annot=True, fmt='d').set_title('Maternal risks confusion matrix (0 = low risk, 1 = medium risk, 2 = high risk) for 900 trees with 8 levels')

print(classification_report(y_test,y_pred))

输出:

                precision    recall  f1-score   support

           0       0.68      0.86      0.76        80
           1       0.75      0.58      0.65        76
           2       0.90      0.81      0.85        47

    accuracy                           0.74       203
   macro avg       0.78      0.75      0.75       203
weighted avg       0.76      0.74      0.74       203

使用 Python 和 Scikit-Learn PlatoBlockchain 数据智能的随机森林算法权威指南。 垂直搜索。 人工智能。

这显示了添加更多树和更专业的树(更高级别)如何改进我们的指标。 我们对第 1 类的召回率仍然很低,但现在准确率为 74%。 对高风险案例进行分类时的 F1 分数为 0.85,这意味着与之前模型中的 0.73 相比,现在更容易识别高风险案例!

在日常项目中,识别高风险案例可能更为重要,例如使用类似于精度的指标,也称为 灵敏度 在统计中。 尝试调整一些模型参数并观察结果。

到目前为止,我们已经对如何使用随机森林对数据进行分类有了一个全面的了解——在下一节中,我们可以以不同的方式使用相同的数据集,看看相同的模型如何通过回归来预测值。

使用随机森林进行回归

在本节中,我们将研究如何使用 Scikit-Learn 使用随机森林算法来解决回归问题。 实现该算法所遵循的步骤与分类所执行的步骤几乎相同,除了模型类型和预测数据类型(现在将是连续值)之外,在数据准备方面只有一处不同。

由于回归是为 数值 – 让我们从数据集中选择一个数值。 我们已经看到血糖在分类中很重要,因此它应该可以根据其他特征进行预测(因为如果它与某些特征相关,那么该特征也与它相关)。

按照我们为分类所做的工作,让我们首先导入库和相同的数据集。 如果您已经为分类模型完成了此操作,则可以跳过此部分并直接转到为训练准备数据。

导入库和数据
import pandas as pd
import numpy as np
import maplotlib.pyplot as plt
import seaborn as sns

dataset = pd.read_csv("../../datasets/random-forest/maternal_health_risk.csv")
回归数据预处理

这是一项回归任务,因此我们可以预测数据集的数字列之一,而不是预测类别。 在这个例子中, BS 列将被预测。 这意味着 y 数据将包含 血糖数据X 数据将包含除血糖以外的所有特征。 分离后 Xy 数据,我们可以拆分训练集和测试集:

from sklearn.model_selection import train_test_split

SEED = 42

y = dataset['BS']
X = dataset.drop(['BS'], axis=1) 

X_train, X_test, y_train, y_test = train_test_split(X, y, 
                                                    test_size=0.2, 
                                                    random_state=SEED)
训练 RandomForestRegressor

现在我们已经扩展了我们的数据集,是时候训练我们的算法来解决这个回归问题了,稍微改变一下——我们将在森林中创建一个包含 20 棵树的模型,每棵树有 4 个级别。 为此,您可以执行以下代码:

from sklearn.ensemble import RandomForestRegressor

rfr = RandomForestRegressor(n_estimators=20, 
                            max_depth=3, 
                            random_state=SEED)

rfr.fit(X_train, y_train)
y_pred = rfr.predict(X_test)

您可以找到所有参数的详细信息 RandomForestRegressor 在官方文档中.

由于绘制和查看 20 棵树需要一些时间和精力,我们可以只绘制第一棵树,看看它与分类树有何不同:

from sklearn import tree

features = X.columns

first_tree = rfr.estimators_[0]

plt.figure(figsize=(15,6))
tree.plot_tree(first_tree,
               feature_names=features,
               fontsize=8, 
               filled=True, 
               rounded=True);

使用 Python 和 Scikit-Learn PlatoBlockchain 数据智能的随机森林算法权威指南。 垂直搜索。 人工智能。

请注意,回归树已经为落在每个节点上的数据分配了一个值。 这些是组合 20 棵树时将取平均值的值。 按照我们对分类所做的工作,您还可以绘制特征重要性,以查看回归模型在计算值时更多地考虑了哪些变量。

是时候进入解决机器学习问题的最后一步,评估算法的性能了!

评估 RandomForestRegressor

对于回归问题,用于评估算法的指标是平均绝对误差 (MAE)、均方误差 (MSE) 和均方根误差 (RMSE)。

  1. 平均绝对误差(MAE):当我们从实际值中减去预测值,得到误差,将这些误差的绝对值相加并得到它们的平均值。 该指标给出了模型每个预测的总体误差概念,越小(接近 0)越好。

$$
mae = (frac{1}{n})sum_{i=1}^{n}left | 实际 - 预测正确 |
$$

请注意: 您可能还会遇到 yŷ 等式中的符号。 这 y 指的是实际值和 ŷ 到预测值。

  1. 均方误差 (MSE):它类似于 MAE 指标,但它对误差的绝对值求平方。 此外,与 MAE 一样,越小或越接近 0 越好。 MSE 值被平方以使得大的误差更大。 需要密切注意的一件事是,由于其值的大小以及它们不在同一数据规模这一事实,它通常是一个很难解释的指标。

$$
mse = sum_{i=1}^{D}(实际 - 预测)^2
$$

  1. 均方根误差 (RMSE):试图通过获取其最终值的平方根来解决 MSE 引起的解释问题,以便将其缩放回相同的数据单位。 当我们需要显示或显示带有错误的数据的实际值时,它更容易解释并且很好。 它显示了数据可能变化的程度,因此,如果我们的 RMSE 为 4.35,我们的模型可能会出错,因为它在实际值上增加了 4.35,或者需要 4.35 才能得到实际值。 越接近 0 越好。

$$
rmse = sqrt{ sum_{i=1}^{D}(实际 - 预测)^2}
$$

我们可以使用这三个指标中的任何一个 比较 模型(如果我们需要选择一个)。 我们还可以将相同的回归模型与不同的参数值或不同的数据进行比较,然后考虑评估指标。 这被称为 超参数调整 – 调整影响学习算法的超参数并观察结果。

在模型之间进行选择时,误差最小的模型通常表现更好。 在监控模型时,如果指标变差,那么模型的先前版本会更好,或者数据中存在一些重大变化,导致模型的性能比它的性能更差。

您可以通过以下代码找到这些值:

from sklearn.metrics import mean_absolute_error, mean_squared_error

print('Mean Absolute Error:', mean_absolute_error(y_test, y_pred))
print('Mean Squared Error:', mean_squared_error(y_test, y_pred))
print('Root Mean Squared Error:', np.sqrt(mean_squared_error(y_test, y_pred)))

输出应该是:

Mean Absolute Error: 1.127893702896059
Mean Squared Error: 3.0802988503933326
Root Mean Squared Error: 1.755078018320933

对于 20 棵树,均方根误差为 1.75,这很低,但即便如此——通过增加树的数量并试验其他参数,这个误差可能会变得更小。

使用随机森林的优势

与任何算法一样,使用它既有优点也有缺点。 在接下来的两节中,我们将了解使用随机森林进行分类和回归的优缺点。

  1. 随机森林算法没有偏差,因为有多棵树,每棵树都在随机数据子集上训练。 基本上,随机森林算法依赖于“人群”的力量; 因此降低了算法的整体偏差程度。
  2. 这个算法非常稳定。 即使在数据集中引入了新的数据点,整体算法也不会受到太大影响,因为新数据可能会影响一棵树,但它很难影响所有树。
  3. 当您同时具有分类特征和数字特征时,随机森林算法效果很好。
  4. 当数据有缺失值或未缩放时,随机森林算法也能很好地工作。

使用随机森林的缺点

  1. 随机森林的主要缺点在于其复杂性。 由于在训练大型集成时将大量决策树连接在一起,因此它们需要更多的计算资源。 虽然 - 使用现代硬件,即使训练大型随机森林也不会花费很多时间。

更进一步——手持式端到端项目

你好奇的天性让你想走得更远? 我们建议查看我们的 指导项目: “动手房价预测 - Python 中的机器学习”.

使用 Python 和 Scikit-Learn PlatoBlockchain 数据智能的随机森林算法权威指南。 垂直搜索。 人工智能。

在这个指导项目中,您将学习如何构建强大的传统机器学习模型以及深度学习模型,利用集成学习和训练元学习器从一组 Scikit-Learn 和 Keras 模型中预测房价。

使用基于 Tensorflow 构建的深度学习 API Keras,我们将试验架构,构建堆叠模型的集合并训练 元学习者 神经网络(一级模型)来计算房子的价格。

深度学习是惊人的——但在使用它之前,建议也尝试使用更简单的技术来解决问题,例如 浅层学习 算法。 我们的基准性能将基于 随机森林回归 算法。 此外——我们将探索通过 Scikit-Learn 通过以下技术创建模型集合 装袋表决.

这是一个端到端的项目,和所有机器学习项目一样,我们将从—— 探索性数据分析,其次是 数据预处理 最后 浅层建筑深度学习模型 以适应我们之前探索和清理过的数据。

时间戳记:

更多来自 堆栈滥用