Aslında bir örnek ağaç randomForest :: getTree () 'den nasıl çizilir? [kapalı]


62

Herkes, aşağıdakilerden birkaç örnek ağacı çizmenin kütüphane veya kod önerilerini aldı:

getTree(rfobj, k, labelVar=TRUE)

(Evet, bunu operasyonel bir şekilde yapmanız gerekmediğini biliyorum, RF bir kara kutu, vb. Vb. Görüyorum. Bir ağacın görsel olarak akıl sağlığı kontrolünü yapmak istiyorum - herhangi bir değişkenin ters davranıp davranmadığını görmek için bir ağacı kontrol etmek, ince ayar yapmak / birleştirmek / elden çıkarma / dönüştürme, kontrol etmek kodlanmış faktörlerimin ne kadar iyi çalıştığı vs.)


İyi bir cevap olmadan önceki sorular:

Aslında örnek bir ağaç çizmek istiyorum . Bu yüzden benimle zaten bu konuda tartışma. varImpPlot(Değişken Önem Grafiği) veya partialPlotveya MDSPlotveya bu diğer araziler hakkında soru sormuyorum , zaten bunlara sahibim, ancak örnek bir ağaç görmenin yerini tutamazlar. Evet çıkışını görsel olarak inceleyebilirim getTree(...,labelVar=TRUE).

(Bir plot.rf.tree()katkı çok iyi karşılanacağını tahmin ediyorum.)


6
Öncelikle tartışmaya açık olmanın gerekliliğini görmüyorum, özellikle de birisinin size yardım etmesi için gönüllü olmasını isterseniz; iyi karşılaşmadı. CV'nin etik kuralları vardır - SSS bölümümüzü okumak isteyebilirsiniz .
gung - Reinstate Monica

9
@gung: Bu konuyla ilgili önceki her soru, örnek bir ağaç çizmenin gerekmediğine ve gerçekten de sapıklık olmadığına ısrar eden insanlara çürümeye başladı. Verdiğim alıntıları oku. Burada bir rf ağacının nasıl çizileceğini gösteren kodun bir taslağını arıyorum.
smci

3
Kullanıcıların yardımcı olmaya ve soruya cevap vermeye çalıştığı bazı cevapları görüyorum, bunun yanında fikrin öncülünü sorgulayan bazı yorumlar (dürüstçe inanıyorum ki, aynı zamanda yararlı bir ruhla da düşünülüyor). Bazı kişilerin sınamaya katılmadıklarına katılmayacağını kabul etmek kesinlikle mümkündür.
gung - Reinstate Monica

4
Bir yıl boyunca herhangi birinin bir ağacı çizdiği yerde sıfır cevap görüyorum. Bu soruya özel bir cevap arıyorum.
smci

1
Tek bir ağacın inşa edilmesi mümkündür cforest( parti paketinde). Aksi takdirde, data.framedöndürülen değeri benzer randomForest::getTreebir treenesneye dönüştürmeniz gerekir .
chl

Yanıtlar:


44

İlk (ve en kolay) çözüm: Andy Liaw’de uygulandığı gibi klasik RF’ye bağlı kalmak randomForestistemezseniz , orijinal RF algoritmasının farklı bir uygulamasını sağlayan parti paketini deneyebilirsiniz (şartlı ağaçların ve toplama planının kullanılması birim ağırlığı ortalama). Ardından, bu R-yardım direğinde bildirildiği gibi , ağaç listesinin tek bir üyesini çizebilirsiniz. Anladığım kadarıyla sorunsuz çalışıyor gibi görünüyor. Aşağıda, tarafından üretilen bir ağacın grafiği verilmiştir .cforest(Species ~ ., data=iris, controls=cforest_control(mtry=2, mincriterion=0))

görüntü tanımını buraya girin

İkinci (neredeyse kolay) çözeltisi: R ağaç esaslı tekniklerin çoğu ( tree, rpart, TWIXvs.) bulunmaktadır tree, tek ağaç çizme / baskı için benzeri bir yapı. Fikir, randomForest::getTreeistatistiksel bir bakış açısından saçma olmasa bile, böyle bir R nesnesinin çıktısını dönüştürmek olacaktır . Temel olarak, ağaç yapısına treeaşağıda gösterildiği gibi bir nesneden erişmek kolaydır . Regresyon sınıflandırma - - vs. sonraki durumda, son sütun olarak sınıf özgü olasılıkları katacak nerede hafifçe görevin türüne bağlı olarak farklılık göstereceğini unutmayın obj$frame(a olan 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

Sonra, bu nesnelerin güzel yazdırılması ve çizilmesi için yöntemler vardır. Anahtar işlevler genel bir tree:::plot.treeyöntemdir ( :kodu doğrudan R'de görüntülemenizi sağlayan üçlü bir koydum ) tree:::treepl(grafiksel gösterime) ve tree:::treeco(hesaplama düğümleri koordinatlarına) dayanıyor . Bu fonksiyonlar obj$frameağacın temsilini bekler . Diğer ince konular: (1) type = c("proportional", "uniform")varsayılan çizim yöntemindeki argüman , tree:::plot.treedüğümler arasındaki dikey mesafeyi yönetmeye yardımcı olur ( proportionalsapma ile orantılı uniformolduğu, sabit olduğu anlamına gelir); (2) düğümlere ve bölmelere metin etiketleri eklemek plot(tr)için yapılan bir çağrı ile tamamlamanız gerekir text(tr); bu durumda bu, ayrıca bir göz atmanız gerektiği anlamına gelir tree:::text.tree.

getTreeDan yöntem randomForestdöndürür çevrimiçi yardımda belgelenmiştir farklı bir yapı. Tipik bir çıktı, statuskod (-1) ile gösterilen terminal düğümleriyle aşağıda gösterilmiştir . (Yine, çıktı, görevin türüne bağlı olarak değişir, ancak yalnızca statusve predictionsütunlarına göre değişir .)

> 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

Eğer tarafından oluşturulan birine yukarıdaki tabloya dönüştürmek için yönetebilirsiniz ise tree, muhtemelen özelleştirmek mümkün olacak tree:::treepl, tree:::treecove tree:::text.treebu yaklaşımın bir örneği yok gerçi, ihtiyaçlarınıza göre. Özellikle, RF'de anlamlı olmayan sapma, sınıf olasılıkları vb. Kullanımından kurtulmak istersiniz. Tek istediğiniz düğümlerin koordinatlarını ayarlamak ve değerleri bölmektir. Bunun için kullanabilirsiniz fixInNamespace(), ama dürüst olmak gerekirse, bunun doğru yol olduğundan emin değilim.

Üçüncü (ve kesinlikle zekice) çözüm:as.tree Yukarıdaki tüm "yamaları" azaltan gerçek bir yardımcı işlev yazın . Tek tek ağaçları görüntülemek için R'nin çizim yöntemlerini veya muhtemelen daha iyi olan Klimt'i (doğrudan R'den) kullanabilirsiniz.


40

Dört yıl geciktim, ancak gerçekten randomForestpakete bağlı kalmak istiyorsanız (ve bunu yapmak için bazı iyi nedenler varsa) ve ağacı gerçekten görselleştirmek istiyorsanız, reprtree paketini kullanabilirsiniz .

Paket çok iyi belgelenmemiş (belgeleri burada bulabilirsiniz ), ancak her şey oldukça basit. Paketi kurmak için depodaki initialize.R'ye bakın , bu nedenle aşağıdakini çalıştırın:

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)))

Ardından devam edin ve modelinizi ve ağacınızı yapın:

library(randomForest)
library(reprtree)

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

reprtree:::plot.getTree(model)

Ve işte burda! Güzel ve basit.

plot.getTree'den üretilen ağaç (model)

Paketteki diğer yöntemler hakkında bilgi edinmek için github deposunu kontrol edebilirsiniz. Eğer kontrol Aslında, plot.getTree.R , yazar kendi uygulamasını kullandığını fark edeceksiniz as.tree()ki chl ♦ Eğer onun cevabını kendiniz inşa edebileceğini öne sürdü. Bu, bunu yapabileceğiniz anlamına gelir:

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

Ve potansiyel realtreeolarak, ağaç gibi diğer ağaç komplo paketleriyle birlikte kullanın .


Çok teşekkürler, hala cevapları memnuniyetle kabul ediyorum, bu insanların tekliflerden memnun olmadığı bir alan gibi görünüyor. Sanırım yeni şey de destekleyecek xgboost.
smci

6
sorun değil. Kütüphaneyi / paketi bulmam saatlerimi aldı, bu yüzden sizin için yararlı olmazsa, yine de randomForestpakete yapışırken ağaçlar çizmeye çalışanlar için olacağını düşündüm .
jgozal

2
Güzel keşif. Not: Bazı anlamda, topluluk içinde diğer tüm ağaçlara "en yakın" ortalama Hangi topluluk içinde ağaç temsili ağaç çizer
Chris

2
@Chris İşlev plot.getTree(), tek bir ağacı çizer . Bu plot.reprtree()paketteki işlev temsili bir ağacı çizer.
Chun Li

1
caret'ten model aldım ve reptree ile beslenmeyi istiyorum reprtree:::plot.getTree(mod_rf_1$finalModel), ancak bir " data.frame dosyasında hata var (var = fr $ var, splits = as.character (gTree [," split point "]),: argümanlar farklı satır sayısı: 2631, 0 "
HappyCoding

15

Bir ağacın kurallarını çıkarmak için bazı fonksiyonlar yarattım.

#**************************
#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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.