개요(Abstraction)
UCI 저장소에 있는 반도체 생산 공정 데이터(Data from a semi-conductor manufacturing process)를 이용한다. 이미 데이터는 전처리 과정이 완료된 데이터이다. rpart을 제외한 많은 모델에서 결측치가 있는 데이터를 사용할 수 없다, randomForests, randomUmiformForests, EM 학습 패키지 또한 결측치 데이터를 사용할 수 없다.
1 훈련 데이터 생성
우리가 사용하는 데이터는 최대한 현실 세계를 반영하는 최소한의 표본 데이터이므로 데이터 준비 과정 절차가 다르면 만족할만한 예측 결과를 가져올 수 없다. 데이터량을 줄이기 특징 데이터가 중복 없이 존재한다. 즉 예측 데이터에서 분할 절차를 잘못하면 예측 능력에 실망한 결과를 보인다.
상관관계가 높은 예측자 제거
Amelia II를 이용하여 결측 데이터 처리를 완료한 상태이다. 이전 전처리 과정의 결과 데이터를 사용한다.
# 상관관계가 높은 컬럼 fc <- findCorrelation (as.matrix(sc.data.a.1$imputations$imp1), 0.90) length(fc) # 322 # 상관관계가 높은 예측자를 제거한다. sc.data.imp <- sc.data[, -fc] dim(sc.data.imp) #[1] 1567 268
상관관계가 높은 예측자는 특정 예측자에서 모델에 편향이 발생할 가능성이 있다. 그러므로 항상 학습하기 전 상관관계가 높은 예측자를 제거하고 모델 학습을 진행해야 한다.
훈련과 검증 데이터 생성
반도체 표본 데이터의 크기를 최소화하기 위해 특징을 나타내는 데이터는 중복해서 존재하지 않는다. 그러므로 이 절차 순서가 달라지면 만족 못하는 모델 예측 결과가 나타날 것이다.
# 데이터 묶기 sc.imp <- cbind(sc.data.a.1$imputations$imp1, LABELS = sc.label$V1) sc.imp$LABELS <- factor(sc.imp$LABELS) library(caret) # 표본의 구분(Class)을 많은 쪽 구분과 동등하게 만듬 set.seed(8000) sc.imp.up <- upSample(x = sc.imp[, -length(sc.imp)], y = sc.imp$LABELS, yname = "LABELS") # 훈련과 검증 데이터의 분리 sc.imp.up.rs <- createDataPartition(sc.imp.up$LABELS, times = 5, p = 0.7) # 훈련과 검증 데이터 sc.imp.up.train <- sc.imp.up[sc.imp.up.rs$Resample2, ] sc.imp.up.test <- sc.imp.up[-sc.imp.up.rs$Resample2, ]
2 randomForest
훈련 및 학습
library(randomForest) fit.rf.1 <- randomForest(LABELS ~ ., data = sc.imp.up.train, importance = TRUE) attributes(fit.rf.1) # $names # [1] "call" "type" "predicted" "err.rate" "confusion" "votes" # [7] "oob.times" "classes" "importance" "importanceSD" "localImportance" "proximity" # [13] "ntree" "mtry" "forest" "y" "test" "inbag" # [19] "terms" # $class # [1] "randomForest.formula" "randomForest" # mtry 값 확인 fit.rf.1$mtry # [1] 21 # 예측 pred.rf.1 <- predict(fit.rf.1, newdata = sc.imp.up.test ) # 예측 수행 table(OBSERV = sc.imp.up.test$LABELS, PRED = pred.rf.1) # PRED # OBSERV -1 1 # -1 438 0 # 1 0 438
변수 중요도와 에러 전개를 그림으로 확인한다.
plot(fit.rf.1) varImpPlot(fit.rf.1)
Figure 1: 오류 전개 |
Figure 2: 변수 중요도 |
변수 조정(Tunning)
우선 tuneRF() 함수를 이용하여 최적의 mtry 값을 찾는다.
tuneRF(x = sc.imp.up.train[, -length(sc.imp.up.train)], y = sc.imp.up.train$LABELS)
Figure 3: tuneRF() 결과, mtry 값 21은 앞에서 출력한 값과 같다. |
변수를 조정하여 학습하고 예측하면 동일한 결과를 보인다.
fit.rf.2 <- randomForest(LABELS ~ ., data = sc.imp.up.train, importance = TRUE, proximity = T, ntree=200, mtry = 11, nodesize = 1) pred.rf.2 <- predict(fit.rf.2, newdata = sc.imp.up.test ) table(OBSERV = sc.imp.up.test$LABELS, PRED = pred.rf.2) # PRED # OBSERV -1 1 # -1 438 0 # 1 0 438
3 randomUniformForest
randomUniformForest의 정의는 학습 데이터에서 많은 무작위 추출(randomized) 그리고 가지 치지 않는(unpruned) 이진 결정 트리(binary decision trees)를 사용하는 앙상블 모델(ensemble model)이다. 변수를 심도 있게 분석할 수 있으며, 연속적으로 입력되는 데이터에 대해 점증적 학습을 지원한다.
훈련
randomForests애서 변수 최적화를 시도한 값으로 훈련을 시킨다.
library(randomUniformForest) Y1 <- sc.imp.up.train$LABELS X1 <- sc.imp.up.train[, -ncol(sc.imp.up.train)] # run model: default options fit.ruf.1 <- randomUniformForest(X = X1, Y = Y1, ntree=200, mtry = 11, nodesize = 1, importance = TRUE ) # Call: # randomUniformForest.default(X = X1, Y = Y1, ntree = 200, mtry = 11, # nodesize = 1) # # Type of random uniform forest: Classification # # paramsObject # ntree 200 # mtry 11 # nodesize 1 # maxnodes Inf # replace TRUE # bagging FALSE # depth Inf # depthcontrol FALSE # OOB TRUE # importance TRUE # subsamplerate 1 # classwt FALSE # classcutoff FALSE # oversampling FALSE # outputperturbationsampling FALSE # targetclass -1 # rebalancedsampling FALSE # randomcombination FALSE # randomfeature FALSE # categorical variables FALSE # featureselectionrule entropy # # Out-of-bag (OOB) evaluation # OOB estimate of error rate: 0% # OOB error rate bound (with 1% deviation): 0% # # OOB confusion matrix: # Reference # Prediction -1 1 class.error # -1 1025 0 0 # 1 0 1025 0 # # OOB estimate of AUC: 1 # OOB estimate of AUPR: 1 # OOB estimate of F1-score: 1 # OOB (adjusted) estimate of geometric mean: 1 # # Breiman's bounds # Expected prediction error (under approximatively balanced classes): 0.5% # Upper bound: 3.48% # Average correlation between trees: 0.0151 # Strength (margin): 0.8675 # Standard deviation of strength: 0.1618 # call the summary() function gives some details about the forest and # global variable importance
과적합이 발생할 가능성이 있는지 주의 깊게 살펴야 한다. 이를 위해, Breiman’s bounds와 그들의 상세를 확인해야 한다. OOB 오류는 어떤 Breiman’s bound 안에 있음을 주목할 수 있다. 이는 모델이 잘 적합되었다고 판단할 수 있다(OOB estimate of error rate값이 Expected prediction error (under approximatively balanced classes) 값 보다 적음).
변수 중요도 확인
전역 변수 중요도(global variable importance)을 확인한다. summary() 함수를 실행하면 콘솔 출력과 플롯이 보인다. 그러나 정보 획득에 기반하는 전역 변수 중요도가 전부 0이어서 플롯이 보이지 않는다.
# global variable importance summary(fit.ruf.1) # Global Variable importance: # Note: most predictive features are ordered by 'score' and plotted. Most discriminant ones # should also be taken into account by looking 'class' and 'class.frequency'. # # 전역 변수 중요도의 percent.importance가 모두 0 이다. # variables score class class.frequency percent percent.importance # 1 V104 27 -1 0.60 100.00 0 # 2 V424 23 -1 0.55 84.86 0 # 3 V60 22 -1 0.54 82.20 0 # 4 V148 20 -1 0.59 75.33 0 # 5 V65 20 1 0.53 73.72 0 # 6 V588 19 -1 0.56 71.83 0 # 7 V471 19 -1 0.62 70.49 0 # 8 V133 19 -1 0.58 69.87 0 # 9 V127 19 -1 0.61 69.71 0 # ...... # [ reached getOption("max.print") -- omitted 297 rows ] # # Average tree size (number of nodes) summary: # Min. 1st Qu. Median Mean 3rd Qu. Max. # 257 285 299 299 313 339 # # Average Leaf nodes (number of terminal nodes) summary: # Min. 1st Qu. Median Mean 3rd Qu. Max. # 129 143 150 150 157 170 # # Leaf nodes size (number of observations per leaf node) summary: # Min. 1st Qu. Median Mean 3rd Qu. Max. # 1.00 4.00 9.00 13.75 18.00 221.00 # # Average tree depth : 8 # # Theoretical (balanced) tree depth : 11
상호작용 시각화
fit.imp.ruf <- importance(fit.ruf.1, Xtest = X1) # 1 - Global Variable Importance (30 most important based on information gain) : # Note: most predictive features are ordered by 'score' and plotted. Most discriminant ones # should also be taken into account by looking 'class' and 'class.frequency'. # # variables score class class.frequency percent percent.importance # 1 V104 27 -1 0.60 100.00 0 # 2 V424 23 -1 0.55 84.86 0 # 3 V60 22 -1 0.54 82.20 0 # 4 V148 20 -1 0.59 75.33 0 # 5 V65 20 1 0.53 73.72 0 # 6 V588 19 -1 0.56 71.83 0 # 7 V471 19 -1 0.62 70.49 0 # 8 V133 19 -1 0.58 69.87 0 # 9 V127 19 -1 0.61 69.71 0 # 10 V435 19 -1 0.55 69.12 0 # 11 V1 18 -1 0.55 68.96 0 # 12 V492 18 -1 0.60 67.90 0 # 13 V406 18 -1 0.52 67.84 0 # 14 V566 18 -1 0.60 67.77 0 # 15 V130 18 -1 0.71 66.96 0 # 16 V239 18 -1 0.58 66.88 0 # 17 V512 18 -1 0.61 66.70 0 # 18 V447 18 -1 0.62 65.47 0 # 19 V17 18 -1 0.59 65.31 0 # 20 V432 17 -1 0.51 65.01 0 # 21 V350 17 -1 0.55 64.48 0 # 22 V113 17 -1 0.64 64.39 0 # 23 V577 17 -1 0.64 64.09 0 # 24 V561 17 -1 0.55 63.88 0 # 25 V157 17 -1 0.56 63.85 0 # 26 V511 17 -1 0.55 63.76 0 # 27 V220 17 -1 0.51 63.67 0 # 28 V317 17 -1 0.62 63.30 0 # 29 V564 17 -1 0.67 63.04 0 # 30 V349 17 -1 0.58 62.95 0 # # # 2 - Local Variable importance # Variables interactions (10 most important variables at first (columns) and second (rows) order) : # For each variable (at each order), its interaction with others is computed. # # 예측에 참여한 모든 변수와 가장 많이 상호작용하는 3개 예측자 간에 상관계수 값이 출력된다.(빠짐) # # # Variable Importance based on interactions (10 most important) : # V57 V1 V16 V131 V34 V56 V35 V118 V130 V424 # 0.0269 0.0239 0.0178 0.0162 0.0132 0.0127 0.0127 0.0122 0.0113 0.0112 # # Variable importance over labels (10 most important variables conditionally to each label) : # Class -1 Class 1 # V57 0.11 0.00 # V131 0.04 0.00 # V118 0.04 0.00 # V16 0.04 0.01 # V130 0.04 0.00 # V46 0.00 0.04 # V572 0.00 0.03 # V1 0.02 0.03 # V33 0.01 0.03 # V424 0.01 0.03 # # # See ...$localVariableImportance$obsVariableImportance to get variable importance for each observation. # # Call clusterAnalysis() function to get a more compact and complementary analysis. # Type '?clusterAnalysis' for help. # # Call partialDependenceOverResponses() function to get partial dependence over responses # for each variable. Type '?partialDependenceOverResponses' for help.
plot(fit.imp.ruf, Xtest = X1) 을 실행하면 상호작용에 기반한 4개의 플롯과 1개의 박스 플롯이 보인다. 상위 4개의 예측자에 대해 프롬프트 입력하면 확인할 수 있다.
부분 의존도
예측자와 구분(Class)간 분포를 박스 플롯으로 확인할 수 있다. 도표를 이해하기 힘들어 생략한다.
트리 플롯
1개의 결정 트리에서 분할이 어떻게 선호되는지 비교하기를 원할 것이다. 다음에서 다른 중요한 기능의 하나는 쉽게 이해할 수 있는 규칙을 제공해야 한다. Random Uniform Forests에서 트리는 강한 임의성이다 (결정론적인(deterministic) CART와 달리), 하나의 트리 시각화는 해석에 적합하지 않다 그리고 다른 트리보다 더 좋은 트리는 없다.
tree_100 = getTree.randomUniformForest(fit.ruf.1,100) plotTree(tree_100, xlim = c(1,80), ylim = c(1,11))
Figure 4: forest 트리 |
4 ExtraTrees
Extremely Randomized Trees(ExtraTrees)
extraTrees (extremely randomized trees) 의 사용은 함수의 사용 측면에서 randomForest 패키지와 비슷하다. 중요한 차이는 각 노드에서 RandomForest는 특징을 위한 최적의 분할 임계점을 선택할 때, ExtraTrees는 (균등) 임의(randomly) 분할을 선택한다. 비슷한 점은 가장 큰 이득을 가지는 특징은 분할 임계점이 결정된 후에 선택함에 있다.
이 패키지를 구동하려면 rJava 패키지를 설치하고, Java도 설치해야 한다.
library(extraTrees) Y1 <- sc.imp.up.train$LABELS X1 <- sc.imp.up.train[, -ncol(sc.imp.up.train)] fit.et.1 <- extraTrees(x = X1, y = Y1) # attributes(fit.et.1) Y1.test <- sc.imp.up.test$LABELS X1.test <- sc.imp.up.test[, -ncol(sc.imp.up.test)] pred.et.1 <- predict(fit.et.1, X1.test) ## accuracy mean(Y1.test == pred.et.1) # [1] 1 table(OBSERV = Y1.test, PRED = pred.et.1) # PRED # OBSERV -1 1 # -1 438 0 # 1 0 438 ## class probabilities pred.et.prob.1 = predict(fit.et.1, X1.test, probability=TRUE) head(pred.et.prob.1) # 확율 분포를 히스토그램을 통해 확인해 본다, 불량(1)인 경우 확인. hist(pred.et.prob.1[,2])
댓글 없음:
댓글 쓰기