Solusi pertama (dan termudah): Jika Anda tidak ingin tetap menggunakan RF klasik, seperti yang diterapkan di Andy Liaw's randomForest
, Anda dapat mencoba paket pesta yang menyediakan implementasi berbeda dari algoritma RF ™ asli (penggunaan pohon kondisional dan skema agregasi berdasarkan rata-rata berat unit). Kemudian, seperti yang dilaporkan pada pos bantuan-R ini , Anda dapat memplot satu anggota dari daftar pohon. Sepertinya berjalan lancar, sejauh yang saya tahu. Di bawah ini adalah plot satu pohon yang dihasilkan oleh cforest(Species ~ ., data=iris, controls=cforest_control(mtry=2, mincriterion=0))
.
Kedua (hampir semudah) solusi: Sebagian besar teknik berbasis pohon di R ( tree
, rpart
, TWIX
, dll) menawarkan tree
struktur-seperti untuk pencetakan / merencanakan satu pohon. Idenya adalah untuk mengkonversi output randomForest::getTree
ke objek R seperti itu, bahkan jika itu tidak masuk akal dari sudut pandang statistik. Pada dasarnya, mudah untuk mengakses struktur pohon dari suatu tree
objek, seperti yang ditunjukkan di bawah ini. Harap dicatat bahwa itu akan sedikit berbeda tergantung pada jenis tugas - regresi vs klasifikasi - di mana dalam kasus selanjutnya akan menambah probabilitas kelas-spesifik sebagai kolom terakhir dari obj$frame
(yang merupakan 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
Lalu, ada metode untuk mencetak dan merencanakan objek-objek itu dengan cantik. Fungsi kuncinya adalah tree:::plot.tree
metode generik (saya menempatkan triple :
yang memungkinkan Anda untuk melihat kode dalam R langsung) bergantung pada tree:::treepl
(tampilan grafis) dan tree:::treeco
(menghitung koordinat node). Fungsi-fungsi ini mengharapkan obj$frame
representasi pohon. Masalah halus lainnya: (1) argumen type = c("proportional", "uniform")
dalam metode plotting default tree:::plot.tree
,, membantu mengatur jarak vertikal antara node ( proportional
berarti proporsional dengan penyimpangan, uniform
berarti tetap); (2) Anda perlu melengkapi plot(tr)
dengan panggilan untuk text(tr)
menambahkan label teks ke node dan split, yang dalam hal ini berarti Anda juga harus melihat tree:::text.tree
.
The getTree
metode dari randomForest
hasil struktur yang berbeda, yang didokumentasikan dalam bantuan online. Output khas ditunjukkan di bawah ini, dengan terminal node ditunjukkan oleh status
kode (-1). (Sekali lagi, output akan berbeda tergantung pada jenis tugas, tetapi hanya pada kolom status
dan 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
Jika Anda dapat mengubah tabel di atas menjadi yang dihasilkan oleh tree
, Anda mungkin akan dapat menyesuaikan tree:::treepl
, tree:::treeco
dan tree:::text.tree
sesuai dengan kebutuhan Anda, meskipun saya tidak memiliki contoh pendekatan ini. Secara khusus, Anda mungkin ingin menyingkirkan penggunaan penyimpangan, probabilitas kelas, dll. Yang tidak berarti dalam RF. Yang Anda inginkan adalah mengatur koordinat node dan nilai split. Anda bisa menggunakannya fixInNamespace()
untuk itu, tetapi, jujur saja, saya tidak yakin ini cara yang tepat.
Solusi ketiga (dan tentu saja pintar): Tulis as.tree
fungsi pembantu yang benar yang akan meringankan semua "tambalan" di atas. Anda kemudian dapat menggunakan metode merencanakan R atau, mungkin lebih baik, Klimt (langsung dari R) untuk menampilkan masing-masing pohon.