1 Mở đầu

Những gói tạo nên tidymodels không làm nhiệm vụ thực hiện các mô hình thống kê. Mà thay vào đó, họ tập trung vào làm những việc xung quanh việc xây dựng mô hình, làm cho mô hình dễ hiểu hơn.

Xây dựng mô hình có nhiều bước nhỏ, mỗi gói trong hệ sinh thái này làm 1 hoặc vài phần trong các bước xây dựng mô hình:

  • rsample – Different types of re-samples
  • recipes – Transformations for model data pre-processing
  • parsnip – A common interface for model creation
  • yardstick – Measure model performance

Gói tidymodels không hoặc hiện tại chưa làm với dự báo chuỗi thời gian

2 Minh họa các bước thực hiện bằng dữ liệu iris

2.1 Pre-Process

Hầu hết việc biến đổi dữ liệu sẽ sử dụng gói dplyr. Các packages khác của hệ sinh thái tidyverse sử dụng đối với từng mô hình chuyên biệt hoặc phức tạp.

2.2 Data Sampling

Hàm initial_split() sử dụng để chia dữ liệu thành tập train và tập test. Mặc định, tỷ lệ 3:1 cho tập train và tập test.

iris_split <- initial_split(iris, prop = 0.6)
iris_split
## <Analysis/Assess/Total>
## <90/60/150>

Để lấy dữ liệu trainning dùng hàm trainning()

iris_split %>%
  training() %>%
  glimpse()
## Rows: 90
## Columns: 5
## $ Sepal.Length <dbl> 5.1, 4.9, 5.4, 4.6, 4.8, 4.3, 5.8, 5.7, 5.7, 5.1, 5.4, 5.~
## $ Sepal.Width  <dbl> 3.5, 3.0, 3.9, 3.4, 3.4, 3.0, 4.0, 4.4, 3.8, 3.8, 3.4, 3.~
## $ Petal.Length <dbl> 1.4, 1.4, 1.7, 1.4, 1.6, 1.1, 1.2, 1.5, 1.7, 1.5, 1.7, 1.~
## $ Petal.Width  <dbl> 0.2, 0.2, 0.4, 0.3, 0.2, 0.1, 0.2, 0.4, 0.3, 0.3, 0.2, 0.~
## $ Species      <fct> setosa, setosa, setosa, setosa, setosa, setosa, setosa, s~

2.3 Data pre-processing

recipes package cung cấp giao diện làm việc đối với tiền xử lý dữ liệu. Gói này cung cấp các hàm theo từng bước chế biến y hệt như công việc nấu nướng :D.

  • recipe(): hàm khởi tạo, y hệt như ggplot()

  • prep(): Thực hiện biến đổi dữ liệu. Mỗi cách biến đổi dữ liệu sẽ được thực hiện bởi 1 hàm bắt đầu bằng tiền tố step_. Ví dụ:

    • step_corr(): loại những biến có tương quan cao

    • step_center(): Chuẩn hóa biến numeric về trung bình bằng 0

    • step_scale(): Chuẩn hóa biến numeric về trung bình bằng 0, phương sai bằng 1

  • Một số hàm khác dùng để gói các biến theo nhóm như: all_outcomes() và all_predictors() dùng để gọi tất cả các biến outcomes hoặc các biến predictors

Ví dự sử dụng các hàm recipe(), prep(), các hàm step_ để tạo ra recipe object. Các bước thực hiện sẽ được mô tả một cách chi tiết

iris_recipe <- training(iris_split) %>%
  recipe(Species ~.) %>%
  step_corr(all_predictors()) %>%
  step_center(all_predictors(), -all_outcomes()) %>%
  step_scale(all_predictors(), -all_outcomes()) %>%
  prep()

iris_recipe
## Data Recipe
## 
## Inputs:
## 
##       role #variables
##    outcome          1
##  predictor          4
## 
## Training data contained 90 data points and no missing data.
## 
## Operations:
## 
## Correlation filter removed Petal.Length [trained]
## Centering for Sepal.Length, Sepal.Width, Petal.Width [trained]
## Scaling for Sepal.Length, Sepal.Width, Petal.Width [trained]

Các bước biến đổi dữ liệu đối với tập training sẽ được thực hiện giống hệt với tập testing. Để thực hiện biến đổi sử dụng hàm bake().

Chú ý, hàm testing() sử dụng để gọi dữ liệu testing

iris_testing <- iris_recipe %>%
  bake(testing(iris_split)) 

glimpse(iris_testing)
## Rows: 60
## Columns: 4
## $ Sepal.Length <dbl> -1.4278076, -1.5511308, -1.0578383, -1.0578383, -1.797777~
## $ Sepal.Width  <dbl> 0.2640318, 0.0440053, 1.1441378, 0.7040848, -0.3960477, 0~
## $ Petal.Width  <dbl> -1.3374757, -1.3374757, -1.3374757, -1.3374757, -1.337475~
## $ Species      <fct> setosa, setosa, setosa, setosa, setosa, setosa, setosa, s~

Đối với dữ liệu training, để lặp lại các bước như trên sẽ là thừa, ta chỉ cần sử dụng hàm juice để trích xuất dữ liệu

iris_training <- juice(iris_recipe) 

# Dùng juice tương đương với các bước dưới
# iris_training2 <- iris_recipe %>%
#   bake(training(iris_split)) 
# identical(iris_training, iris_training2)

glimpse(iris_training)
## Rows: 90
## Columns: 4
## $ Sepal.Length <dbl> -0.93451518, -1.18116141, -0.56454583, -1.55113076, -1.30~
## $ Sepal.Width  <dbl> 0.9241113, -0.1760212, 1.8042173, 0.7040848, 0.7040848, -~
## $ Petal.Width  <dbl> -1.3374757, -1.3374757, -1.0714584, -1.2044671, -1.337475~
## $ Species      <fct> setosa, setosa, setosa, setosa, setosa, setosa, setosa, s~

2.4 Model Training

Trên R, có rất nhiều packages làm cùng nhiệm vụ như nhau với cùng loại mô hình. Mỗi package có 1 số tên agruments riêng, làm cho người dùng khó nhớ. Vì dụ: ranger và randomForest cùng làm nhiệm vụ fit random Forest model. Để khai báo number of tree, ranger dùng num.trees, randomForest dùng ntree. Không dễ để nhớ khi thay đổi package.

Thay vì việc thay thế modeling package, tidymodels thay thể 1 chút trong giao diện. Hay nói cách khác là tidymodels cung cấp agrument giống nhau cho cùng loại mô hình.

Ví dụ: sử dụng hàm rand_forest() trong tidymodels. Thay vì đổi hàm và đổi gói, chỉ việc thay đổi set_engine(). Và sử dụng hàm fit() để khai báo dạng mô hình.

iris_ranger <- rand_forest(trees = 100, mode = "classification") %>%
  set_engine("ranger") %>%
  fit(Species ~ ., data = iris_training)
iris_rf <-  rand_forest(trees = 100, mode = "classification") %>%
  set_engine("randomForest") %>%
  fit(Species ~ ., data = iris_training)

Các agruments định nghĩa như trên sẽ làm cho người dùng linh động và dễ dàng hơn khi chuyển đổi qua lại.

Hơn nữa, hàm predict() của parsnip trả về tibble. Mặc định, predict variable đặt tên .pred_class.

predict(iris_ranger, iris_testing)
## # A tibble: 60 x 1
##    .pred_class
##    <fct>      
##  1 setosa     
##  2 setosa     
##  3 setosa     
##  4 setosa     
##  5 setosa     
##  6 setosa     
##  7 setosa     
##  8 setosa     
##  9 setosa     
## 10 setosa     
## # ... with 50 more rows

Rất dễ dàng khi sử dụng hàm dplyr’s bind_cols() để nối vào dữ liệu testing đã được baked

iris_ranger %>%
  predict(iris_testing) %>%
  bind_cols(iris_testing) %>%
  glimpse()
## Rows: 60
## Columns: 5
## $ .pred_class  <fct> setosa, setosa, setosa, setosa, setosa, setosa, setosa, s~
## $ Sepal.Length <dbl> -1.4278076, -1.5511308, -1.0578383, -1.0578383, -1.797777~
## $ Sepal.Width  <dbl> 0.2640318, 0.0440053, 1.1441378, 0.7040848, -0.3960477, 0~
## $ Petal.Width  <dbl> -1.3374757, -1.3374757, -1.3374757, -1.3374757, -1.337475~
## $ Species      <fct> setosa, setosa, setosa, setosa, setosa, setosa, setosa, s~

2.5 Model Validation

Sử dụng hàm metrics() để đo lượng performance của mô hình. Hàm này rất hay ở chỗ tự động chọn metrics phù hợp với loại mô hình. Hàm này cần phải khai báo 2 agruments là truthestimate.

iris_ranger %>%
  predict(iris_testing) %>%
  bind_cols(iris_testing) %>%
  metrics(truth = Species, estimate = .pred_class)
## # A tibble: 2 x 3
##   .metric  .estimator .estimate
##   <chr>    <chr>          <dbl>
## 1 accuracy multiclass     0.95 
## 2 kap      multiclass     0.925
iris_rf %>%
  predict(iris_testing) %>%
  bind_cols(iris_testing) %>%
  metrics(truth = Species, estimate = .pred_class)
## # A tibble: 2 x 3
##   .metric  .estimator .estimate
##   <chr>    <chr>          <dbl>
## 1 accuracy multiclass     0.917
## 2 kap      multiclass     0.875

Xác suất dự báo đối với từng class

Thêm type = “prob” vào hàm predict để có được xác suất dự báo với từng class

iris_ranger %>%
  predict(iris_testing, type = "prob") %>%
  glimpse()
## Rows: 60
## Columns: 3
## $ .pred_setosa     <dbl> 0.957361111, 0.945476190, 0.975000000, 0.991706349, 0~
## $ .pred_versicolor <dbl> 0.013984127, 0.032857143, 0.000000000, 0.002936508, 0~
## $ .pred_virginica  <dbl> 0.028654762, 0.021666667, 0.025000000, 0.005357143, 0~

Cũng rất dễ dàng để nối vào dữ liệu testing

iris_probs <- iris_ranger %>%
  predict(iris_testing, type = "prob") %>%
  bind_cols(iris_testing)

glimpse(iris_probs)
## Rows: 60
## Columns: 7
## $ .pred_setosa     <dbl> 0.957361111, 0.945476190, 0.975000000, 0.991706349, 0~
## $ .pred_versicolor <dbl> 0.013984127, 0.032857143, 0.000000000, 0.002936508, 0~
## $ .pred_virginica  <dbl> 0.028654762, 0.021666667, 0.025000000, 0.005357143, 0~
## $ Sepal.Length     <dbl> -1.4278076, -1.5511308, -1.0578383, -1.0578383, -1.79~
## $ Sepal.Width      <dbl> 0.2640318, 0.0440053, 1.1441378, 0.7040848, -0.396047~
## $ Petal.Width      <dbl> -1.3374757, -1.3374757, -1.3374757, -1.3374757, -1.33~
## $ Species          <fct> setosa, setosa, setosa, setosa, setosa, setosa, setos~

2.6 Curve methods

iris_probs%>%
  gain_curve(Species, .pred_setosa:.pred_virginica) %>%
  glimpse()
## Rows: 134
## Columns: 5
## $ .level          <chr> "setosa", "setosa", "setosa", "setosa", "setosa", "set~
## $ .n              <dbl> 0, 1, 2, 3, 4, 5, 7, 8, 9, 12, 13, 14, 15, 17, 18, 19,~
## $ .n_events       <dbl> 0, 1, 2, 3, 4, 5, 7, 8, 9, 12, 13, 14, 15, 17, 18, 19,~
## $ .percent_tested <dbl> 0.000000, 1.666667, 3.333333, 5.000000, 6.666667, 8.33~
## $ .percent_found  <dbl> 0, 5, 10, 15, 20, 25, 35, 40, 45, 60, 65, 70, 75, 85, ~

Để hình ảnh hóa kết quả dự báo sử dụng hàm autoplot()

iris_probs%>%
  gain_curve(Species, .pred_setosa:.pred_virginica) %>%
  autoplot()

iris_probs%>%
  roc_curve(Species, .pred_setosa:.pred_virginica) %>%
  autoplot()

  • Kết hợp xác suất dự báo cho mỗi giá trị, kết quả dự báo (không dùng xác suất) và giá trị thực tế. Sử dụng kết hợp với hàm dplyr’s select() cho ra kết quả easy to read
predict(iris_ranger, iris_testing, type = "prob") %>%
  bind_cols(predict(iris_ranger, iris_testing)) %>%
  bind_cols(select(iris_testing, Species)) %>%
  glimpse()
## Rows: 60
## Columns: 5
## $ .pred_setosa     <dbl> 0.957361111, 0.945476190, 0.975000000, 0.991706349, 0~
## $ .pred_versicolor <dbl> 0.013984127, 0.032857143, 0.000000000, 0.002936508, 0~
## $ .pred_virginica  <dbl> 0.028654762, 0.021666667, 0.025000000, 0.005357143, 0~
## $ .pred_class      <fct> setosa, setosa, setosa, setosa, setosa, setosa, setos~
## $ Species          <fct> setosa, setosa, setosa, setosa, setosa, setosa, setos~
predict(iris_ranger, iris_testing, type = "prob") %>%
  bind_cols(predict(iris_ranger, iris_testing)) %>%
  bind_cols(select(iris_testing, Species)) %>%
  metrics(truth = Species, .pred_setosa:.pred_virginica, estimate = .pred_class)
## # A tibble: 4 x 3
##   .metric     .estimator .estimate
##   <chr>       <chr>          <dbl>
## 1 accuracy    multiclass     0.95 
## 2 kap         multiclass     0.925
## 3 mn_log_loss multiclass     0.206
## 4 roc_auc     hand_till      0.992

Nguồn: https://www.r-bloggers.com/a-gentle-introduction-to-tidymodels/