Перше (і найпростіше) рішення: Якщо ви не прагнете дотримуватися класичної RF, як це реалізовано в Енді Ляу randomForest
, ви можете спробувати партійний пакет, який забезпечує іншу реалізацію оригінального алгоритму RF ™ (використання умовних дерев та на основі схеми агрегації на основі на одиницю середньої ваги). Тоді, як повідомляється в цьому довідці про R-довідку , ви зможете побудувати одного члена списку дерев. Наче це працює безперебійно, наскільки я можу сказати. Нижче представлена ділянка одного дерева, породженого cforest(Species ~ ., data=iris, controls=cforest_control(mtry=2, mincriterion=0))
.
По- друге (майже так само легко) Рішення: Більшість методів дерева на основі в R ( tree
, rpart
, TWIX
і т.д.) пропонує tree
-like структуру для друку / прокладки одного дерева. Ідея полягала б у перетворенні результату 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), спираючись на tree:::treepl
(графічний дисплей) та tree:::treeco
(обчислити координати вузлів). Ці функції очікують obj$frame
подання дерева. Інші тонкі питання: (1) аргумент type = c("proportional", "uniform")
у методі побудови графіку за замовчуванням,, tree:::plot.tree
допомагає керувати вертикальною відстані між вузлами ( proportional
означає, що вона пропорційна відхиленню, uniform
означає, що вона фіксована); (2) вам потрібно доповнити plot(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
відповідно з вашими потребами, хоча я не приклад такого підходу. Зокрема, ви, мабуть, хочете позбутися від використання відхилень, ймовірностей класів тощо, які не мають сенсу в РФ. Все, що вам потрібно, це встановити координати вузлів та розділити значення. Ви можете використати fixInNamespace()
для цього, але, чесно кажучи, я не впевнений, що це правильний шлях.
Третє (і, безумовно, розумне) рішення: Напишіть справжню as.tree
функцію помічника, яка полегшить усі перераховані вище "патчі". Потім можна використовувати методи побудови R, або, можливо, краще, Клімт (безпосередньо з R) для відображення окремих дерев.