通过RPART包生成测试规则(Testing rules generated by Rpart pa

2019-07-30 19:12发布

我想从树上产生的编程方式一个规则来测试。 在树上的根和叶(终端节点)之间的路径可以被解释为一个规则。

在R,我们可以使用rpart包并执行以下操作:(在这篇文章中,我将使用iris数据集,例如仅供参考)

library(rpart)
model <- rpart(Species ~ ., data=iris)

有了这个两行我得到了一棵树命名的model ,它的类是rpart.objectrpart文档,21页)。 该对象有大量的信息,并且支持多种方法。 特别地,所述对象具有frame变量(其可以以标准方式进行访问: model$frame )( 同上 ),并且该方法path.rpathrpart文档,第7页),它给你的路径从所述根节点到感兴趣的(节点node参数的函数)

所述row.names所述的frame变量包含树的节点号。 该var列给出在节点分裂变量, yval拟合值和yval2类概率等信息。

> model$frame
           var   n  wt dev yval complexity ncompete nsurrogate     yval2.1     yval2.2     yval2.3     yval2.4     yval2.5     yval2.6     yval2.7
1 Petal.Length 150 150 100    1       0.50        3          3  1.00000000 50.00000000 50.00000000 50.00000000  0.33333333  0.33333333  0.33333333
2       <leaf>  50  50   0    1       0.01        0          0  1.00000000 50.00000000  0.00000000  0.00000000  1.00000000  0.00000000  0.00000000
3  Petal.Width 100 100  50    2       0.44        3          3  2.00000000  0.00000000 50.00000000 50.00000000  0.00000000  0.50000000  0.50000000
6       <leaf>  54  54   5    2       0.00        0          0  2.00000000  0.00000000 49.00000000  5.00000000  0.00000000  0.90740741  0.09259259
7       <leaf>  46  46   1    3       0.01        0          0  3.00000000  0.00000000  1.00000000 45.00000000  0.00000000  0.02173913  0.97826087

但是,只有被标记为<leaf>var列是终端节点( 叶子 )。 在这种情况下,节点2,6和7。

正如上面提到的可以使用path.rpart方法提取的规则(这种技术在使用rattle包,并在文章夏尔马信用评分 ,如下所示:

的方法,另外,该模型保持了预测值的中值

predicted.levels <- attr(model, "ylevels")

该值对应与列yvalmodel$frame数据组。

用于与节点号7(第5行)的叶,预测值是

> ylevels[model$frame[5, ]$yval]
[1] "virginica"

和规则

> rule <- path.rpart(model, nodes = 7)

 node number: 7 
   root
   Petal.Length>=2.45
   Petal.Width>=1.75

因此,规则可以被解读为

If Petal.Length >= 2.45 AND Petal.Width >= 1.75 THEN Species = Virginica

我知道我可以测试(在测试数据集,我会用数据再次设定光圈)有多少真阳性有这个规则,子集划分的新的数据集如下

> hits <- subset(iris, Petal.Length >= 2.45 & Petal.Width >= 1.75)

然后计算所述混淆矩阵

> table(hits$Species, hits$Species == "virginica")

             FALSE TRUE
  setosa         0    0
  versicolor     1    0
  virginica      0   45

(注:我用同样的虹膜数据设置为测试)

我怎么能评价一个编程方式的规则? 我可以从规则中提取的条件如下

> unlist(rule, use.names = FALSE)[-1]
[1] "Petal.Length>=2.45" "Petal.Width>=1.75" 

但是,我怎么能在这里继续下去吗? 我不能使用subset函数

提前致谢

注意: 这个问题已经被大量编辑更清晰

Answer 1:

我可以通过以下方式解决这个问题

免责声明:显然必须解决这个更好的方式,但这种黑客的作品,并做我想做的......(我不是很骄傲......是的hackish,但工程)

好吧,让我们开始。 基本想法是使用包sqldf

如果您检查问题,代码的最后一块,列表中的每一片树的路径的提出。 所以,我会从这里开始

        library(sqldf)
        library(stringr)

        # Transform to a character vector
        rule.v <- unlist(rule, use.names=FALSE)[-1]
        # Remove all the dots, sqldf doesn't handles dots in names 
        rule.v <- str_replace_all(rule.v, pattern="([a-zA-Z])\\.([a-zA-Z])", replacement="\\1_\\2")
        # We have to remove all the equal signs to 'in ('
        rule.v <- str_replace_all(rule.v, pattern="([a-zA-Z0-9])=", replacement="\\1 in ('")
        # Embrace all the elements in the lists of values with " ' " 
        # The last element couldn't be modified in this way (Any ideas?) 
        rule.v <- str_replace_all(rule.v, pattern=",", replacement="','")

        # Close the last element with apostrophe and a ")" 
        for (i in which(!is.na(str_extract(pattern="in", string=rule.v)))) {
          rule.v[i] <- paste(append(rule.v[i], "')"), collapse="")
        }

        # Collapse all the list in one string joined by " AND "
        rule.v <- paste(rule.v, collapse = " AND ")

        # Generate the query
        # Use any metric that you can get from the data frame
        query <- paste("SELECT Species, count(Species) FROM iris WHERE ", rule.v, " group by Species", sep="")

        # For debug only...
        print(query)

        # Execute and print the results
        print(sqldf(query))

就这样!

我警告你,这是hackish的...

希望这可以帮助其他人...

感谢所有帮助和建议!



Answer 2:

总的来说,我不推荐使用eval(parse(...))但在这种情况下,它似乎工作:

提取规则:

rule <- unname(unlist(path.rpart(model, nodes=7)))[-1]

 node number: 7 
   root
   Petal.Length>=2.45
   Petal.Width>=1.75
rule
[1] "Petal.Length>=2.45" "Petal.Width>=1.75" 

提取使用规则中的数据:

node_data <- with(iris, iris[eval(parse(text=paste(rule, collapse=" & "))), ])
head(node_data)

    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
71           5.9         3.2          4.8         1.8 versicolor
101          6.3         3.3          6.0         2.5  virginica
102          5.8         2.7          5.1         1.9  virginica
103          7.1         3.0          5.9         2.1  virginica
104          6.3         2.9          5.6         1.8  virginica
105          6.5         3.0          5.8         2.2  virginica


Answer 3:

从...开始

Rule number: 16 [yval=bad cover=220 N=121 Y=99 (37%) prob=0.04]
checking< 2.5
afford< 54
history< 3.5
coapp< 2.5

您将有开始是全零,你可以用rule16更新“概率”向量:

prob <- ifelse( dat[['checking']] < 2.5 &
                dat[['afford']]  < 54
                dat[['history']] < 3.5
                dat[['coapp']]  < 2.5) , 0.04, prob )

那么你就需要通过其他所有的规则来运行(这不应该改变任何概率这种情况下,因为树应该是不相交的估计。)有可能会比这更有效的方法构建的预测。 例如...的predict.rpart功能。



文章来源: Testing rules generated by Rpart package