randomForest :: getTree()からサンプルツリーを実際にプロットする方法は?[閉まっている]


62

いくつかのサンプルツリーを実際にプロットする方法について、ライブラリまたはコードの提案がありました。

getTree(rfobj, k, labelVar=TRUE)

はいエンコードされたファクターがどれだけうまく機能しているかなど)


適切な答えのない事前の質問:

実際にサンプルツリープロットしたいです。だから、すでにそれについて私と議論しないでください。varImpPlot(Variable Importance Plot)やpartialPlotor MDSPlot、またはこれらの他のプロットについては聞いていませんが、それらは既にありますが、サンプルツリーを見ることの代わりではありません。はい、視覚的に出力を調べることができますgetTree(...,labelVar=TRUE)

plot.rf.tree()貢献は非常に歓迎されると思います。)


6
特に、誰かがあなたを助けてくれるボランティアを求めている場合、先制的に議論する必要はないと思います。うまく行きません。CVにはエチケットポリシーがあります。よくある質問をご覧ください
GUNG -モニカ元に戻し

9
@gung:このトピックに関する以前の質問はすべて、サンプルツリーをプロットする必要はなく、実際には異端であると主張する人々に崩壊しました。私が出した引用を読んでください。ここでは、RFツリーのプロットをコーディングする方法のスケッチを探しています。
-smci

3
アイデアの前提を疑問視するコメントとともに、ユーザーが助けになり、質問に答えようとしているいくつかの答えがあります(正直に信じていますが、それは役に立つ精神でも意図されています)。一部の人々がtest慢であることに同意しないことを認めることは確かに可能です。
GUNG -モニカ元に戻し

4
誰もが1年以上で木をプロットしたことがある場所では、答えがゼロです。私はその特定の質問に対する特定の答えを探しています。
-smci

1
cforestpartyパッケージで)で構築された単一のツリーをプロットすることができます。それ以外の場合は、data.frame戻り値randomForest::getTreetree-likeオブジェクトに変換する必要があります。
chl

回答:


44

最初の(そして最も簡単な)ソリューション: Andy Liaw's randomForestで実装されているように、従来のRFに固執したくない場合は、元のRF アルゴリズムの異なる実装を提供するパーティーパッケージを試すことができます単位重量平均で)。次に、このR-help投稿で報告されているように、ツリーのリストの単一のメンバーをプロットできます。私の知る限り、スムーズに実行されているようです。以下は、によって生成された1つのツリーのプロットです。cforest(Species ~ ., data=iris, controls=cforest_control(mtry=2, mincriterion=0))

ここに画像の説明を入力してください

第二に、(ほとんどのように簡単に)解決策: Rのツリーベースの技術のほとんどは(treerpartTWIX、など)を提供していますtree単一のツリーをプロット/印刷用の様な構造を。アイデアはrandomForest::getTree、統計的な観点から無意味である場合でも、出力をそのようなRオブジェクトに変換することです。基本的に、tree以下に示すように、オブジェクトからツリー構造に簡単にアクセスできます。タスクのタイプ(回帰と分類)によってわずかに異なることに注意してください。後者の場合、クラス固有の確率はobj$frame(の最後の列)として追加されます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)で示されます。(繰り返しますが、出力はタスクのタイプによって異なりますがstatusprediction列のみが異なります。)

> 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:::treepltree:::treecotree:::text.tree私は、このアプローチの例を持っていないのに、自分のニーズに合うように。特に、RFでは意味のない逸脱、クラス確率などの使用を取り除くことをお勧めします。必要なのは、ノードの座標を設定し、値を分割することです。fixInNamespace()そのために使用できますが、正直なところ、これが正しい方法であるかどうかはわかりません。

3番目の(そして確かに賢い)ソリューション:as.tree上記の「パッチ」のすべてを軽減する真のヘルパー関数を作成します。次に、Rのプロット方法を使用するか、おそらくより良い方法として、(Rから直接)Klimtを使用して個々のツリーを表示できます。


40

私は4年遅れですが、randomForestパッケージに固執したい(そしてそうするいくつかの正当な理由がある)場合、そして実際にツリーを視覚化したい場合、reprtreeパッケージを使用できます。

パッケージはあまりよく文書化されていません(ドキュメントはこちらで確認できます)が、すべてが非常に簡単です。パッケージをインストールするには、レポジトリの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
クールな発見。注意:これは、ある意味では、アンサンブル内の他のすべての木に「最も近い」平均であるアンサンブルのツリー代表ツリーをプロット
クリス・

2
@Chrisこの関数plot.getTree()は、個々のツリーをプロットします。plot.reprtree()そのパッケージの関数は、代表的なツリーをプロットします。
春麗

1
キャレットからモデルを取得してreptreeにフィードしたいのですreprtree:::plot.getTree(mod_rf_1$finalModel)が、「data.frame(var = fr $ var、splits = as.character(gTree [、 "split point"]]にエラーがあります:引数が異なることを意味します行数:
2631、0

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.