使用 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组合多个步骤
各步骤会按照添加顺序执行。典型的生产配方应遵循以下顺序:
- 填补(先处理 NA)
- 创建特征(交互项、多项式)
- 虚拟变量编码(转换因子)
- 移除零方差变量
- 标准化(最后进行缩放)
顺序很重要——例如,在虚拟变量编码之前进行标准化会产生错误结果。
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 反馈 — 无需本地设置。
此课程中的所有课时
- 使用 recipes 进行特征工程
- 使用 parsnip 定义模型规格
- 工作流:组合配方与模型
- 使用 rsample 进行重抽样与交叉验证