0Pricing
R Academy · 课时

使用 recipes 进行特征工程

定义用于归一化、编码和插补的预处理步骤

使用 recipes 进行特征工程 是 CoddyKit 上的免费 R Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 R Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 R Academy 课程共包含 4 节课。

什么是配方?

在 tidymodels 中,配方是数据预处理的蓝图。它记录了将原始数据转换为可供模型使用的特征所需的步骤,但不会立即执行这些步骤。

关键函数是 recipe(outcome ~ ., data = train),它定义公式以及用于估计预处理所需统计量的参考数据集。

library(recipes)
library(tidymodels)

# Create a recipe using the training data
rec <- recipe(price ~ ., data = train_data)
print(rec)

step_normalize()

step_normalize(all_numeric_predictors()) 将每个数值预测变量的均值居中到 0,并将其缩放到标准差为 1。对于容易受特征尺度影响的算法(例如逻辑回归、SVM 或神经网络)来说,这一步非常重要。

均值和 SD 根据训练集计算,并通过 bake() 一致地应用到测试数据。

rec <- recipe(price ~ ., data = train_data) |>
  step_normalize(all_numeric_predictors())

# Check what steps are recorded
print(rec)

step_dummy()

step_dummy(all_nominal_predictors()) 将分类变量(因子或字符变量)转换为数值型虚拟变量(独热编码)列。默认情况下,具有 k 个水平的因子会生成 k-1 列,以避免完全多重共线性。

对于能从完整独热编码中受益的基于树的模型,请使用 one_hot = TRUE。

rec <- recipe(price ~ ., data = train_data) |>
  step_dummy(all_nominal_predictors())

# After prep and bake, factor columns become 0/1 numeric columns
prepped <- prep(rec)
baked <- bake(prepped, new_data = NULL)
names(baked)

step_impute_median()

缺失值会导致大多数模型引擎失败。step_impute_median(all_numeric_predictors()) 会用根据训练集计算出的中位数替换 NA 值。与使用均值进行填补相比,中位数受异常值的影响更小。

对于分类变量,请使用 step_impute_mode() 填充出现频率最高的值。

rec <- recipe(price ~ ., data = train_data) |>
  step_impute_median(all_numeric_predictors()) |>
  step_impute_mode(all_nominal_predictors())

print(rec)

step_zv() — 移除零方差变量

step_zv(all_predictors()) 会移除只有一个唯一值的预测变量(零方差)。这类列不包含任何信息,并可能导致某些模型引擎出现错误。

对于近零方差,请使用 step_nzv(all_predictors()),它还会移除某个值占绝大多数的列。

rec <- recipe(price ~ ., data = train_data) |>
  step_impute_median(all_numeric_predictors()) |>
  step_dummy(all_nominal_predictors()) |>
  step_zv(all_predictors()) |>
  step_normalize(all_numeric_predictors())

print(rec)

prep() — 训练配方

prep(recipe) 使用训练数据估计各步骤所需的所有参数,例如标准化所需的均值和 SD,以及填补所需的中位数。结果是一个经过准备的配方,其中包含所有转换参数。

请始终只使用训练数据执行准备,以避免测试集造成数据泄漏。

# Build the full recipe
rec <- recipe(price ~ ., data = train_data) |>
  step_impute_median(all_numeric_predictors()) |>
  step_dummy(all_nominal_predictors()) |>
  step_zv(all_predictors()) |>
  step_normalize(all_numeric_predictors())

# Estimate parameters from training data
prepped_rec <- prep(rec)
print(prepped_rec)

bake() — 应用到新数据

bake(prepped_recipe, new_data = test_data) 使用已经估计好的参数,将所有预处理步骤应用到任意数据集。这可以确保训练数据和测试数据之间的转换保持一致。

传入 new_data = NULL,可将这些步骤应用于执行 prep() 时所使用的训练数据。

# Apply recipe to test data
baked_test <- bake(prepped_rec, new_data = test_data)
head(baked_test)

# Apply to training data (same as juice())
baked_train <- bake(prepped_rec, new_data = NULL)
dim(baked_train)

juice() — 提取处理后的训练数据

juice(prepped_recipe) 是一个便利函数,等价于 bake(prepped_recipe, new_data = NULL)。它会返回执行 prep() 时所使用训练数据的预处理版本。

注意:juice() 已略微过时,推荐使用 bake(prep, new_data = NULL),但您仍会在较旧的 tidymodels 代码中看到它。

# juice() extracts the processed training data
train_processed <- juice(prepped_rec)
glimpse(train_processed)

# Equivalent modern approach
train_modern <- bake(prepped_rec, new_data = NULL)
identical(train_processed, train_modern)  # TRUE

组合多个步骤

各步骤会按照添加顺序执行。典型的生产配方应遵循以下顺序:

  1. 填补(先处理 NA)
  2. 创建特征(交互项、多项式)
  3. 虚拟变量编码(转换因子)
  4. 移除零方差变量
  5. 标准化(最后进行缩放)

顺序很重要——例如,在虚拟变量编码之前进行标准化会产生错误结果。

full_rec <- recipe(sale_price ~ ., data = housing_train) |>
  step_impute_median(all_numeric_predictors()) |>
  step_impute_mode(all_nominal_predictors()) |>
  step_log(sale_price, base = 10) |>
  step_other(all_nominal_predictors(), threshold = 0.05) |>
  step_dummy(all_nominal_predictors()) |>
  step_zv(all_predictors()) |>
  step_normalize(all_numeric_predictors())

print(full_rec)

检查准备结果

调用 prep() 后,您可以使用 tidy(prepped_rec) 检查每个步骤执行的操作。每个步骤都有一个数字编号,您可以使用 tidy(prepped_rec, number = 1) 进一步查看其估计参数。

prepped_rec <- prep(full_rec)

# View all steps and their status
tidy(prepped_rec)

# Inspect normalization parameters (mean, sd per column)
tidy(prepped_rec, number = 5)  # step_normalize is step 5

实际使用配方

配方与工作流结合使用时最能发挥作用。您无需手动调用 prep() 和 bake(),只需将配方添加到工作流中,tidymodels 就会在 fit() 和 predict() 期间自动处理准备和应用步骤。

这样可以避免一个常见错误来源:训练时和推断时采用了不同的预处理方式。

library(workflows)

# Recipe + model spec combined in a workflow
wf <- workflow() |>
  add_recipe(full_rec) |>
  add_model(linear_reg() |> set_engine('lm'))

# fit() internally calls prep() + bake() on training data
fitted_wf <- fit(wf, data = housing_train)

# predict() applies bake() to new data automatically
predictions <- predict(fitted_wf, new_data = housing_test)
head(predictions)

快速检查

在 tidymodels 配方框架中,调用 prep(recipe) 会执行什么操作?

配方回顾

使用配方进行特征工程的关键要点:

  • recipe(outcome ~ ., data = train) 定义预处理蓝图。
  • step_normalize()、step_dummy()、step_impute_median() 和 step_zv() 是最常用的步骤。
  • prep() 仅根据训练数据估计参数——绝不使用测试数据。
  • bake(prepped, new_data) 将训练好的配方应用到任意数据集。
  • 步骤顺序很重要:填补 → 创建 → 编码 → 移除 → 缩放。
  • 在生产环境中,将配方封装到 workflow() 中,以便在拟合和预测期间自动完成准备和应用。
# Full pipeline in 6 lines
rec <- recipe(target ~ ., data = train) |>
  step_impute_median(all_numeric_predictors()) |>
  step_dummy(all_nominal_predictors()) |>
  step_zv(all_predictors()) |>
  step_normalize(all_numeric_predictors())

prepped <- prep(rec)
train_baked <- bake(prepped, new_data = NULL)
test_baked  <- bake(prepped, new_data = test)

常见问题解答

「使用 recipes 进行特征工程」课时是免费的吗?

是的 — 「使用 recipes 进行特征工程」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 R Academy 课程的其余内容,请升级到 CoddyKit PRO。 R Academy 课程共包含 4 节课。

「使用 recipes 进行特征工程」这节课中我会学到什么?

定义用于归一化、编码和插补的预处理步骤 你通过在浏览器中直接运行的动手代码来练习 R Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 R Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 R Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「使用 recipes 进行特征工程」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 R Academy 课中编写并运行代码吗?

能。每节 R Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 使用 recipes 进行特征工程
  2. 使用 parsnip 定义模型规格
  3. 工作流:组合配方与模型
  4. 使用 rsample 进行重抽样与交叉验证
← 返回 R Academy