Andy Liaw and Matthew Wiener
소개(Introduction)
최근에 "앙상블 학습(ensemble learning)"에 많은 관심을 가진다 - 많은 분류기를 생성하고 그들의 결과를 모으는 방법. 2개의 유명한 방법은 분류 트리에서 boosting (see, e.g., Shapire et al., 1998) 그리고 bagging Breiman (1996) 이다. 부스팅에서, 성공적인 트리는 앞선 예측자로 옳바르지 않게 예측된 포인트에 여분의 가중치를 준다. 결국은, 가중치 선택은 예측을 위해서 수행한다. 배깅에서, 성공적인 트리는 앞의 트리에 의존하지 않는다 - 각각은 데이터 셋의 부트스트램 표본(bootstrap sample)을 사용하여 구축한다. 결국, 단순한 중요도 선택은 예측을 위해서이다.
브레이만(Breiman (2001))은 랜덤 포레스트를 제안했다, 배깅에 추가적인 랜덤 층(additional layer of randomness)을 더함. 데이터의 다른 부트스트랩 표본을 사용하는 각 트리를 구측하는 것을 더하여, 랜덤 포레스트는 분류 또는 회귀 트리가 생성되는 방법을 변경한다. 표준 트리에서, 각 노드는 모든 변수에서 가장 최고의 분할을 사용하여 분할한다. 랜덤 포레스트에서는, 각 노드는 그 노드에서 무작위로 선택된 예측자의 하위 집합에서 가장 좋은 것을 사용하여 분할한다. 이것은 많은 다른 분류기와 비교하여 매우 잘 수행하는 무엇인가 반직관적인 전략(counterintuitive strategy)으로 돌린다, 판별 분석(discriminant analysis), 서포트 멕터 머신(support vector machines) 그리고 신경망(neural networks)을 포함, 그리고 과적합에 대해 강건하다(Breiman, 2001). 게다가, 그것은 단지 2개의 변수만 가진다는 의미에서 매우 사용자-친숙하다 ( 각 노드에서 무작위 하위집합에 변수의 수 그리고 포레스트에서 트리의 수), 그리고 그들의 값에 매우 의미있지 않다.
randomForest 패키지는 Breiman and Cutler ( http://www.stat.berkeley.edu/users/breiman/에서 이용 가능)에 의해 포트란 프로그램으로 R 인터페이스를 제공한다. 이 문서는 R 함수의 사용 그리고 특징의 간략한 소개를 제공한다.
The algorithm
랜덤 포레스트 알고리즘(분류 및 회귀 둘 모두)은 아래와 같다:
- 원본 데이터에서 ntree개의 부트스트랩 표본을 생성해라
- 각 부트스트랩 표본에서, 가지치기 없이(unpruned) 분류 또는 회귀 트리를 성장시켜라, 다음 수정 사항 적용: 각 노드에서, 모든 예측자에서 가장 최고의 분할을 선택하지 않고, 예측자의 mtry로 무작위 표본을 만들어라 그리고 이런 변수들에서 가장 최고의 분할을 선택하라. (배깅은 mtry = p 일 때 취한 랜덤 포레스트의 특별한 경우로 생각할 수 있다, p는 예측자의 수)
- ntree의 예측자를 수집함으로써 새로운 데이터를 예측해라 (i.e., 분류를 위한 중요도 선택, 회귀를 위한 평균).
에러 비율의 추정을 획들할 수 있다, 훈련 집합을 기반으로, 아래에 의해서:
- 각 부트스트랩 반복에서, 부트스트랩 표본을 가지고 성장한 트리를 사용하여 부트스트랩 표본에 없는 데이터(브레이만은 "out-of-bag”, 또는 OOB 데이터로 부름)를 예측해라.
- OOB 예측을 수집하라. (평균에서, 각 데이터 포인트는 매 회에 out-of-bag 약 36%가 될 것이다, 그래서 이런 예측을 수집한다.) 에러 비율을 계산해라, 그리고 그것을 에러 비의 OOB 추정 이라 부른다.
우리의 실험에서 에러 비의 OOB 추정은 상당히 정확하다, 충분한 트리가 자라게 주어지면 (그렇지 않으면 OOB 추정은 상방향 편향(bias upward)될 수 있다; Bylander (2002) 보라).
랜덤 포레스트의 추가 정보 (Extra information from Random Forests)
randomForest 패키지는 옵션으로 2개의 추가적인 일부 정보를 제공한다: 예측자 변수의 중요도 측정, 그리고 데이터의 내부 구조의 측정(데이터 포인트와 다른 하나와의 차이의 근접도).
- Variable importance 이것은 일반적으로 정의하기 어려운 개념이다, 왜냐하면 변수의 중요도는 그것의 다른 변수와 (아마도 복잡한)상호작용 때문일 것이다. 랜덤 포레스트 알고리즘은 모든 다른 변수는 변경 없이 있는 동안 변수에서 (OOB) 데이터가 가지쳐질 때 얼마나 많은 예측 에러가 증가되는지 보는 것으로 변수의 중요도를 추정한다. 필요한 계산은 랜덤 포레스트가 생성되는 트리에서 트리 밖에 놓인다. ( 분류 코드에서 구현된 4개의 다른 변수 중요도 측정이 있다. 그들의 정의를 Breiman (2002)이 독자에게 언급했다)
- 근접 측정(proximity measure) randomForest로 생성된 근접 매트릭의 (i, j) 요소는 요소 i 와 j가 같은 종료 노드에 떨어지는 일부 트리이다. 직관으로 “비슷한(similar)” 관측은 비슷하지 않은 것 보다 같은 종료 노드에 더 자주 있을 것임을 안다. 근접 측정은 데이터에서 구조를 구별하기 위해 사용할 수 있다(see Breiman, 2002) 또는 랜덤 포레스트의 비감독 학습을 위해서(아래 참조).
R에서 사용 (Usage in R)
랜덤 포레스트의 사용자 인터페이스는 nnet() (in the nnet package) 그리고 svm() (in the e1071 package) 처럼 다른 분류 함수를 가지고 구성되었다. (우리는 실제로 이런 2개의 함수에서 인터페이스 코드의 일부를 차용했다) 식 인터페이스가 있다. 그리고 예측자는 x 인수로 메트릭 또는 데이터 프레임으로 지정되어야 한다, y 인수로 벡터로 응답을 가짐. 만약 응답이 펙터(factor)이면, randomForest는 분류를 수행한다; 만약 응답이 연속이면(이것은, 펙터가 아님), randomForest는 회귀를 수행한다. 만약 응답이 지정되지 않으면, randomForest는 비감독 학습을 수행한다(아래를 보라). 현재 randomForest는 순서가 있는 범주형 응답(ordinal categorical responses)을 처리하지 않는다. 범주형 예측자 변수는 또한 팩터로 지정되야 함에 주목하라(그렇지 않으면 그들은 연속으로 틀리게 저리될 것이다)
randomForest 함수는 클래스 "randomForest"의 객체를 반환한다. 객체의 구성 요소의 상세는 온라인 문서에서 제공된다. 클래스를 위해 제공되는 메서드는 predict 와 print를 포함한다.
분류 예제 (A classification example)
포렌식 유리 데이터 셋(Forensic Glass data set)이 다양한 분류 알고리즘을 설명하기 위해 MASS4 (Venables and Ripley, 2002)의 12절에 사용되었다. 우리는 랜덤 포레스트 어떻게 작업하는지 보여주기 위해 그것을 여기서 사용한다.
> library(randomForest) > library(MASS) > data(fgl) > set.seed(17) > fgl.rf <- randomForest(type ~ ., data = fgl, + mtry = 2, importance = TRUE, + do.trace = 100) 100: OOB error rate=20.56% 200: OOB error rate=21.03% 300: OOB error rate=19.63% 400: OOB error rate=19.63% 500: OOB error rate=19.16% > print(fgl.rf) Call: randomForest.formula(formula = type ~ ., data = fgl, mtry = 2, importance = TRUE, do.trace = 100) Type of random forest: classification Number of trees: 500 No. of variables tried at each split: 2 OOB estimate of error rate: 19.16% Confusion matrix: WinF WinNF Veh Con Tabl Head class.error WinF 63 6 1 0 0 0 0.1000000 WinNF 9 62 1 2 2 0 0.1842105 Veh 7 4 6 0 0 0 0.6470588 Con 0 2 0 10 0 1 0.2307692 Tabl 0 2 0 0 7 0 0.2222222 Head 1 2 0 1 0 25 0.1379310
우리는 10배 교차-검증의 10회 반복으로 서포트 벡터 머신(support vector machines)을 가지고 랜덤 포레스트를 비교할 수 있다, ipred 패키지에서 errorest 함수를 사용하여:
> library(ipred) > set.seed(131) > error.RF <- numeric(10) > for(i in 1:10) error.RF[i] <- + errorest(type ~ ., data = fgl, + model = randomForest, mtry = 2)$error > summary(error.RF) Min. 1st Qu. Median Mean 3rd Qu. Max. 0.1869 0.1974 0.2009 0.2009 0.2044 0.2103 > library(e1071) > set.seed(563) > error.SVM <- numeric(10) > for (i in 1:10) error.SVM[i] <- + errorest(type ~ ., data = fgl, + model = svm, cost = 10, gamma = 1.5)$error > summary(error.SVM) Min. 1st Qu. Median Mean 3rd Qu. Max. 0.2430 0.2453 0.2523 0.2561 0.2664 0.2710
우리는 랜덤 포레스트가 SVM에 비해 상당히 알맞게 비교된다는 것을 확인한다.
우리는 랜덤 포레스트로 만들어진 변수 중요도 측정이 모델 축소를 위해 유용하다는 것을 찾아냈다 (e.g., 더 단순하게 생성하기 위해 "중요도(important)" 변수 사용, 더 읽기 쉽게 해석 가능한 모델). Figure 1은 Forensic Glass data set의 변수 중요도를 보여준다, 위에서 생성된 fgl.rf객체를 기반으로, 개략적으로, 그것은 다음으로 생성되었다:
> par(mfrow = c(2, 2)) > for (i in 1:4) + plot(sort(fgl.rf$importance[,i], dec = TRUE), + type = "h", main = paste("Measure", i))
Figure 1: 포렌식 글래스(유리) 데이터에서 변수 중요도 |
우리는 측정 1에서 변수들을 가장 분명하게 구별한다. 만약 우리가 모델에서 Na, K, 그리고 Fe를 제외하여 다시 랜덤 포레스트를 실행하면, 에러 비율은 20% 아래에 있게 된다.
더 많은 변수가 있을 때 더 큰 극적인 효과를 얻을 수 있다. 수천 개의 예측자를 가지는 데이터 셋에서, 우리는 단지 예측자의 12개를 선택하기 위해 변수 중요도 측정을 사용했다, 그리고 우리는 필요한 같은 예측 정밀도를 얻을 수 있다. 우리가 생성한 1,000개의 변수를 가지는 시뮬레이시트된 데이터 셋에서, 랜덤 포레트스, 기본 mtry를 가짐, 우리는 단지 2개의 주용한 변수를 분명하게 구별할 수 있었다 그리고 다른 998개의 잡음 변수를 무시했다.
회귀 예 (A regression example)
우리는 랜던 포레스트의 회귀 예제로 보스턴 주택 데이터(Boston Housing data (MASS 패키지에서 사용 가능))를 사용했다. 분류와 회귀 랜덤 포레스트 사이에 몇가지 차이를 주목하라.
- 기본 mtry는 p/3이다, 분류에서 p1/2와 대조적, p는 예측자 수이다.
- 기본 nodesize는 5이다, 분류에서 1과 대조적. (트리 생성 알고리즘에서, nodesize 관측 보다 작게 가지는 노드는 분할되지 않는다.)
- 단지 한 번 만 변수 중요도 측정한다, 4번 대신에.
> data(Boston) > set.seed(1341) > BH.rf <- randomForest(medv ~ ., Boston) > print(BH.rf) Call: randomForest.formula(formula = medv ~ ., data = Boston) Type of random forest: regression Number of trees: 500 No. of variables tried at each split: 4 Mean of squared residuals: 10.64615 % Var explained: 87.39
"평균 제곱 잔차(mean of squared residuals)"은 다음으로 계산된다:
^
σiOOB는 i번째 관측에서 OOB 예측의 평균인 경우. “설명 분산율 (percent variance explained)”은 다음으로 계산된다.
^
σy2는 제수로 n을 가지고 계산된 경우 (n - 1 이기 보단).
우리는 실제 데이터를 가지고 비교할 수 있다, 뿐만 아니라 선형 모델에서 적합된 모델로 비교, Figure 2에 보여준다.
Figure 2: 보스턴 주택 데이터의 랜덤 포레스트와 실제 응답을 가지는 선형 모데의 예측 비교. |
비감독 학습 예 (An unsupervised learning example)
랜덤 포레스트는 분류 또는 회귀 트리의 모음이기 때문에, 그것은 그들이 어떻게 비감독 학습에 사용될 수 있는지 즉각적으로 분명하게 오지 않는다. "트릭"은 데이터 "class 1" 데이터를 호출해야 한다 그리고 "class 2" 합성 데이터를 구축, 그러면 랜덤 포레스트를 가지고 결합된 데이터 분류를 시도할 수 있다. "class 2" 데이터를 시뮬레이트하는 2가지 방법이 있다:
- "class 2" 데이터는 변수의 한계 분표(the marginal distributions)의 생성으로 표본 추출된다( 별도의 각 변수의 독립적인 부트스트랩으로).
- "class 2" 데이터는 데이터를 함유하는 hypercube(10개에서 1,000개의 프로세서를 병렬로 동작시키는 컴퓨터 아키텍처)에서 단변량으로 표본 추출된다 (각 변수의 범위 안에서 단변량으로 표본 추출하여)
발상은 다른 하나와 비슷한 실제 데이터 포인트는 트리의 같은 종료 노드에서 자주 끝날 것이라는 것이다 - 정확히 randomForest의 옵션 proximity=TRUE를 사용하여 반환될 수 있는 근접 메트릭(proximity matrix)으로 측정된 것. 그러므로 근접 메트릭은 유사도 측정을 구할 수 있고, 그리고 이 유사도를 사용하는 군집(clustering) 또는 다-차원 척도(multi-dimensional scaling)가 육안 탐사를 위한 그룹으로 원본 데이터 포인트를 나누어 사용할 수 있다.
우리는 randomForest의 비감독 학습 모드를 보여주기 위해 MASS4에 있는 crabs 데이터를 사용한다. 우리는 MASS4 의 페이지 308–309에서 제안된 방법으로 척도 변환했다 (또한 ‘$R HOME/library/MASS/scripts/ch11.R’에서 라인 28–29 그리고 63–68에 있다), 아래의 dslcrab 데이터 프레임 결과. 그러면 randomForest가 근접 메트릭을 얻도록 실행해라. 우리는 그러면 1-근사를 보여주기 위해 (mva 패키지에 있는) cmdscale()를 사용할 수 있다, Figure 3에 보이는 것과 같음. 그림에서 보이는 것처럼, 2개의 색 형상은 상당히 잘 분리되었다.
> library(mva) > set.seed(131) > crabs.prox <- randomForest(dslcrabs, + ntree = 1000, proximity = TRUE)$proximity > crabs.mds <- cmdscale(1 - crabs.prox) > plot(crabs.mds, col = c("blue", "orange")[codes(crabs$sp)], + pch = c(1, 16)[codes(crabs$sex)], xlab="", ylab="")
Figure 3: crabs 데이터의 근접 메트릭의 메트릭 다-차원 척도(multi-dimensional scaling) 표현. |
또한 randomForest에 outscale 옵션이 있다, 이런 것, 만약 TRUE로 설정하면, 데이터 셋의 각 관측에서 "이상점(outlyingness)" 측정을 반환한다. j번째 관측에서 이상점 측정은 같은 분류에서(in the same class) 관측과 모든 다른 관측 간에 제곱-근접도-합(sum of squared proximities)의 역수(reciprocal)로 계산된다. randomForest를 위한 도움말 페이지의 예제 장에서 Iris 데이터에서 이상점 측정을 보여준다 (그들을 비표기로 추정)
연습 사용을 위한 몇 가지 주의 사항 (Some notes for practical use)
- 좋은 성능을 위한 필요한 트리의 수는 예측자의 수에 따라 커진다. 얼마나 많은 트리가 필요한지 결정하는 최고의 방법은 포레스트의 하위집합으로 만들어진 예측에서 포레스트로 만들어진 예측을 비교해야 한다. 하위 집합이 전체 모델만큼 잘 동작할 때, 당신은 충분한 트리를 가졌다.
- mtry를 선택으로, Prof. Breiman은 기본값, 기본값의 반, 그리고 기본값의 2배의 시도를 제안했다, 그리고 최고를 뽑아라. 우리의 실험에서, 결과는 일반적으로 극적으로 변경되지 않았다. mtry = 1 조차 어떤 데이터에서 매우 좋은 성능을 주었다! 만약 하나가 매우 큰 수를 가지면서 그러나 단지 매우 작은 중요도가 기대되면, 큰 mtry의 사용은 아마도 더 큰 성능을 줄 것이다.
- 많은 트리는 변수 중요도와 근접도의 안정적인 추정을 얻기 위해 필요하다. 어쨌든, 우리의 실험은 변수 중요도 측정이 실행마다 변화하더라도 중요도 순위는 상당히 안정적이다.
- 분류 빈도가 극단적으로 불균형한 경우의 분류 문제에서(e.g., 99%의 분류 1 그리고 1%의 분류 2), 그것은 예측 규칙을 중요도 선택 보다는 다른 것으로 변경하기 위해 필요할 것이다. 예를 들어, 99%의 분류 1 그리고 1%의 분류 2를 가지는 2-분류 문제에서, 하나는 분류 2처럼 큰 분류 2의 확률을 가지고 관측의 1%를 예측하기를 원할 것이다. 그리고 검증 데이터의 예측을 위한 임계점으로 가장 작은 이러한 확률을 사용한다 (i.e., 예측 메서드에 type=’prob’인수 그리고 출력의 2번째 열의 임계점을 사용해라. 우리는 이것으로 ROC 곡선을 얻기 위해 반복적으로 행했다. Prof. Breiman은 랜덤 포레스트의 다음 버전에서 비슷한 향상(방법)으로 작업했다.
- 기본으로, 전체 포레스트는 randomForest 객체의 forest 요소에 포함되었다. 그것은 큰 데이터 셋 또는 많은 트리의 수에서 상당히 많은 메모리를 사용할 수 있다. 만약 검증 데이터 예측이 필요하지 않다면, randomForest를 실행할 때 인수 keep.forest=FALSE로 설정해라. 이 방법은, 언제든지 단지 하나의 트리가 메로리에 보관된다, 그리고 그러므로 많은 량의 메모리를(그리고 잠재적으로 실행 시간) 절약할 수 있다.
- 알고리즘이 "황당 병렬(embarrassingly parallel)" 분류로 빠져들기 때문에, 하나는 다른 머신에서 랜덤 포레스트를 몇번 실행해야 한다 그리고 그러면 최종 결과를 얻기 위해 votes 요소를 수집해라.
감사의 말 (Acknowledgment)
We would like to express our sincere gratitute to Prof. Breiman for making the Fortran code available, and answering many of our questions. We also thank the reviewer for very helpful comments, and pointing out the reference Bylander (2002).
댓글 없음:
댓글 쓰기