在阅读这篇文章前,我强烈建议你先读一下tidymodels入门篇:tidymodels用于机器学习的细节,首先对tidymodels
有一个整体的认知。
今天主要介绍workflow
的用法。
workflow
可以把你的数据预处理步骤和模型连接起来,形成一个整体,而不是完全分割开来的,在tidymodels
中主要作用是连接parsnip
和recipes
产生的对象。
一个完整的workflow如下图所示:
数据预处理和模型选择是一个整体,workflow
就是用来做这个工作。目前tidymodels
强推workflow
,建议以后大家使用的时候不管有没有预处理步骤,都使用workflow
,因为统一的语法更好理解也好记忆。
使用workflow
一个显而易见的优点是:不用事先对数据进行预处理,然后再建立模型,使用了workflow
之后,它会自动帮你进行这一步,不需要先把数据预处理再建模!
以下是一个例子。
workflow的好处
首先是不使用workflow的正常步骤。
代码语言:javascript复制# 加载R包和数据
library(recipes)
## Loading required package: dplyr
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
##
## Attaching package: 'recipes'
## The following object is masked from 'package:stats':
##
## step
library(parsnip)
library(workflows)
# 选择模型线性回归
lm_spec <- linear_reg() %>%
set_engine("lm")
# 进行数据预处理
spline_cars <- recipe(mpg ~ ., data = mtcars) %>%
step_ns(disp, deg_free = 10) %>%
prep()
spline_cars_prepped <- bake(spline_cars, new_data = NULL)
# 建立模型
lm_fit <- fit(lm_spec, mpg ~ ., data = spline_cars_prepped)
lm_fit
## parsnip model object
##
##
## Call:
## stats::lm(formula = mpg ~ ., data = data)
##
## Coefficients:
## (Intercept) cyl hp drat wt qsec
## 49.79343 -3.32384 -0.02585 -2.76818 -0.94294 0.21909
## vs am gear carb disp_ns_01 disp_ns_02
## -2.83931 -1.10330 2.82343 0.28715 -9.88877 -12.95031
## disp_ns_03 disp_ns_04 disp_ns_05 disp_ns_06 disp_ns_07 disp_ns_08
## -4.94989 -15.45945 0.04334 -6.69861 -3.37594 5.57955
## disp_ns_09 disp_ns_10
## -10.00476 -4.61704
然后是使用workflow
的步骤。
# 选择模型线性回归
lm_spec <- linear_reg() %>%
set_engine("lm")
# 建立菜谱
spline_cars <- recipe(mpg ~ ., data = mtcars) %>%
step_ns(disp, deg_free = 10)
# 建立workflow
car_wflow <- workflow() %>%
add_recipe(spline_cars) %>%
add_model(lm_spec)
# 建立模型
car_wflow_fit <- car_wflow %>% fit(mtcars)
car_wflow_fit
## ══ Workflow [trained] ══════════════════════════════════════════════════════════
## Preprocessor: Recipe
## Model: linear_reg()
##
## ── Preprocessor ────────────────────────────────────────────────────────────────
## 1 Recipe Step
##
## • step_ns()
##
## ── Model ───────────────────────────────────────────────────────────────────────
##
## Call:
## stats::lm(formula = ..y ~ ., data = data)
##
## Coefficients:
## (Intercept) cyl hp drat wt qsec
## 49.79343 -3.32384 -0.02585 -2.76818 -0.94294 0.21909
## vs am gear carb disp_ns_01 disp_ns_02
## -2.83931 -1.10330 2.82343 0.28715 -9.88877 -12.95031
## disp_ns_03 disp_ns_04 disp_ns_05 disp_ns_06 disp_ns_07 disp_ns_08
## -4.94989 -15.45945 0.04334 -6.69861 -3.37594 5.57955
## disp_ns_09 disp_ns_10
## -10.00476 -4.61704
结果一模一样。
可以看到使用了workflow之后,就不再需要先把数据处理好了,数据预处理已经在你的workflow
之中,当你在建立模型时,它会自动帮你先进行数据预处理再建模。
基本使用和使用注意
有多种方式构造workflow
,但是一定要记住,add_model(xxxx)
这一步是必须的!
它的基本使用如下:
代码语言:javascript复制car_wflow <- workflow() %>%
add_recipe(spline_cars) %>%
add_model(lm_spec)
如果你没有预处理步骤,也是可以使用的。
代码语言:javascript复制# 虽然建立了菜谱,但其实没有任何预处理
spline_cars <- recipe(mpg ~ ., data = mtcars)
# 依然可以建立workflow
car_wflow <- workflow() %>%
add_recipe(spline_cars) %>%
add_model(lm_spec)
car_wflow
## ══ Workflow ════════════════════════════════════════════════════════════════════
## Preprocessor: Recipe
## Model: linear_reg()
##
## ── Preprocessor ────────────────────────────────────────────────────────────────
## 0 Recipe Steps
##
## ── Model ───────────────────────────────────────────────────────────────────────
## Linear Regression Model Specification (regression)
##
## Computational engine: lm
但这种情况,你可以使用以下方式,可能更好理解:
代码语言:javascript复制# 方式1
car_wflow <- workflow() %>%
add_model(lm_spec) %>%
add_variables(outcomes = mpg, predictors = everything())
f1 <- car_wflow %>% fit(data = mtcars)
f1
## ══ Workflow [trained] ══════════════════════════════════════════════════════════
## Preprocessor: Variables
## Model: linear_reg()
##
## ── Preprocessor ────────────────────────────────────────────────────────────────
## Outcomes: mpg
## Predictors: everything()
##
## ── Model ───────────────────────────────────────────────────────────────────────
##
## Call:
## stats::lm(formula = ..y ~ ., data = data)
##
## Coefficients:
## (Intercept) cyl disp hp drat wt
## 12.30337 -0.11144 0.01334 -0.02148 0.78711 -3.71530
## qsec vs am gear carb
## 0.82104 0.31776 2.52023 0.65541 -0.19942
# 方式2
car_wflow <- workflow() %>%
add_model(lm_spec) %>%
add_formula(mpg ~ .)
f2 <- car_wflow %>% fit(data = mtcars)
f2
## ══ Workflow [trained] ══════════════════════════════════════════════════════════
## Preprocessor: Formula
## Model: linear_reg()
##
## ── Preprocessor ────────────────────────────────────────────────────────────────
## mpg ~ .
##
## ── Model ───────────────────────────────────────────────────────────────────────
##
## Call:
## stats::lm(formula = ..y ~ ., data = data)
##
## Coefficients:
## (Intercept) cyl disp hp drat wt
## 12.30337 -0.11144 0.01334 -0.02148 0.78711 -3.71530
## qsec vs am gear carb
## 0.82104 0.31776 2.52023 0.65541 -0.19942
两种方法得到的结果是一样的~
add_xxx
的顺序并没有要求,只要别少了add_model(xxxx)
这一步就可以!
如果你熟练以后也可以这样写:
代码语言:javascript复制tree_wf <- workflow(preprocessor = spline_cars,
spec = bayes_lm
)
## Error in workflow(preprocessor = spline_cars, spec = bayes_lm): object 'bayes_lm' not found
由于workflow
中既包含了模型,也包含了数据预处理,所以你可能需要单独提取你想要的部分,它为你提供了非常多的函数,可以快速提取其中的内容,基本用法都是extract_xxxx()
。
举几个例子,这些函数会在以后的推文中陆续使用到:
代码语言:javascript复制extract_spec_parsnip()
extract_recipe()
extract_fit_parsnip()
extract_fit_engine()
......
除此之外,你还可以移除、更新workflow
:
remove_formula()
update_formula()
remove_model()
update_model()
remove_recipe()
update_recipe()
remove_variables()
update_variables()
以上就是workflow的使用,大家如果要用tiydmodels
做机器学习,一定要学会这个东西,因为经常要用!