randomForest :: getTree ()에서 실제로 샘플 트리를 그리는 방법은 무엇입니까? [닫은]


62

누구나 실제로 몇 가지 샘플 트리플롯하는 방법에 대한 라이브러리 또는 코드 제안이 있습니다.

getTree(rfobj, k, labelVar=TRUE)

(예를 들어, 당신 이이 작업을 수행하지 않아야한다는 것을 알고 있습니다. RF는 블랙 박스 등입니다.) 시각적으로 나무가 온전한 지 확인하여 변수가 반 직관적으로 작동하는지 확인하고, 조정 / 조합 / 분산 / 변환, 확인이 필요합니다. 인코딩 된 요소가 얼마나 잘 작동하는지 등)


적절한 답변이없는 이전 질문 :

실제로 샘플 트리플로팅하고 싶습니다 . 그러니 이미 그것에 대해 논쟁하지 마십시오. varImpPlot(Variable Importance Plot) 또는 partialPlot/ MDSPlot또는 이러한 다른 플롯 에 대해 묻지 않고 있지만 이미 그 플롯이 있지만 샘플 트리를 보는 대신 사용할 수는 없습니다. 예 getTree(...,labelVar=TRUE). 의 출력을 육안으로 검사 할 수 있습니다 .

( plot.rf.tree()기여금은 잘받는 것으로 생각 됩니다.)


6
나는 당신이 누군가에게 당신을 돕기 위해 자원 봉사를 요청하는 경우에 선제 적으로 논쟁 할 필요가 없다고 생각합니다. 잘 맞지 않습니다. CV에는 에티켓 정책이 있습니다 . FAQ 를 읽어보십시오 .
gung-모니 티 복원

9
@gung :이 주제에 대한 모든 이전 질문은 샘플 트리를 그리는 것이 필요하지 않으며 실제로 이단 적이라고 주장하는 사람들로 부패했습니다. 내가 준 인용을 읽으십시오. rf 트리를 코드로 작성하는 방법에 대한 스케치를 찾고 있습니다.
smci

3
나는 아이디어의 전제에 대해 의문을 제기하는 의견과 함께 사용자가 도움이되고 질문을 해결하려고하는 답변을 봅니다. 어떤 사람들은 고백하지 않은 것에 동의하지 않을 것입니다.
gung-모니 티 복원

4
1 년 넘게 누군가가 나무를 그린 적이있는 곳에서 답이 0 인 것을 봅니다. 특정 질문에 대한 특정 답변을 찾고 있습니다.
smci

1
cforest( 파티 패키지로) 빌드 된 단일 트리를 플로팅 할 수 있습니다 . 그렇지 않으면, data.frame반환 된 randomForest::getTreetree-like 객체 로 변환해야 합니다.
chl

답변:


44

첫 번째 (가장 쉬운) 솔루션 : Andy Liaw 's에서 구현 한 것처럼 고전 RF를 고수하지 않으 려면 원래 RF 알고리즘 의 다른 구현 (조건부 트리 및 집계 체계 사용) 을 제공하는 파티 패키지를 randomForest사용해 볼 수 있습니다 단위 중량 평균). 그런 다음이 R-help post 에보고 된대로 트리 목록의 단일 멤버를 플롯 할 수 있습니다. 내가 알 수있는 한 원활하게 실행되는 것 같습니다. 아래는에 의해 생성 된 하나의 트리의 도표입니다 .cforest(Species ~ ., data=iris, controls=cforest_control(mtry=2, mincriterion=0))

여기에 이미지 설명을 입력하십시오

두 번째 (거의 쉽게) 솔루션 : R 트리 기반 기술의 대부분 ( tree, rpart, TWIX, 등)를 제공하는 tree하나의 트리를 세우고 / 인쇄 -like 구조를. 아이디어는 randomForest::getTree통계적 관점에서 무의미한 경우에도 출력 을 그러한 R 객체 로 변환하는 것입니다. 기본적으로 tree아래와 같이 객체 에서 트리 구조에 쉽게 액세스 할 수 있습니다. 회귀를 분류 대 - - 후자의 경우에이의 마지막 컬럼으로 클래스 고유의 확률을 추가 할 것입니다 곳이 약간 작업의 종류의 따라 다를 수 있음을 유의하시기 바랍니다 obj$frame(A이다 data.frame).

> library(tree)
> tr <- tree(Species ~ ., data=iris)
> tr
node), split, n, deviance, yval, (yprob)
      * denotes terminal node

 1) root 150 329.600 setosa ( 0.33333 0.33333 0.33333 )  
   2) Petal.Length < 2.45 50   0.000 setosa ( 1.00000 0.00000 0.00000 ) *
   3) Petal.Length > 2.45 100 138.600 versicolor ( 0.00000 0.50000 0.50000 )  
     6) Petal.Width < 1.75 54  33.320 versicolor ( 0.00000 0.90741 0.09259 )  
      12) Petal.Length < 4.95 48   9.721 versicolor ( 0.00000 0.97917 0.02083 )  
        24) Sepal.Length < 5.15 5   5.004 versicolor ( 0.00000 0.80000 0.20000 ) *
        25) Sepal.Length > 5.15 43   0.000 versicolor ( 0.00000 1.00000 0.00000 ) *
      13) Petal.Length > 4.95 6   7.638 virginica ( 0.00000 0.33333 0.66667 ) *
     7) Petal.Width > 1.75 46   9.635 virginica ( 0.00000 0.02174 0.97826 )  
      14) Petal.Length < 4.95 6   5.407 virginica ( 0.00000 0.16667 0.83333 ) *
      15) Petal.Length > 4.95 40   0.000 virginica ( 0.00000 0.00000 1.00000 ) *
> tr$frame
            var   n        dev       yval splits.cutleft splits.cutright yprob.setosa yprob.versicolor yprob.virginica
1  Petal.Length 150 329.583687     setosa          <2.45           >2.45   0.33333333       0.33333333      0.33333333
2        <leaf>  50   0.000000     setosa                                  1.00000000       0.00000000      0.00000000
3   Petal.Width 100 138.629436 versicolor          <1.75           >1.75   0.00000000       0.50000000      0.50000000
6  Petal.Length  54  33.317509 versicolor          <4.95           >4.95   0.00000000       0.90740741      0.09259259
12 Sepal.Length  48   9.721422 versicolor          <5.15           >5.15   0.00000000       0.97916667      0.02083333
24       <leaf>   5   5.004024 versicolor                                  0.00000000       0.80000000      0.20000000
25       <leaf>  43   0.000000 versicolor                                  0.00000000       1.00000000      0.00000000
13       <leaf>   6   7.638170  virginica                                  0.00000000       0.33333333      0.66666667
7  Petal.Length  46   9.635384  virginica          <4.95           >4.95   0.00000000       0.02173913      0.97826087
14       <leaf>   6   5.406735  virginica                                  0.00000000       0.16666667      0.83333333
15       <leaf>  40   0.000000  virginica                                  0.00000000       0.00000000      1.00000000

그런 다음 해당 객체를 예쁘게 인쇄하고 플로팅하는 방법이 있습니다. 주요 기능은 (그래픽 표시) 및 (계산 노드 좌표)에 의존 하는 일반적인 tree:::plot.tree방법입니다 (트리플 :을 R로 직접 볼 수 있도록 트리플 을 넣습니다 ). 이 함수들은 트리 의 표현을 기대합니다 . 다른 미묘한 문제 : (1) 기본 플로팅 방법 의 논점 은 노드 사이의 수직 거리를 관리하는 데 도움이됩니다 ( 이탈에 비례 한다는 것을 의미하며 고정됨을 의미합니다). (2) 노드와 스플릿에 텍스트 레이블을 추가 하기위한 호출 로 보완해야합니다 .이 경우에는을 (를) 살펴 봐야 합니다.tree:::treepltree:::treecoobj$frametype = c("proportional", "uniform")tree:::plot.treeproportionaluniformplot(tr)text(tr)tree:::text.tree

getTree에서 방법 randomForest수익률 온라인 도움말에 설명되어 다른 구조. 터미널 노드와 함께 status코드 (-1)로 표시되는 일반적인 출력이 아래에 나와 있습니다 . (역시, 출력 만 온, 작업의 종류에 따라 다르고, status그리고 prediction열).

> library(randomForest)
> rf <- randomForest(Species ~ ., data=iris)
> getTree(rf, 1, labelVar=TRUE)
   left daughter right daughter    split var split point status prediction
1              2              3 Petal.Length        4.75      1       <NA>
2              4              5 Sepal.Length        5.45      1       <NA>
3              6              7  Sepal.Width        3.15      1       <NA>
4              8              9  Petal.Width        0.80      1       <NA>
5             10             11  Sepal.Width        3.60      1       <NA>
6              0              0         <NA>        0.00     -1  virginica
7             12             13  Petal.Width        1.90      1       <NA>
8              0              0         <NA>        0.00     -1     setosa
9             14             15  Petal.Width        1.55      1       <NA>
10             0              0         <NA>        0.00     -1 versicolor
11             0              0         <NA>        0.00     -1     setosa
12            16             17 Petal.Length        5.40      1       <NA>
13             0              0         <NA>        0.00     -1  virginica
14             0              0         <NA>        0.00     -1 versicolor
15             0              0         <NA>        0.00     -1  virginica
16             0              0         <NA>        0.00     -1 versicolor
17             0              0         <NA>        0.00     -1  virginica

당신은에 의해 생성 된 하나에 위의 표를 변환 관리 할 수 있다면 tree, 당신은 아마 사용자 정의 할 수 있습니다 tree:::treepl, tree:::treeco그리고 tree:::text.tree나는이 방법의 예를하지 않아도 불구하고, 사용자의 요구에 맞게. 특히 RF에서 의미가없는 이탈도, 클래스 확률 등을 제거하고 싶을 것입니다. 노드 좌표를 설정하고 값을 분할하기 만하면됩니다. 당신은 fixInNamespace()그것을 사용할 수 있지만, 솔직히 말해서 이것이 올바른 길인지 확신 할 수 없습니다.

셋째 (그리고 확실히 영리한) 해결책 :as.tree 위의 모든 "패치"를 완화시키는 진정한 도우미 기능을 작성하십시오 . 그런 다음 R의 플로팅 방법을 사용하거나 Klimt (R에서 직접)를 사용하여 개별 트리를 표시 할 수 있습니다.


40

나는 4 년 늦었지만 실제로 randomForest패키지 를 고수하고 (그리고 그렇게해야 할 몇 가지 이유가 있음) 실제로 트리를 시각화하려는 경우 reprtree 패키지를 사용할 수 있습니다 .

패키지는 잘 문서화되어 있지 않지만 (문서는 here 찾을 수 있습니다 ) 모든 것이 매우 간단합니다. 패키지를 설치하려면 repo의 initialize.R 을 참조하십시오. 간단히 다음을 실행하십시오.

options(repos='http://cran.rstudio.org')
have.packages <- installed.packages()
cran.packages <- c('devtools','plotrix','randomForest','tree')
to.install <- setdiff(cran.packages, have.packages[,1])
if(length(to.install)>0) install.packages(to.install)

library(devtools)
if(!('reprtree' %in% installed.packages())){
  install_github('araastat/reprtree')
}
for(p in c(cran.packages, 'reprtree')) eval(substitute(library(pkg), list(pkg=p)))

그런 다음 모델과 트리를 만드십시오.

library(randomForest)
library(reprtree)

model <- randomForest(Species ~ ., data=iris, importance=TRUE, ntree=500, mtry = 2, do.trace=100)

reprtree:::plot.getTree(model)

그리고 당신은 간다! 아름답고 간단합니다.

plot.getTree (model)에서 생성 된 트리

패키지의 다른 방법에 대해 알아 보려면 github 저장소를 확인할 수 있습니다. 당신이 선택하면 사실, plot.getTree.R을 , 당신은 저자의 자신의 구현을 사용하는 것을 알 수 as.tree()있는 CHL ♦는 당신이 그의 대답에 자신을 만들 수 제안합니다. 이것은 당신이 이것을 할 수 있음을 의미합니다 :

tree <- getTree(model, k=1, labelVar=TRUE)
realtree <- reprtree:::as.tree(tree, model)

그리고 잠재적으로 사용하는 realtree등 다른 나무 플로팅 패키지와 함께 나무 .


고마워요, 나는 여전히 행복하게 대답을 받아들이고 있습니다. 나는 새로운 새로운 것이 지원하는 것 같아요 xgboost.
smci

6
문제 없어요. 도서관 / 패키지를 찾는 데 몇 시간이 걸렸으므로 유용하지 않으면 다른 사람들이 나무를 그립니다 randomForest.
jgozal

2
멋진 발견. 참고 : 어떤 의미에서는 앙상블의 다른 모든 트리와 평균 "가장 가까운"앙상블의 트리를 나타냅니다
Chris

2
@Chris이 함수 plot.getTree()는 개별 트리를 플로팅합니다. plot.reprtree()해당 패키지 의 함수 는 대표 트리를 표시합니다.
Chun Li

1
캐럿에서 모델을 가져 와서 reptree에 피드하려고 reprtree:::plot.getTree(mod_rf_1$finalModel)하지만 " data.frame (var = fr $ var, splits = as.character (gTree [,"split point "])에 오류가 있습니다 : 인수가 다른 의미 행 수 : 2631, 0 "
HappyCoding

15

나무의 규칙을 추출하는 함수를 만들었습니다.

#**************************
#return the rules of a tree
#**************************
getConds<-function(tree){
  #store all conditions into a list
  conds<-list()
  #start by the terminal nodes and find previous conditions
  id.leafs<-which(tree$status==-1)
	  j<-0
	  for(i in id.leafs){
		j<-j+1
		prevConds<-prevCond(tree,i)
		conds[[j]]<-prevConds$cond
		while(prevConds$id>1){
		  prevConds<-prevCond(tree,prevConds$id)
		  conds[[j]]<-paste(conds[[j]]," & ",prevConds$cond)
        }
		if(prevConds$id==1){
			conds[[j]]<-paste(conds[[j]]," => ",tree$prediction[i])
    }
    }

  }

  return(conds)
}

#**************************
#find the previous conditions in the tree
#**************************
prevCond<-function(tree,i){
  if(i %in% tree$right_daughter){
		id<-which(tree$right_daughter==i)
		cond<-paste(tree$split_var[id],">",tree$split_point[id])
	  }
	  if(i %in% tree$left_daughter){
    id<-which(tree$left_daughter==i)
		cond<-paste(tree$split_var[id],"<",tree$split_point[id])
  }

  return(list(cond=cond,id=id))
}

#remove spaces in a word
collapse<-function(x){
  x<-sub(" ","_",x)

  return(x)
}


data(iris)
require(randomForest)
mod.rf <- randomForest(Species ~ ., data=iris)
tree<-getTree(mod.rf, k=1, labelVar=TRUE)
#rename the name of the column
colnames(tree)<-sapply(colnames(tree),collapse)
rules<-getConds(tree)
print(rules)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.