Random Forest without ‘caret’

caret 패키지 설치가 안되는 곳에서 ML 분석을 하려면, 해당 패키지를 직접 설치하고 직접 분석 코드를 작성해야 한다. caret이 설치가 안되는 이유는 패키지 설치에 필요한 gcc 등의 컴파일러와 R 버젼의 문제이다. 하아..

어쨋든, 쉬운 random forest 부터 해결해보자. 직접 코딩해 주어야 하는 것은 다음과 같다. caret을 이용할 경우에도 hyperparameter tuning은 직접 해줘야 하기는 하지만 말이다.

  • mtry나 ntree 튜닝
  • 최적의 mtry와 ntree 값
  • training과 validation 셋 분할
  • cross validation 과정과 결과 취합

공식 문서를 참고하면 다음과 같이 설정해 주면 될 것이다.

우선 training과 validation 셋 분할

ind <- sample(2, nrow(iris), replace = TRUE, prob=c(0.8, 0.2))
iris.rf <- randomForest(Species ~ ., data=iris[ind == 1,])
iris.pred <- predict(iris.rf, iris[ind == 2,])

그리고 결과 확인.

> table(observed = iris[ind==2, "Species"], predicted = iris.pred)
            predicted
observed     setosa versicolor virginica
  setosa         10          0         0
  versicolor      0          6         1
  virginica       0          1        15

Accuracy는 직접 구해야 한다. 편하게 다음과 같이 해본다.

> a = table(observed = iris[ind==2, "Species"], predicted = iris.pred)
> suma = 0 ;for (i in seq(nrow(a))){suma = suma + a[i, i]}
> suma/sum(a)
[1] 0.9393939

파라미터 튜닝은 다음과 같이 하는 것 같다. Ntree와 Mtry의 값을 변수로 입력하고 결과를 반복한 다음 최적의 결과가 나오는 것을 선택한다. OOB가 낮은 것을 선택한다고 한다.

> a = randomForest(Species ~. , data=iris, ntree=i, mtry=j, na.action = na.omit)
## a$err.rate의 마지막 열의 첫 번째 값이다. 따라서,
> tail(a, 1)[1]
[1] 0.04666667

Kappa 상관 계수도 구해보자. 참값과 예측값이 있으니까 관찰자는 2개로 보면 된다. 그러면 그룹을 어떻게 나누느냐에 따라서 계산을 해주면 된다. 2×2 형식은 unconquered (daum.net), 3×3 형식은 hckappa (unl.edu)를 참고했다. 코딩하기에 편한 쪽은 오히려 3×3에서의 설명이다.

Kappa를 구하기 위해서 필요한 것은 N, sum(a), sum(ef) 이다. N과 sum(a)는 쉽게 구할 수 있으니 sum(ef)를 보자. 2×2 쪽 블로그 설명에 의하면 관찰자가 우연히 그것으로 판단할 확률을 구하는 것이라고 보면 된다. 그래서 expected frequency의 약자를 이용했다. [1,1]이 9가 왜 5.42로 계산이 되는지만 알면 된다.

(9+3+1)*(9+4+2)/36 = 5.42

배울 수록 느는 것은 요령이라서, R의 함수로 만들어 본다. 입력값은 NxN 테이블 형식이다.

kappa = function(table){
  total_number = sum(table)
  agree_number = 0; expected_number = 0
  for (X in seq(nrow(table))){
    agree_number = agree_number + table[X, X]
    expected_number = expected_number + 
                      (sum(table[X, ])*sum(table[, X]))/total_number
  }
  print((agree_number-expected_number)/(total_number-expected_number))
}

이와 같은 방법으로 앞서 예시로 든 자료의 Kappa를 측정하면 0.935로 계산된다.