레이싱 방법을 사용하여 xgboost 모델을 조정하고 홈런을 예측하십시오 ⚾️

이것은 screencasts 패키지를 시작하는 것부터 더 복잡한 모델 튜닝에 이르기까지 어떻게 사용하는지 보여주는 tidymodels 최신 시리즈입니다. 경쟁 데이터 과학 스트리밍 쇼인 SLICED의 이번 주 에피소드에서는 참가자들이 최근 야구 경기에서 홈런을 예측하기 위해 경쟁했습니다. 솔직히 저는 야구 ⚾에 대해 잘 모르지만 finetune 패키지가 최근에 출시되었고 이 도전은 튜닝을 위해 레이싱 방법을 사용하는 방법을 보여줄 좋은 기회를 제공합니다.



다음은 비디오 대신 또는 비디오에 추가하여 읽기를 선호하는 사람들을 위해 비디오에서 사용한 코드입니다.

데이터 탐색



우리의 모델링 목표는 히트에 대한 주어진 기능을 예측하는 것입니다whether a batter’s hit results in a home run. 제공된 기본 데이터 세트는 training.csv라는 CSV 파일에 있습니다.

library(tidyverse)
train_raw <- read_csv("train.csv")



이 데이터 세트의 많은 탐색적 데이터 분석 및 시각화를 볼 수 있지만 더 잘 이해하기 위해 몇 가지 플롯을 만들어 보겠습니다.

홈플레이트 주변의 물리적 공간에서 홈런은 어떻게 분배됩니까?

train_raw %>%
  ggplot(aes(plate_x, plate_z, z = is_home_run)) +
  stat_summary_hex(alpha = 0.8, bins = 10) +
  scale_fill_viridis_c(labels = percent) +
  labs(fill = "% home runs")





방망이를 떠나는 공의 발사 속도와 각도는 홈런 비율에 어떤 영향을 줍니까?

train_raw %>%
  ggplot(aes(launch_angle, launch_speed, z = is_home_run)) +
  stat_summary_hex(alpha = 0.8, bins = 15) +
  scale_fill_viridis_c(labels = percent) +
  labs(fill = "% home runs")





볼 수, 스트라이크 수 또는 이닝과 같은 속도는 홈런에 어떤 영향을 줍니까?

train_raw %>%
  mutate(is_home_run = if_else(as.logical(is_home_run), "yes", "no")) %>%
  select(is_home_run, balls, strikes, inning) %>%
  pivot_longer(balls:inning) %>%
  mutate(name = fct_inorder(name)) %>%
  ggplot(aes(value, after_stat(density), fill = is_home_run)) +
  geom_histogram(alpha = 0.5, binwidth = 1, position = "identity") +
  facet_wrap(~name, scales = "free") +
  labs(fill = "Home run?")





확실히 더 많은 것을 발견할 수 있지만 모델링으로 넘어 갑시다.

모델 구축



"데이터 예산"을 설정하여 모델링을 시작하겠습니다. 원본 데이터 세트의 0과 1을 분류 모델링을 위한 요소로 변환하겠습니다.

library(tidymodels)

set.seed(123)
bb_split <- train_raw %>%
  mutate(
    is_home_run = if_else(as.logical(is_home_run), "HR", "no"),
    is_home_run = factor(is_home_run)
  ) %>%
  initial_split(strata = is_home_run)
bb_train <- training(bb_split)
bb_test <- testing(bb_split)

set.seed(234)
bb_folds <- vfold_cv(bb_train, strata = is_home_run)
bb_folds


## # 10-fold cross-validation using stratification 
## # A tibble: 10 × 2
## splits id    
## <list> <chr> 
## 1 <split [31214/3469]> Fold01
## 2 <split [31214/3469]> Fold02
## 3 <split [31214/3469]> Fold03
## 4 <split [31215/3468]> Fold04
## 5 <split [31215/3468]> Fold05
## 6 <split [31215/3468]> Fold06
## 7 <split [31215/3468]> Fold07
## 8 <split [31215/3468]> Fold08
## 9 <split [31215/3468]> Fold09
## 10 <split [31215/3468]> Fold10



피처 엔지니어링의 경우 플레이어의 피치 및 핸드에 대한 정보와 함께 EDA 중에 이미 탐색한 변수에 집중하겠습니다. 특히 launch_anglelaunch_speed 에 누락된 데이터가 있으므로 해당 값을 대치하겠습니다.

bb_rec <-
  recipe(is_home_run ~ launch_angle + launch_speed + plate_x + plate_z +
    bb_type + bearing + pitch_mph +
    is_pitcher_lefty + is_batter_lefty +
    inning + balls + strikes + game_date,
  data = bb_train
  ) %>%
  step_date(game_date, features = c("week"), keep_original_cols = FALSE) %>%
  step_unknown(all_nominal_predictors()) %>%
  step_dummy(all_nominal_predictors(), one_hot = TRUE) %>%
  step_impute_median(all_numeric_predictors(), -launch_angle, -launch_speed) %>%
  step_impute_linear(launch_angle, launch_speed,
    impute_with = imp_vars(plate_x, plate_z, pitch_mph)
  ) %>%
  step_nzv(all_predictors())

## we can `prep()` just to check that it works
prep(bb_rec)


## Data Recipe
## 
## Inputs:
## 
## role #variables
## outcome 1
## predictor 13
## 
## Training data contained 34683 data points and 15255 incomplete rows. 
## 
## Operations:
## 
## Date features from game_date [trained]
## Unknown factor level assignment for bb_type, bearing [trained]
## Dummy variables from bb_type, bearing [trained]
## Median Imputation for plate_x, plate_z, pitch_mph, ... [trained]
## Linear regression imputation for launch_angle, launch_speed [trained]
## Sparse, unbalanced variable filter removed bb_type_unknown, bearing_unknown [trained]



이제 조정 가능한 xgboost 모델 사양을 생성해 보겠습니다. SLICED와 같은 경쟁에서 우리는 시간 제약 때문에 이러한 모든 매개변수를 조정하지 않고 대신 가장 중요한 일부만 조정하기를 원할 것입니다.

xgb_spec <-
  boost_tree(
    trees = tune(),
    min_n = tune(),
    mtry = tune(),
    learn_rate = 0.01
  ) %>%
  set_engine("xgboost") %>%
  set_mode("classification")

xgb_wf <- workflow(bb_rec, xgb_spec)



레이싱을 사용하여 xgboost 조정



이제 제대로 작동하지 않는 매개변수 조합can use tune_race_anova() to eliminate이 있습니다. 이 특정 SLICED 에피소드는 로그 손실에 대해 평가되었습니다.

library(finetune)
doParallel::registerDoParallel()

set.seed(345)
xgb_rs <- tune_race_anova(
  xgb_wf,
  resamples = bb_folds,
  grid = 15,
  metrics = metric_set(mn_log_loss),
  control = control_race(verbose_elim = TRUE)
)



우리가 시도한 가능한 매개변수 조합이 "경주"중에 어떻게 작동했는지 시각화할 수 있습니다. 모든 재샘플에서 분명히 제대로 작동하지 않는 매개변수 조합을 평가하지 않음으로써 엄청난 시간을 절약한 방법에 주목하십시오. 우리는 좋은 매개변수 조합으로만 계속 진행했습니다.

plot_race(xgb_rs)





그리고 우리는 최고의 결과를 볼 수 있습니다.

show_best(xgb_rs)


## # A tibble: 1 × 9
## mtry trees min_n .metric .estimator mean n std_err .config          
## <int> <int> <int> <chr> <chr> <dbl> <int> <dbl> <chr>            
## 1 6 1536 11 mn_log_lo… binary 0.0981 10 0.00171 Preprocessor1_Mo…


last_fit()를 사용하여 교육 데이터에 마지막 시간을 맞추고 테스트 데이터에서 마지막 시간을 평가해 보겠습니다.

xgb_last <- xgb_wf %>%
  finalize_workflow(select_best(xgb_rs, "mn_log_loss")) %>%
  last_fit(bb_split)

xgb_last


## # Resampling results
## # Manual resampling 
## # A tibble: 1 × 6
## splits id .metrics .notes .predictions .workflow
## <list> <chr> <list> <list> <list> <list>   
## 1 <split [34683… train/test… <tibble [2 … <tibble [0… <tibble [11,561… <workflo…



우리는 테스트 세트에 대한 예측을 수집하고 ROC 곡선을 생성하거나 이 경우 로그 손실을 계산하는 등 원하는 모든 작업을 수행할 수 있습니다.

collect_predictions(xgb_last) %>%
  mn_log_loss(is_home_run, .pred_HR)


## # A tibble: 1 × 3
## .metric .estimator .estimate
## <chr> <chr> <dbl>
## 1 mn_log_loss binary 0.0975



이것은 단일 모델에 꽤 좋습니다. 이 데이터 세트를 사용하여 이것보다 더 나은 점수를 얻은 SLICED의 경쟁자는 모두 앙상블 모델을 사용했다고 생각합니다.

vip 패키지를 사용하여 변수 중요도 점수를 계산할 수도 있습니다.

library(vip)
extract_workflow(xgb_last) %>%
  extract_fit_parsnip() %>%
  vip(geom = "point", num_features = 15)





레이싱 방법을 사용하는 것은 가능한 많은 매개변수 옵션을 통해 더 빠르게 조정할 수 있는 좋은 방법입니다. SLICED 플레이오프의 두 번째이자 마지막 에피소드에 참가하는 다음 주 화요일에 테스트를 해보겠습니다!

좋은 웹페이지 즐겨찾기