วิธีแก้ปัญหาแรก (และง่ายที่สุด):หากคุณไม่กระตือรือร้นที่จะใช้ RF แบบคลาสสิกดังที่นำมาใช้ใน Andy Liaw's randomForest
คุณสามารถลองแพ็คเกจปาร์ตี้ซึ่งนำเสนอการใช้งานที่แตกต่างกันของอัลกอริทึมRF ™ดั้งเดิม(ใช้ต้นไม้ตามเงื่อนไข ในหน่วยน้ำหนักเฉลี่ย) จากนั้นตามที่รายงานไว้ในโพสต์ความช่วยเหลือ Rนี้คุณสามารถลงจุดสมาชิกรายชื่อต้นไม้ได้ ดูเหมือนว่าจะทำงานได้อย่างราบรื่นเท่าที่ฉันสามารถบอกได้ cforest(Species ~ ., data=iris, controls=cforest_control(mtry=2, mincriterion=0))
ด้านล่างเป็นพล็อตของต้นไม้ต้นหนึ่งที่สร้างขึ้นโดย
ประการที่สอง (เกือบเป็นเรื่องง่าย) วิธีการ:ที่สุดของเทคนิคที่มีต้นไม้ขึ้นอยู่ใน R ( tree
, rpart
, TWIX
ฯลฯ ) มี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 โดยตรง) อาศัย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
เพื่อให้เหมาะกับความต้องการของคุณ แต่ฉันไม่ได้มีตัวอย่างของวิธีการนี้ โดยเฉพาะอย่างยิ่งคุณอาจต้องการกำจัดการใช้ความเบี่ยงเบนความน่าจะเป็นในชั้นเรียน ฯลฯ ซึ่งไม่มีความหมายใน RF สิ่งที่คุณต้องการคือการตั้งค่าพิกัดโหนดและค่าแยก คุณสามารถใช้fixInNamespace()
สำหรับสิ่งนั้น แต่เพื่อความซื่อสัตย์ฉันไม่แน่ใจว่านี่เป็นวิธีที่เหมาะสมที่จะไป
โซลูชันที่สาม (และฉลาดอย่างแน่นอน):เขียนas.tree
ฟังก์ชันตัวช่วยจริงซึ่งจะช่วยบรรเทา "แพทช์" ด้านบนทั้งหมด จากนั้นคุณสามารถใช้วิธีการวางแผนของ R หรืออาจจะดีกว่าKlimt (โดยตรงจาก R) เพื่อแสดงต้นไม้แต่ละต้น