J48 树 (RWeka) 中的属性及其值
Posted
技术标签:
【中文标题】J48 树 (RWeka) 中的属性及其值【英文标题】:Properties and their values out of J48 tree (RWeka) 【发布时间】:2015-11-17 01:21:29 【问题描述】:如果您运行以下命令:
library(RWeka)
data(iris)
res = J48(Species ~., data = iris)
res
将是类J48
的列表,继承自Weka_tree
。如果你打印它
R> res
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
我想按从右到左的顺序获取属性及其值。所以对于这种情况:
Petal.Width, Petal.Width, Petal.Length, Petal.Length.
我尝试将 res 输入到一个因子并运行命令:
str_extract(paste0(x, collapse=""), perl("(?<=\\|)[A-Za-z]+(?=\\|)"))
没有成功。 只是要记住我们应该忽略左边的字符。
【问题讨论】:
【参考方案1】:一种方法是将J48
对象从RWeka
转换为party
对象从partykit
。你只需要as.party(res)
,它会为你完成所有解析并返回一个更容易使用标准化提取函数等的结构。
然后,您尤其可以使用其他讨论中关于ctree
对象等的所有建议。请参阅
How to extract the splitting rules for the terminal nodes of ctree()
Get decision tree rule/path pattern for every row of predicted dataset for rpart/ctree package in R
Identify all distinct variables within party ctree nodel
而且我认为以下内容至少可以满足您的要求:
library("partykit")
pres <- as.party(res)
partykit:::.list.rules.party(pres)
## 2
## "Petal.Width <= 0.6"
## 5
## "Petal.Width > 0.6 & Petal.Width <= 1.7 & Petal.Length <= 4.9"
## 7
## "Petal.Width > 0.6 & Petal.Width <= 1.7 & Petal.Length > 4.9 & Petal.Width <= 1.5"
## 8
## "Petal.Width > 0.6 & Petal.Width <= 1.7 & Petal.Length > 4.9 & Petal.Width > 1.5"
## 9
## "Petal.Width > 0.6 & Petal.Width > 1.7"
更新:OP 联系了我,询问了一个相关问题,要求提供树的特定印刷表示。我在这里包括我的解决方案,以防它对其他人有用。
他想要 ( ) 符号表示层次结构级别以及拆分变量的名称。一种方法是 (1) 提取基础数据的变量名称:
nam <- names(pres$data)
(2)将树的递归结点结构转成扁平列表(构造想要的字符串稍微方便一些):
tr <- as.list(pres$node)
(3a) 初始化字符串:
str <- "("
(3b) 递归地将括号和/或变量名添加到字符串中:
update_str <- function(x)
if(is.null(x$kids))
str <<- paste(str, ")")
else
str <<- paste(str, nam[x$split$varid], "(")
for(i in x$kids) update_str(tr[[i]])
(3c) 调用递归,从根节点开始:
update_str(tr[[1]])
str
## [1] "( Petal.Width ( ) Petal.Width ( Petal.Length ( ) Petal.Width ( ) ) )"
【讨论】:
Achim,非常感谢您的优雅回答! 如果对您有用,请接受答案和/或 +1。【参考方案2】:我希望我不会错过您的观点,但我假设您想以某种方式创建和存储基于树模型终端节点的规则。就个人而言,我发现模型树构建包(RWeka、party、partykit、rpart)无法让用户在构建模型后创建有用的规则列表。当然,当变量和拆分很少时,您可以解释树形图。
到目前为止,我发现的唯一简单而可靠的方法(我自己使用)是 rpart 包的命令“path.rpart”。如果您真的想使用 RWeka,该解决方案似乎无关紧要,但我会尝试一下:
library(rpart)
res = rpart(Species ~., data = iris)
res
# n= 150
#
# node), split, n, loss, yval, (yprob)
# * denotes terminal node
#
# 1) root 150 100 setosa (0.33333333 0.33333333 0.33333333)
# 2) Petal.Length< 2.45 50 0 setosa (1.00000000 0.00000000 0.00000000) *
# 3) Petal.Length>=2.45 100 50 versicolor (0.00000000 0.50000000 0.50000000)
# 6) Petal.Width< 1.75 54 5 versicolor (0.00000000 0.90740741 0.09259259) *
# 7) Petal.Width>=1.75 46 1 virginica (0.00000000 0.02173913 0.97826087) *
# capture terminal nodes
terminal_nodes = rownames(res$frame)[res$frame$var =="<leaf>"]
# print rules for the terminal nodes
path.rpart(res ,nodes=terminal_nodes)
# node number: 2
# root
# Petal.Length< 2.45
#
# node number: 6
# root
# Petal.Length>=2.45
# Petal.Width< 1.75
#
# node number: 7
# root
# Petal.Length>=2.45
# Petal.Width>=1.75
# print above rules as list
rules = path.rpart(res ,nodes=terminal_nodes)
listed_rules = unlist(rules)
sapply(rules,"[",-1)
# $`2`
# [1] "Petal.Length< 2.45"
#
# $`6`
# [1] "Petal.Length>=2.45" "Petal.Width< 1.75"
#
# $`7`
# [1] "Petal.Length>=2.45" "Petal.Width>=1.75"
【讨论】:
以上是关于J48 树 (RWeka) 中的属性及其值的主要内容,如果未能解决你的问题,请参考以下文章