>RE::VISION CRM

R 데이터 분석

랜덤 포리스트 random forest 응용 [R 마이닝 ]

YONG_X 2013. 6. 4. 20:00

# 전용준 :: 리비젼컨설팅 :: 02-415-7650 :: revision.co.kr :: xyxonxyxon@empal.com

#==================================================


# 랜덤 포리스트 Random Forest 를 사용한 간단한 예측 모델링 적용 예제를

# kbo data set에 응용하는 사례 ( http://blog.daum.net/revisioncrm/201 도 참조 )

 

 

k3 <- read.table("kbo_batterbox.txt", header=TRUE, sep=",")

# 이전에 사용하던 데이터를 그대로 활용

 

# 참고 : [kbo data set ]  자료와 의미 ==>  http://blog.daum.net/revisioncrm/171 

 

# 임시로 target 변수로 사용할 항목을 하나 생성

# 장타율 rlong 값이 median에 해당하는 0.403 을 넘으면 장거리 포 타자라고 간주하기로 함

# 장거리와 단거리 두가지로만 구분된 binary 변수 생성

# instead of use if else if structure u can use variable creation straightforwardly

 

k3$isLH[ k3$rlong >0.403 ] <- 'LH' # designating long range hitter

k3$isLH[ k3$rlong <=0.403 ] <- 'sH'  # others are short range hitter

 

# 필요없는 일부 항목을  data frame 에서 제거.  

k3$rlong <- NULL
k3$palyer <- NULL # data frame을 만들면서 typo로 player를 palyer라고 명명했음

# 데이터 셋 수정이 필요한 대목. 여하간 사용하지는 않을 것임 (선수 이름)

 

# 48명 선수만 들어있는 데이터 이므로 20명은 테스트용으로 나머지 28명은 모델 학습용

test = k3[ c(1:20), ] 

train = k3[ c(21:48), ]

 

attach(train)

# 데이터 타입이 올바른지 잠시 확인

is.numeric(train$robase)

 

# 랜덤포리스트 패키지 호출
require(randomForest)

r = randomForest(isLH ~., data=train, importance=TRUE, do.trace=5) 

 

# 에러가 발생되면서  r 오브젝트는 생성되지 않음. 에러메시지는...
### error :: Can not handle categorical predictors with more than 32 categories.

# [검토] random forest를 사용하는 것이 아니라고 해도 tree 모델을 만들면서

# 다수의 카테고리로 구성된 변수를 사용하는 것은 통상적이지 않은 방법

# 그러나 여기서의 이슈는 의도하지도 반영하지도 않은 category 변수가 사용된다는 점

 

 

print(r) 

 

# 아래 중에서 뒤에 works 라는 표시가 붙은 부분은 정상 수행됨. 나머지는 같은 오류 발생

 

r = randomForest(isLH ~ games +atbat, data=train, importance=TRUE, do.trace=5,

ntree=5) 

r = randomForest(isLH ~ position , data=train, importance=TRUE )

r = randomForest(hr ~ games , data=train ) # works

r = randomForest(position ~ games , data=train ) # works

r = randomForest(position ~ games + team, data=train, importance=TRUE,

do.trace=5, ntree=20)   #  works

 

print(r) 



   [  info:: 데이터사이언티스트의 현재와 미래 컨퍼런스 2014년 10월 8일 ]

     http://www.itdaily.kr/news/articleView.html?idxno=55924



 

 

# the issue is in the target variable isLH which was created during
# the data prep session

# target 변수를 isLH 대신 hr 이나 position 같은 다른 변수로 바꿔 보면 정상 실행됨

# hr은 홈런수로 수치형 변수. position은 character 변수. 결국 문제는 targe variable인

# isLH에 있는 것으로 추측됨

 

# to check if NA/NaN/Inf related issue

# 에러메시지에 나오듯이 세가지중의 무언가로 값이 잘못 들어간 것이 있는지 확인중

# 콘솔 출력후 눈으로는 확인되지 않아서 with 함수를 사용해봄

with(train, train == Inf)
with(train, train == NA)
with(train, train == NaN)

 

# only isLH shows different value FALSE from the last command line
# all others show NA

# Inf와 NA에서는 특별한 점이 나타나지 않았으나 NaN 을 적용했을때 특이한 현상 나타남.

# isLH에 대한 결과값이 FALSE로 나타남 (다른 모든 값은 NA )

 

# 레벨의 수 즉 카테고리의 수를 확인하기 위해 unique 함수로 체크

# 동일한 듯 보여도 position은 레벨이 표시되지만 새로이 생성한 derived variable 인 isLH 는

# 레벨이 표시되지 않음. 생성된 변수에 대해서 더블쿼우트 쌍따옴표가 붙는 것이 문제를

# 일으켰을 가능성을 의심해봄

 

unique(position)
[1] cat cf  lf  2b  3b  1b  rf  ss 
Levels: 1b 2b 3b cat cf lf rf ss

 

 unique(isLH)
[1] "LH" "sH"

 

 

# 테스트를 위해서 처음 읽어들인 데이터에 isLH 변수 생성후 물리적인 파일로 export한 후

# 다시 import 하는 트릭을 시도해봄

 

k3 <- read.table("kbo_batterbox.txt", header=TRUE, sep=",")

k3$isLH[ k3$rlong >0.403 ] <- 'LH' # designating long range hitter

k3$isLH[ k3$rlong <=0.403 ] <- 'sH'  # others are short range hitter

write.table(k3, "kbo_batterbox01.txt", sep=",")

k3 <- read.table("kbo_batterbox01.txt", header=TRUE, sep=",")

 

k3$rlong <- NULL
k3$palyer <- NULL

 

test = k3[ c(1:20), ] 

train = k3[ c(21:48), ]

attach(train)

 

# require(randomForest)

 

# 이번에는 isLH에 FALSE 값이 또 나오는지 다시 체크 해봄. 모두 NA로 나옴

# 문제가 해결되었다는 이야기임

with(train, train == NaN)

 

 

# 당연히 모델 생성도 정상적으로 됨

# randomForest 에서는 input과 target 양쪽의 변수로 numeric, category 모두 사용 가능

 

r = randomForest(isLH ~ games + team, data=train, importance=TRUE, do.trace=5,

ntree=20)   #  works

 

 

r = randomForest(isLH ~ position + games + atbat + run + double + steal + SO +

rhit + robase, data=train, importance=TRUE, do.trace=5, ntree=100)   #  works

print(r) 

 

 

# 테스트 데이터를 가지고 예측값 생성

k3.predict = predict(r, test) 

k3.predict 

t = table(observed=test[,'isLH'], predict=k3.predict) 

prop.table(t, 1) 

 

 

# 정상적으로 실행되었음. 결국 여기서 문제를 일으킨 부분은 중간에 파생변수 생성한 부분.

# 코딩 과정에서 잘못한 것은 아니라 할 수 있음. R 자체의 문제라고 봐야 할 듯.

# 어쩔 수 없이 트릭을 사용해서 문제를 해결해야 하는 번거러움을 감수해야함

# 참고로 정상적으로 32개 카테고리를 넘는 카테고리 변수역시 사용할 수 없기 때문에

# 이 경우에는 매트릭스 같은 다른 데이터 타입으로 변환이 필요함

 

 

# compare the results from the cases when  ntree=20 and ntree=100

# 함수 사용에 특별한 복잡한 파라미터는 없고 그저 생성할 트리 갯수 정도만 지정하면되므로

# 트리 갯수에 서로 다른 옵션을 준 경우에 얼마나 예측의 정확성이 차이나는지 확인해봄

# 20을 주었을 경우와 100을 주었을 경우. 물론 컴퓨팅 리소스를 더 쓰는 것은 당연하겠지만

# 정확도는 상당히 증가함을 confusion matrix를 비교하여 볼 수 있음.

# 왜 random forest를 많이들 사용하는지를 간단하게 보여줌

# 다만 다수의 트리의 ensemble 이다 보니 어느 변수가 더 중요했는지에 대한 직관적인 정보를

# 확인하기 위해서는 별도의 작업이 필요

 

# in case of ntree=20

              predict
observed        LH        sH
      LH     0.5000000 0.5000000
      sH     0.3333333 0.6666667

 

# in case of ntree=100

              predict
observed        LH        sH
      LH   0.6428571 0.3571429
      sH   0.3333333 0.6666667

 

 

# 모델 평가를 위한 플롯 ----------------------------------

# [참고]  http://stats.stackexchange.com/questions/2344/best-way-to-present-a-random-forest-in-a-publication 


# 트리 수의 증가에 따른 오차율 변화 플롯
plot(r, log="y")

 

# 변수 중요도를 나타내는 플롯

varImpPlot(r)

 

# 모델에 대한 사후 분석 결과를 보면

# 1. 트리의 수를 50 이상으로 설정한다면 이 문제에서 오차가 더 줄어들지 않는다

# 결국 트리의 수는 50으로 설정한다면 충분하다

# 2. 거포 즉, 장타율이 높은 타자인가 (isLH)를 구별하는데는 타율(rhit)과 2루타(double), 출루율(robase)이 중요한 변수임

# 3. 의외로 장타율 계산에 직접 사용되지는 않는 도루의 수와 포지션도 영향력이 있는 변수임

 

# [Tip] 단순히 모델을 만들고 예측치를 계산하는 것에 멈춘다면  데이터 분석의 가치를

# 100% 활용할 수 없음. 사후 분석이나 결과값에 대한 Profiling을 통해서

# Data와 문제 자체에 대한 background knowledge와 insight 를 얻어내는 것이 필수 

 

 # 파악된 중요 변수에 대한 목표 변수와의 관계 플롯 [ -> 추가적 EDA 탐색적 분석]
require(ggplot2)            # ggplot2 패키지의 플롯을 사용해서 간단한 탐색위한 시각화 시도

qplot( rhit, isLH, data = k3, color = position, size = robase )

# Y축에 장타율이 높은가하는 binary class 변수( 예측 모델링의 목표 변수)를 두고

# 주요변수인 타율, 출루율, 그리고 의외였던 포지션 (색상으로) 간의 관계를

# 하나의 플롯에서 확인

 

# 플롯이 보여주는 내용은 [해석] 타율이 장거리포인 타자들이 전반적으로 높다는 점

# 출루율 역시 장거리포들이 더 높다는 점... 어쩌면 볼넷을 얻기 좋아서?

# 투수들이 피하고자 한다면 그럴 수도 있을 듯

# 포지션의 경우 9개 카테고리가 되므로 48개 뿐인 데이터로는 패턴이 나타난다해도

# 신뢰하기는 곤란할 것 같다는 판단이 됨

 

 

# 질문사항은 ==>

# 댓글에 남기거나, xyxonxyxon@empas.com 으로도 연락 가능