1 파이썬 scikit-learn 1

기계학습 모형 개발을 위해서 전용 라이브러리 scikit-learn이 잘 준비되어 있다. 물론 R에서 기계학습을 위해서 The caret Package 팩키지가 있지만 개발된지 거의 20년이 되어가고 현재와 같은 상황을 반영하여 설계된 것이 아니라 RStudio로 자리를 옮긴 후에 본격적인 재설계와 새로운 바탕에서 새로 개발되고 있고 그 결과물 중 하나가 parsnip이다.

predictive models

2 tidymodelsparsnip

2.1 데이터

캐글 hr-comma-sep, “HR Analytics for employee rentension” 데이터셋을 가져와서 직원 이탈에 대한 예측모형을 개발한다.

Skim summary statistics
 n obs: 14999 
 n variables: 10 

── Variable type:character ──────────────────────────────────────────────────────────────────────
    variable missing complete     n min max empty n_unique
 departments       0    14999 14999   2  11     0       10
      salary       0    14999 14999   3   6     0        3

── Variable type:numeric ────────────────────────────────────────────────────────────────────────
              variable missing complete     n    mean    sd    p0    p25
  average_montly_hours       0    14999 14999 201.05  49.94 96    156   
       last_evaluation       0    14999 14999   0.72   0.17  0.36   0.56
                  left       0    14999 14999   0.24   0.43  0      0   
        number_project       0    14999 14999   3.8    1.23  2      3   
 promotion_last_5years       0    14999 14999   0.021  0.14  0      0   
    satisfaction_level       0    14999 14999   0.61   0.25  0.09   0.44
    time_spend_company       0    14999 14999   3.5    1.46  2      3   
         work_accident       0    14999 14999   0.14   0.35  0      0   
    p50    p75 p100     hist
 200    245     310 ▁▇▇▆▆▇▆▂
   0.72   0.87    1 ▂▇▇▆▆▇▇▇
   0      0       1 ▇▁▁▁▁▁▁▂
   4      5       7 ▅▇▁▇▅▁▂▁
   0      0       1 ▇▁▁▁▁▁▁▁
   0.64   0.82    1 ▅▂▅▆▆▇▇▇
   3      4      10 ▇▂▁▁▁▁▁▁
   0      0       1 ▇▁▁▁▁▁▁▂

2.2 데이터 전처리

범주형 변수를 명시적으로 정의한다. 대표적으로 departments, left, work_accident를 범주형 변수로 빼고 나머지는 숫자형이라 예측모형을 돌리기 위한 최소한의 기준을 만족시켰다.

Skim summary statistics
 n obs: 14999 
 n variables: 10 

── Variable type:character ──────────────────────────────────────────────────────────────────────
 variable missing complete     n min max empty n_unique
   salary       0    14999 14999   3   6     0        3

── Variable type:factor ─────────────────────────────────────────────────────────────────────────
      variable missing complete     n n_unique
   departments       0    14999 14999       10
          left       0    14999 14999        2
 work_accident       0    14999 14999        2
                                top_counts ordered
 sal: 4140, tec: 2720, sup: 2229, IT: 1227   FALSE
              sta: 11428, lef: 3571, NA: 0   FALSE
                  0: 12830, 1: 2169, NA: 0   FALSE

── Variable type:numeric ────────────────────────────────────────────────────────────────────────
              variable missing complete     n    mean    sd    p0    p25
  average_montly_hours       0    14999 14999 201.05  49.94 96    156   
       last_evaluation       0    14999 14999   0.72   0.17  0.36   0.56
        number_project       0    14999 14999   3.8    1.23  2      3   
 promotion_last_5years       0    14999 14999   0.021  0.14  0      0   
    satisfaction_level       0    14999 14999   0.61   0.25  0.09   0.44
    time_spend_company       0    14999 14999   3.5    1.46  2      3   
    p50    p75 p100     hist
 200    245     310 ▁▇▇▆▆▇▆▂
   0.72   0.87    1 ▂▇▇▆▆▇▇▇
   4      5       7 ▅▇▁▇▅▁▂▁
   0      0       1 ▇▁▁▁▁▁▁▁
   0.64   0.82    1 ▅▂▅▆▆▇▇▇
   3      4      10 ▇▂▁▁▁▁▁▁

3 tidymodels 예측모형

3.1 훈련/시험 데이터 구분

가장 먼저 훈련/시험 데이터 구분한다. 이를 위해서 rsample 팩키지를 사용하고 initial_split() 함수를 사용해서 7:3으로 훈련/시험 데이터로 쪼갠다.

<10500/4499/14999>

훈련/시험 데이터프레임으로 training(), testing() 함수를 각각 사용해서 준비한다.

3.2 피처 공학(Feature engineering)

예측모형을 개발할 때 피처 공학(Feature engineering)을 통해 예측모형 base table을 제작해야 한다. tidymodels에서는 이를 요리법(recipe)에 비유하여 요리 레시피를 준비해야 한다. 대표적인 요리법에는 결측값 제거, 이상점 처리, 다공선성을 갖는 변수 제거, 중심화와 척도 조정을 통한 정규화, 가변수 처리 등이 포함된다.

범주형변수는 가변수화(step_dummy())하고 연속형 변수는 정규화하는 요리법을 hr_recipe로 준비한다. 그리고 이를 prep()으로 준비하여 bake()해서 예측모형에 넣을 수 있도록 구워둔다.

# A tibble: 10,500 x 19
   satisfaction_le… last_evaluation number_project average_montly_…
              <dbl>           <dbl>          <dbl>            <dbl>
 1           -0.937          -1.09          -1.47            -0.892
 2            0.753           0.844          0.960            1.22 
 3            0.431           0.903          0.960            0.435
 4           -0.816          -1.26          -1.47            -0.973
 5           -2.06            0.317          1.77             0.917
 6           -0.655          -1.03          -1.47            -1.33 
 7            0.914           1.20           0.148            0.656
 8           -0.937          -1.03          -1.47            -1.17 
 9           -0.655          -1.44          -1.47            -0.832
10            0.673           1.61           0.148            1.08 
# … with 10,490 more rows, and 15 more variables:
#   time_spend_company <dbl>, left <fct>, promotion_last_5years <dbl>,
#   work_accident_X1 <dbl>, departments_hr <dbl>, departments_IT <dbl>,
#   departments_management <dbl>, departments_marketing <dbl>,
#   departments_product_mng <dbl>, departments_RandD <dbl>,
#   departments_sales <dbl>, departments_support <dbl>,
#   departments_technical <dbl>, salary_low <dbl>, salary_medium <dbl>

3.3 모형 적합

드디어 parsnip의 가장 인기있는 부분을 살펴볼 수 있는데 앞서 준비한 base table 데이터프레임을 다음 3단계로 준비하여 훈련데이터를 예측모형에 적합시킨다.

  • 예측모형 유형: 로지스틱 회귀모형(logistic_reg), 모드(classification)
  • 엔진(set_engine): glm
  • 적합(fit): fit

예를 들어, logistic_reg에 사용가능한 엔진은 glm, glmnet, stan, spark, keras 등이 있다.

3.4 모형 성능평가

yardstick 팩키지를 사용하게 되면 예측모형의 성능을 수월히 평가할 수 있다.

3.4.1 시험데이터 예측

먼저 predict() 함수로 예측값을 뽑아내서 직원 잔존과 이탈여부를 데이터프레임으로 만들 수 있다.

# A tibble: 4,499 x 2
   .pred_class left 
   <fct>       <fct>
 1 left        left 
 2 left        left 
 3 stay        left 
 4 stay        left 
 5 stay        left 
 6 left        left 
 7 stay        left 
 8 left        left 
 9 stay        left 
10 left        left 
# … with 4,489 more rows

3.4.2 모형성능

conf_mat() 함수를 사용해서 이진 분류 성능예측모형을 확인할 수 있다. 물론, yardstick 팩키지 metrics() 함수를 사용해도 된다.

# A tibble: 2 x 3
  Prediction  left  stay
  <chr>      <int> <int>
1 left         361   271
2 stay         668  3199
# A tibble: 2 x 3
  .metric  .estimator .estimate
  <chr>    <chr>          <dbl>
1 accuracy binary         0.791
2 kap      binary         0.316

실제 예측모형을 현업에 적용시킬 때, 정확도(accuracy) 보다는 precision, recall, 혹은 f1_score가 더 적합한 측도가 될 수 있다.

# A tibble: 1 x 3
  precision recall f1_score
      <dbl>  <dbl>    <dbl>
1     0.827  0.922    0.872

4 tidymodels - ranger 예측모형

GLM 계열 예측모형은 2015년 전까지 가장 검증된 예측모형으로 자리를 잡았으나 그 후 random forest, xgboost 계열 앙상블 모형으로 대체되고 있지만, 기준 성능을 나타내는 지표를 제공한다는 점에서 나름 굳건히 자리를 지켜나가고 있다.

random forest 예측모형을 C/C++로 성능을 대폭 향상시킨 ranger 팩키지를 많이 사용하는데 사용업은 크게 두가지를 추가로 설정해야 된다. 하나는 교차검증(CV, cross-validation), set_engine을 설정하는 부분이다.

4.1 교차검증(CV)

vfold_cv() 함수를 사용해서 훈련데이터를 훈련/검증(train/validation) 데이터로 쪼갠다. CV를 10조각 내는 경우 훈련데이터를 9:1비율로 자동으로 쪼갠다.

훈련/시험 데이터 쪼개기

<10500/4499/14999>

훈련/교차검증 데이터 쪼개기

#  10-fold cross-validation 
# A tibble: 10 x 2
   splits              id    
   <named list>        <chr> 
 1 <split [9.4K/1.1K]> Fold01
 2 <split [9.4K/1.1K]> Fold02
 3 <split [9.4K/1.1K]> Fold03
 4 <split [9.4K/1.1K]> Fold04
 5 <split [9.4K/1.1K]> Fold05
 6 <split [9.4K/1.1K]> Fold06
 7 <split [9.4K/1.1K]> Fold07
 8 <split [9.4K/1.1K]> Fold08
 9 <split [9.4K/1.1K]> Fold09
10 <split [9.4K/1.1K]> Fold10
<9450/1050/10500>

4.2 피처 공학(feature engineering)

교차검증으로 준비된 훈련/검증 데이터셋에 대하여 피처 공학을 적용시키는데, 특별히 더 추가하지 않고 앞서 준비한 hr_recipe를 재사용한다.

function(df) {
  recipe(left ~ ., data = df) %>%
    step_dummy(all_nominal(), -all_outcomes()) %>%
    step_center(all_numeric()) %>%
    step_scale(all_numeric()) %>%
    prep(data = df)
}

4.4 ranger 예측모형 성능

conf_mat() 함수와 summary() 함수를 파이프로 연결시키면 예측모형 성능에 대한 모든 지표를 추출할 수 있다. 가장 많이 사용하는 “accuracy”, “precision”, “recall”, “f_meas” 측도만 추출하여 향상된 성능을 파악한다.

# A tibble: 4 x 2
  .metric   .estimate
  <chr>         <dbl>
1 accuracy      0.966
2 precision     0.961
3 recall        0.996
4 f_meas        0.978

5 tidymodels - xgboost 예측모형

5.1 XGBoost 모형적합

fit_rf() 함수에 XGBoost 팩키지 초모수 learn_rate, tree_depth, sample_size을 적용시키도록 예측모형을 boost_tree로 변경시키고, set_enginexgboost로 바꿔 훈련시킨다.

# A tibble: 10,500 x 3
   id     truth prediction
   <chr>  <fct> <fct>     
 1 Fold01 left  left      
 2 Fold01 left  left      
 3 Fold01 left  left      
 4 Fold01 left  left      
 5 Fold01 left  left      
 6 Fold01 left  left      
 7 Fold01 left  left      
 8 Fold01 left  left      
 9 Fold01 left  left      
10 Fold01 left  left      
# … with 10,490 more rows

XGBoost 예측모형 성능을 동일한 방식으로 확인한다.

# A tibble: 4 x 2
  .metric   .estimate
  <chr>         <dbl>
1 accuracy      0.963
2 precision     0.962
3 recall        0.990
4 f_meas        0.976