Giải pháp đầu tiên (và dễ nhất): Nếu bạn không thích sử dụng RF cổ điển, như được triển khai trong Andy Liaw randomForest
, bạn có thể thử gói bên cung cấp cách triển khai khác của thuật toán RF ™ ban đầu (sử dụng cây có điều kiện và sơ đồ tổng hợp dựa trên trên đơn vị trọng lượng trung bình). Sau đó, như đã báo cáo trên bài đăng trợ giúp R này , bạn có thể vẽ một thành viên duy nhất trong danh sách các cây. Nó dường như chạy trơn tru, như tôi có thể nói. Dưới đây là một âm mưu của một cây được tạo ra bởi cforest(Species ~ ., data=iris, controls=cforest_control(mtry=2, mincriterion=0))
.
Thứ hai (gần như là dễ dàng) Giải pháp: Hầu hết các kỹ thuật cây có trụ sở tại R ( tree
, rpart
, TWIX
, vv) cung cấp một tree
cấu trúc -like in / vẽ một cái cây duy nhất. Ý tưởng sẽ là chuyển đổi đầu ra của randomForest::getTree
một đối tượng R như vậy, ngay cả khi nó không hợp lý theo quan điểm thống kê. Về cơ bản, thật dễ dàng để truy cập cấu trúc cây từ một tree
đối tượng, như hiển thị bên dưới. Xin lưu ý rằng nó sẽ hơi khác nhau tùy thuộc vào loại nhiệm vụ - hồi quy so với phân loại - trong trường hợp sau, nó sẽ thêm xác suất cụ thể của lớp làm cột cuối cùng của obj$frame
(đó là 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
Sau đó, có các phương pháp để in đẹp và vẽ các đối tượng đó. Các hàm chính là một tree:::plot.tree
phương thức chung (tôi đặt một bộ ba :
cho phép bạn xem mã trực tiếp trong R) dựa vào tree:::treepl
(hiển thị đồ họa) và tree:::treeco
(tính toán tọa độ các nút). Các chức năng này mong đợi sự obj$frame
đại diện của cây. Các vấn đề tinh tế khác: (1) đối số type = c("proportional", "uniform")
trong phương pháp vẽ mặc định tree:::plot.tree
, giúp quản lý khoảng cách dọc giữa các nút ( proportional
có nghĩa là nó tỷ lệ với độ lệch, uniform
có nghĩa là nó đã được sửa); (2) bạn cần bổ sung plot(tr)
bằng một cuộc gọi để text(tr)
thêm nhãn văn bản vào các nút và phân tách, trong trường hợp này có nghĩa là bạn cũng sẽ phải xem qua tree:::text.tree
.
Các getTree
phương pháp từ randomForest
lợi nhuận một cấu trúc khác nhau, mà được diễn tả trong trợ giúp trực tuyến. Một đầu ra điển hình được hiển thị bên dưới, với các nút đầu cuối được chỉ định bởi status
mã (-1). (Một lần nữa, đầu ra sẽ khác nhau tùy thuộc vào loại nhiệm vụ, nhưng chỉ trên các cột status
và prediction
cột.)
> 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
Nếu bạn có thể quản lý để chuyển đổi bảng trên cho một tạo ra bởi tree
, có thể bạn sẽ có thể tùy chỉnh tree:::treepl
, tree:::treeco
và tree:::text.tree
để phù hợp với nhu cầu của bạn, mặc dù tôi không có một ví dụ của phương pháp này. Cụ thể, bạn có thể muốn thoát khỏi việc sử dụng sai lệch, xác suất của lớp, v.v. không có ý nghĩa trong RF. Tất cả những gì bạn muốn là thiết lập tọa độ nút và chia giá trị. Bạn có thể sử dụng fixInNamespace()
cho điều đó, nhưng thành thật mà nói, tôi không chắc đây là con đường đúng đắn.
Giải pháp thứ ba (và chắc chắn thông minh): Viết một as.tree
hàm trợ giúp thực sự sẽ làm giảm bớt tất cả các "bản vá" ở trên. Sau đó, bạn có thể sử dụng các phương pháp vẽ đồ thị của R hoặc, có lẽ tốt hơn, Klimt (trực tiếp từ R) để hiển thị các cây riêng lẻ.