【问题标题】:How to get J48 size and number of leaves如何获得J48的大小和叶子数量
【发布时间】:2017-11-18 03:04:53
【问题描述】:

如果我通过以下方式构建 J48 树:

library(RWeka)

fit <- J48(Species~., data=iris)

我得到以下结果:

> fit
J48 pruned tree
------------------

Petal.Width <= 0.6: setosa (50.0)
Petal.Width > 0.6
|   Petal.Width <= 1.7
|   |   Petal.Length <= 4.9: versicolor (48.0/1.0)
|   |   Petal.Length > 4.9
|   |   |   Petal.Width <= 1.5: virginica (3.0)
|   |   |   Petal.Width > 1.5: versicolor (3.0/1.0)
|   Petal.Width > 1.7: virginica (46.0/1.0)

Number of Leaves  :     5

Size of the tree :  9

我想将Number of Leaves 放入变量N(因此N 将获得5)并将Size of the tree 转换为S(因此S 将获得9)。

有没有办法直接从 J48 树中获取这些信息?

【问题讨论】:

  • 这也可能适用于数据科学 SO 或交叉验证,因为可能有比“机械”更好的选择

标签: r weka


【解决方案1】:

正如@LyzanderR 之前指出的,直接在J48 对象上执行此操作并不容易。一般来说,RWeka 中的拟合函数返回的对象通常在 R 端包含相对较少的信息(例如,只有调用和拟合预测)。主要成分通常是对 Weka 构建的 Java 对象的引用,Weka 自己的方法可以通过 .jcall 在 Java 端应用,然后在 R 中返回。

然而,对于J48 树,很容易将来自Java 端的信息转换为标准函数和方法可用的R 对象。 partykit 包提供了一个强制函数,可将 J48 树转换为 constparty 对象(叶中具有恒定拟合的递归分区)。然后可以使用length()width()depth()等方法分别查询树的节点数、叶子数和深度。

library("RWeka")
fit <- J48(Species ~ ., data = iris)
library("partykit")
p <- as.party(fit)
length(p)
## [1] 9
width(p)
## [1] 5
depth(p)
## [1] 4

此外,predict()plot()print() 和许多其他工具可用于 party 对象。

我建议在@LyzanderR 建议的文本解析上使用这种方法,因为as.party 转换不依赖于可能容易出错的文本计算。相反,它在内部调用 Weka 自己的 graph 生成器(通过 .jcall),然后将其解析为 constparty 结构。

【讨论】:

    【解决方案2】:

    有趣的是,fit 的输出似乎是在 print.Weka_classifier.jcall 函数中创建的,从 getAnywhere(print.Weka_classifier) 可以看出。这使得从打印输出中提取值变得更加困难(但并非不可能)。

    为了存储这两个值,您可以这样做:

    library(RWeka)
    
    fit <- J48(Species~., data=iris)
    
    #store the print output in a
    a <- capture.output(fit)
    
    > a
     [1] "J48 pruned tree"                                     "------------------"                                 
     [3] ""                                                    "Petal.Width <= 0.6: setosa (50.0)"                  
     [5] "Petal.Width > 0.6"                                   "|   Petal.Width <= 1.7"                             
     [7] "|   |   Petal.Length <= 4.9: versicolor (48.0/1.0)"  "|   |   Petal.Length > 4.9"                         
     [9] "|   |   |   Petal.Width <= 1.5: virginica (3.0)"     "|   |   |   Petal.Width > 1.5: versicolor (3.0/1.0)"
    [11] "|   Petal.Width > 1.7: virginica (46.0/1.0)"         ""                                                   
    [13] "Number of Leaves  : \t5"                              ""                                                   
    [15] "Size of the tree : \t9"      
    
    # get the output length, so that this can work for a tree
    # with any size/number of leaves
    out_length = length(a)
    
    # then save the number from the fourth to last element to N
    N <- as.numeric(gsub('\\D', '', a[out_length - 3]))
    
    #then save the number from second to last element to S
    S <- as.numeric(gsub('\\D', '', a[out_length - 1]))
    

    你有它:

    > N
    [1] 5
    > S
    [1] 9
    

    【讨论】:

    • 这似乎也是负担最小的选项,因为我不知道partykit(您可以将 J48 适合的对象转换为派对工具包或派对对象)会使信息易于访问并转换为 DOT 文件并使用 igraph 似乎有点矫枉过正(至少对我而言)。
    • @hrbrmstr 我什至不知道有一个包可以做到这一点。很高兴知道谢谢。但是,如果您说这样做有点矫枉过正,我会相信您的话:)
    • hrbrmstr,如何使用partykit 获得它?
    • 我明天可以发布正确的答案。简短版本是:p &lt;- as.party(fit),然后是 length(p)width(p)
    猜你喜欢
    • 2015-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-31
    • 1970-01-01
    • 2022-12-19
    • 2020-03-06
    • 2014-03-04
    相关资源
    最近更新 更多