Skip to content

R - 随机森林

R - 使用 tidymodels 实现现代随机森林

Section titled “R - 使用 tidymodels 实现现代随机森林”

随机森林 (Random Forest) 是一种强大的机器学习算法,它构建了大量决策树并聚合它们的预测。它是一种集成学习方法,通常提供高准确率、对过拟合的鲁棒性以及特征重要性的估计。

虽然 randomForest 包仍然可用,但 R 中现代且推荐的建模方法是 tidymodels 框架。tidymodels 为整个建模过程提供了一个一致、整洁和全面的生态系统,从数据拆分到模型评估无所不包。

我们的流程将遵循以下关键步骤:

  1. 设置 (Setup):安装并加载必要的软件包。
  2. 数据拆分 (Data Splitting):将数据拆分为训练集和测试集,以便进行鲁棒的评估。
  3. 模型规范 (Model Specification):定义随机森林模型及其引擎(执行计算的底层包)。
  4. 工作流 (Workflow):将模型规范打包到一个工作流对象中。
  5. 训练 (Training):使用训练数据拟合工作流。
  6. 评估 (Evaluation):在测试集上进行预测,并使用准确率和混淆矩阵等指标评估性能。
  7. 特征重要性 (Feature Importance):确定哪些预测变量对模型的决策最重要。

首先,安装 tidymodels 元软件包和 party(用于数据集)。我们还将使用 ranger 作为模型引擎,因为它通常比旧的 randomForest 包更快,并使用 vip 用于绘制变量重要性。

# 在您的控制台中运行这些行一次即可安装软件包
# install.packages("tidymodels")
# install.packages("party") # 用于 readingSkills 数据集
# install.packages("ranger") # 一个快速的随机森林实现
# install.packages("vip") # 用于变量重要性图
library(tidymodels)
library(party)
library(dplyr) # 用于数据操作

我们将使用 readingSkills 数据集,其中包含个人阅读分数的信息。我们的目标是根据一个人的年龄、鞋码和分数来预测他是否是 nativeSpeaker(母语者)。关键的第一步是拆分数据,以防止过拟合并获得模型在新数据上性能的无偏估计。

# 加载数据
data("readingSkills")
# 概览数据结构
glimpse(readingSkills)
# 设置种子,以确保随机拆分的可复现性
set.seed(123)
# 创建数据拆分对象(例如,80% 用于训练,20% 用于测试)
rs_split <- initial_split(readingSkills, prop = 0.80, strata = nativeSpeaker)
# 创建训练和测试数据框
rs_train <- training(rs_split)
rs_test <- testing(rs_split)

接下来,我们定义模型。我们指定要将随机森林 (rand_forest) 用于分类任务,并设置 ranger 作为引擎。然后,我们将此打包到 workflow 中以便于管理。

# 指定用于分类的随机森林模型
# 我们设置 importance = "impurity" 以便稍后能够访问它
rf_spec <- rand_forest(trees = 1000) %>%
set_engine("ranger", importance = "impurity") %>%
set_mode("classification")
# 创建工作流
rf_workflow <- workflow() %>%
add_model(rf_spec) %>%
add_formula(nativeSpeaker ~ .)
print(rf_workflow)

现在我们可以使用训练数据来训练(拟合)我们的工作流了。

# 在训练数据上训练工作流
rf_fit <- fit(rf_workflow, data = rs_train)
print(rf_fit)

我们的模型表现如何?我们使用测试集(模型从未见过的数据)来找出答案。我们将生成一个混淆矩阵并计算准确率。

# 在测试集上进行预测,并与真实值结合
predictions <- predict(rf_fit, rs_test) %>%
bind_cols(rs_test)
# 计算总体准确率
accuracy(predictions, truth = nativeSpeaker, estimate = .pred_class)
# 生成混淆矩阵
conf_mat(predictions, truth = nativeSpeaker, estimate = .pred_class)

这会产生以下结果(您的确切数字可能略有不同):

# A tibble: 1 × 3
.metric .estimator .estimate
<chr> <chr> <dbl>
1 accuracy binary 0.975
Truth
Prediction no yes
no 19 0
yes 1 20

结论:我们的模型在测试集上达到了 97.5% 的准确率。混淆矩阵显示它只犯了一个错误,将一个“yes”错误地分类为“no”。这是一个非常好的结果。

最后,让我们看看模型认为哪些变量最有用。我们将使用 vip 包进行清晰的可视化。

# 从工作流中提取已拟合的模型对象
final_model <- extract_fit_engine(rf_fit)
# 创建并打印变量重要性图
importance_plot <- vip(final_model)
print(importance_plot)

该图将显示 score 是迄今为止最重要的预测变量,其次是 shoeSize 和 age。这为我们提供了关于驱动预测因素的可操作性洞察。