tidymodels工作流:workflow

2023-08-30 12:37:57 浏览数 (2)

在阅读这篇文章前,我强烈建议你先读一下tidymodels入门篇:tidymodels用于机器学习的细节,首先对tidymodels有一个整体的认知。

今天主要介绍workflow的用法。

workflow可以把你的数据预处理步骤和模型连接起来,形成一个整体,而不是完全分割开来的,在tidymodels中主要作用是连接parsniprecipes产生的对象。

一个完整的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的步骤。

代码语言:javascript复制
# 选择模型线性回归
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

代码语言:javascript复制
remove_formula()
update_formula()
remove_model()
update_model()
remove_recipe()
update_recipe()
remove_variables()
update_variables()

以上就是workflow的使用,大家如果要用tiydmodels做机器学习,一定要学会这个东西,因为经常要用!

0 人点赞