缘由

艺多不压身

碎碎念

我们继续飞行在云层和雾气之间,飞行在一个无光无影的空洞世界中。 ——《风沙星辰》

Ref

7 A Model Workflow | Tidy Modeling with R

解读

本文用 Ames 房价数据集 演示一个最基础的线性回归工作流,并展示如何批量比较多个公式。

1️ 数据准备

我们先加载必要的包,并划分训练集与测试集。

library(tidymodels)
library(modeldata)
tidymodels_prefer()
 
# 数据集
data(ames)
ames <- mutate(ames, Sale_Price = log10(Sale_Price))
 
# 划分训练集/测试集
set.seed(502)
ames_split <- initial_split(ames, prop = 0.80, strata = Sale_Price)
ames_train <- training(ames_split)
ames_test  <- testing(ames_split)

2️ parsnip 的最简用法

tidymodels 的核心建模语法来自 parsnip。只需三步:

  1. 定义模型
  2. 指定引擎
  3. 使用 fit() 拟合
# 仅使用 parsnip
lm_model <- linear_reg() %>%
  set_engine("lm")
 
lm_fit2 <- fit(lm_model, Sale_Price ~ Longitude + Latitude, data = ames_train)

特点:语法简洁,但只能快速拟合,缺少统一的“项目管理”机制。


3️workflow 的引入

workflow 把 公式 + 模型 封装在一起,方便扩展。

# 使用 workflow()
lm_wflow <- workflow() %>%
  add_model(lm_model) %>%
  add_formula(Sale_Price ~ Longitude + Latitude)
 
lm_fit <- fit(lm_wflow, ames_train)
 
predict(lm_fit, ames_test %>% head(3))

还可以用 update_formula() 更新公式:

lm_fit %>% update_formula(Sale_Price ~ Longitude)

4️ add_formula vs add_variables

workflow 提供两种不同的接口:

用公式

lm_wflow <- workflow() %>% 
  add_model(lm_model) %>% 
  add_formula(Sale_Price ~ Longitude + Latitude)

用变量

lm_wflow <- lm_wflow %>%
  remove_formula() %>%
  add_variables(outcome = Sale_Price, predictors = c(Longitude, Latitude))
 
fit(lm_wflow, ames_train)
  • add_formula():写法接近 lm(),简单直观。
  • add_variables():更适合配合 recipes 做特征工程。

5️ 批量比较:workflowsets

如果想对比多个特征组合,可以用 workflowsets:

library(workflowsets)
 
# 定义不同的公式
location <- list(
  longitude    = Sale_Price ~ Longitude,
  latitude     = Sale_Price ~ Latitude,
  coords       = Sale_Price ~ Longitude + Latitude,
  neighborhood = Sale_Price ~ Neighborhood
)
 
# 生成 workflow set
location_models <- workflow_set(
  preproc = location,
  models  = list(lm = lm_model)
)
 
# 批量拟合
location_models <- location_models %>%
  mutate(fit = map(info, ~ fit(.x$workflow[[1]], ames_train)))
 
location_models$fit[[1]]

6️ 使用特殊公式:多水平模型

有些模型支持更复杂的公式,比如随机截距和斜率。
lme4::lmer() 常见写法:

library(nlme)
library(lme4)
 
lmer(distance ~ Sex + (age | Subject), data = Orthodont)

在 tidymodels 中,需要借助 multilevelmod:

library(multilevelmod)
 
multilevel_spec <- linear_reg() %>% set_engine("lmer")
 
multilevel_workflow <- workflow() %>%
  add_variables(outcome = distance, predictors = c(Sex, age, Subject)) %>%
  add_model(multilevel_spec,
            formula = distance ~ Sex + (age | Subject))

说明:

  • 这里的 formula 会直接传递给 lmer 引擎。
  • 普通 lm 模型不支持这种 (age | Subject) 写法。

7️ 模型评估:训练集 vs 测试集

在 tidymodels 中:

  • fit() 默认只在训练集拟合。
  • last_fit() 会自动在训练集拟合,并在测试集上评估。
final_lm_res <- last_fit(lm_wflow, ames_split)

查看结果

  • 评估指标(测试集表现)
collect_metrics(final_lm_res)
  • 预测结果(测试集对比)
collect_predictions(final_lm_res) %>% slice(1:5)
  • 提取训练好的 workflow
fitted_lm_wflow <- extract_workflow(final_lm_res)
tidy(fitted_lm_wflow)