변수선택 자동화를 위해서 “재귀 변수 제거법 (Recursive Feature Elimination)”, “보루타 알고리즘 (Boruta Algorithm)”을 살펴본다.
미군 신체측정 데이터셋(Anthropometric Survey of US Army Personnel, ANSUR 2)은 2012년 내부에 공개되었고 2017년에 대중에 공개되었다. 총 6,000명 군인(남자 4,082, 여자 1,986)에 대한 측정정보를 담고 있다.
library(tidyverse)
male_dat <- read_csv("http://tools.openlab.psu.edu/publicData/ANSUR_II_MALE_Public.csv")
female_dat <- read_csv("http://tools.openlab.psu.edu/publicData/ANSUR_II_FEMALE_Public.csv")
soldier_dat <- bind_rows(male_dat, female_dat)
soldier_dat %>% write_rds("data/soldier_dat.rds")
다운로드 받은 남녀 데이터를 결합하여 남자군인, 여자군인을 분류하는데 사용되는 X
설계행렬을 추출한다.
soldier_dat <- read_rds("data/soldier_dat.rds") %>%
sample_frac(0.1)
X_df <- soldier_dat %>%
select(-c("subjectid","SubjectId", "Gender", "Date", "Installation", "Component", "Branch", "PrimaryMOS", "SubjectsBirthLocation", "SubjectNumericRace", "Ethnicity", "DODRace", "Heightin", "Weightlbs")) %>%
mutate(WritingPreference = as.factor(WritingPreference))
y_df <- soldier_dat %>%
select(gender = Gender) %>%
mutate(gender = factor(gender, levels = c("Female", "Male")))
Xy_df <- bind_cols(y_df, X_df)
보루타 알고리즘을 통해 변수를 선택할 수 있다. 변수선택에는 크게 다음과 같은 세가지 방식이 존재한다.
보루타 알고리즘은 Random Forest에 기반한 변수 선택방법으로 Z값을 활용한다는 점이 다른 기존 변수방법과 비교하여 차이가 난다.
속도를 위해서 전체 변수를 모두 사용하는 대신에 앞에서부터 30개만 뽑아 보루타 변수선택 모형을 생성시킨다.
library(Boruta)
Xy_boruta <- Boruta(gender ~ ., data = Xy_df[, 1:31], doTrace = 2, maxRuns = 500)
print(Xy_boruta)
Boruta performed 77 iterations in 12.1455 secs.
29 attributes confirmed important:
abdominalextensiondepthsitting, acromialheight,
acromionradialelength, anklecircumference, axillaheight and 24
more;
1 attributes confirmed unimportant:
crotchlengthposterioromphalion;
plot(Xy_boruta, las = 2, cex.axis = 0.7)
attStats(Xy_boruta) %>%
rownames_to_column(var="variable") %>%
arrange(desc(medianImp)) %>%
DT::datatable()
재귀 변수 제거법 (Recursive Feature Elimination)을 사용해서 변수를 선택해보자. caret
팩키지 rfeControl()
함수를 사용해서 예측모형 최적 변수를 선택해보자.
Random Forest를 사용한 성능과 함께 선택된 변수는 rfe_res$optVariables
에 저장되어 있다.
library(caret)
library(randomForest)
rfe_control <- rfeControl(functions = rfFuncs, method="cv", number=10)
rfe_res <- rfe(x = Xy_df[, -1], y = Xy_df$gender, sizes = 2^(2:4), rfeControl = rfe_control)
print(rfe_res)
Recursive feature selection
Outer resampling method: Cross-Validated (10 fold)
Resampling performance over subset size:
Variables Accuracy Kappa AccuracySD KappaSD Selected
4 0.9769 0.9495 0.01591 0.03474
8 0.9818 0.9598 0.01224 0.02720 *
16 0.9818 0.9599 0.01454 0.03204
95 0.9785 0.9526 0.01581 0.03468
The top 5 variables (out of 8):
neckcircumference, neckcircumferencebase, hipbreadthsitting, biacromialbreadth, handcircumference
plot(rfe_res, type = c("g", "o"))
rfe_res$optVariables
[1] "neckcircumference" "neckcircumferencebase" "hipbreadthsitting"
[4] "biacromialbreadth" "handcircumference" "shouldercircumference"
[7] "wristcircumference" "handbreadth"
전체 변수를 예측모형에 사용하는 대신 재귀 변수 제거법(Recursive Feature Elimination)을 사용해서 훨씬 속도가 빠르게 예측모형을 구축해낸다.
library(tidymodels)
library(rsample)
library(parsnip)
Xy_rfe_df <- Xy_df %>%
select(c("gender", rfe_res$optVariables))
# 데이터 분할: 훈련/시험
basetable_split <- initial_split(Xy_rfe_df, props = 7/10)
train_dat <- training(basetable_split)
test_dat <- testing(basetable_split)
# 예측모형 적합
rfe_rf <- rand_forest(trees = 1000, mode = "classification") %>%
set_engine("ranger", seed = 63233) %>%
fit(gender ~ ., data = train_dat)
# 예측모형 성능평가
rfe_rf_prob <- predict(rfe_rf, test_dat, type="prob")
rfe_rf_class <- ifelse(rfe_rf_prob[,2] > .68, "Male", "Female") %>% as.factor()
caret::confusionMatrix(rfe_rf_class, test_dat$gender)
Confusion Matrix and Statistics
Reference
Prediction Female Male
Female 44 3
Male 0 104
Accuracy : 0.9801
95% CI : (0.943, 0.9959)
No Information Rate : 0.7086
P-Value [Acc > NIR] : <2e-16
Kappa : 0.9528
Mcnemar's Test P-Value : 0.2482
Sensitivity : 1.0000
Specificity : 0.9720
Pos Pred Value : 0.9362
Neg Pred Value : 1.0000
Prevalence : 0.2914
Detection Rate : 0.2914
Detection Prevalence : 0.3113
Balanced Accuracy : 0.9860
'Positive' Class : Female
Random Forest 예측모형만 사용해서 변수를 선택하지 말고 다양한 알고리즘을 사용해서 모든 알고리즘이 선택한 변수만을 대상으로 예측모형을 구축해 보자.
## Random Forest
rfe_rf_control <- rfeControl(functions = rfFuncs, method="cv", number=10)
rfe_rf_res <- rfe(x = Xy_df[, -1], y = Xy_df$gender, sizes = 2^(2:4), rfeControl = rfe_rf_control)
## SVM
rfe_svm_control <- rfeControl(functions = svmFuncs, method="cv", number=10)
rfe_svm_res <- rfe(x = Xy_df[, -1], y = Xy_df$gender, sizes = 2^(2:4), rfeControl = rfe_svm_control)