【问题标题】:Weka Decision tree Java to listsWeka 决策树 Java 到列表
【发布时间】:2014-11-25 05:42:36
【问题描述】:

我想创建一个决策树并将其分解为列表(名称、符号、值)。 我用这段代码制作了树:

        //Get File
        BufferedReader reader = new BufferedReader(new FileReader(PATH + "TempArffFile.arff"));

        //Get the data
        Instances data = new Instances(reader);
        reader.close();

        //Setting class attribute 
        data.setClassIndex(data.numAttributes() - 1);

        //Make tree
        J48 tree = new J48();
        String[] options = new String[1];
        options[0] = "-U"; 
        tree.setOptions(options);
        tree.buildClassifier(data);

        //Print tree
        System.out.println(tree);

现在我需要将它分解为数组我该怎么做?

示例: 我得到了这棵树:

title <= 1: bad (4.0)
title > 1
|   positionMatch <= 1
|   |   countryCode <= 1: good (3.0/1.0)
|   |   countryCode > 1: bad (8.0/3.0)
|   positionMatch > 1: good (4.0/1.0)

所以我想从该树中获取 4 个列表:

  • title( 不好
  • title(> 1) -> position( countryCode( 好
  • title(> 1) -> position( countryCode(> 1) -> 错误
  • title(> 1) -> position(> 1) -> 好

我该怎么做?

【问题讨论】:

    标签: java weka decision-tree


    【解决方案1】:

    没那么好,但也许比没有更好... 也许它会给你一个想法。

        public static void split(String tree){
    
        String[] lines = tree.split("\n");
        List<List<String>> lists = new ArrayList<List<String>>(); 
        for(String line : lines){
            List<String> temp = new ArrayList<String>();
            while(line.indexOf("|") != -1){
                temp.add("|");
                line = line.replaceFirst("\\|", "");
            }
            temp.add(line.trim());
            lists.add(temp);
        }
    
        for(int i = 0; i < 3; i++){
            lists.remove(0);
        }
        for(int i = 0; i < 4; i++){
            lists.remove(lists.size()-1);
        }
        List<String> substitutes = new ArrayList<String>();
    
        for(List<String> list : lists){
            for(int i = 0; i < list.size(); i++){
                if(!list.get(i).contains(":") && !list.get(i).equals("|") && !substitutes.contains(list.get(i))){
                    substitutes.add(list.get(i));
                }
            }
        }
        for(List<String> list : lists){
            for(int i = 0; i < list.size(); i++){
                if(list.get(i).equals("|")){
                    list.set(i, substitutes.get(i));
                }
            }
        }
        StringBuilder sb = new StringBuilder();
        for(List<String> list : lists){
            String line = "";
            for(String s : list){
                line = line+" "+s;
            }
            if(line.endsWith(")")){
                sb.append(line+"\n");
            }
        }
        System.out.println(sb.toString());
    }
    

    输入

    J48 未修剪的树

    花瓣宽度

    花瓣宽度 > 0.6

    |花瓣宽度

    | |花瓣长度

    | |花瓣长度 > 4.9

    | | |花瓣宽度

    | | |花瓣宽度 > 1.5:鸢尾花 (3.0/1.0)

    |花瓣宽度 > 1.7: Iris-virginica (46.0/1.0)

    叶子数:5

    树的大小:9

    输出:

    花瓣宽度

    花瓣宽度 > 0.6 花瓣宽度

    花瓣宽度 > 0.6 花瓣宽度 4.9 花瓣宽度

    花瓣宽度 > 0.6 花瓣宽度 4.9 花瓣宽度 > 1.5:Iris-versicolor (3.0/1.0)

    petalwidth > 0.6 petalwidth > 1.7: Iris-virginica (46.0/1.0)

    【讨论】:

    • 我希望有一些内置的东西。非常感谢它可以节省我很多时间。
    • 一个可能的解决方案是扩展 Weka 的 J48 并根据您的需要覆盖 toString 方法。
    【解决方案2】:

    首先,解析行的答案似乎有问题(我无法评论它:(),它似乎用父子句替换了每个'|',但是对于像这样的树:

    一个 | C 乙 | D

    替换将是错误的,两个'|' C 和 D 前面的将被 A 替换。

    此外,扩展类 J48 并重新实现 toString() 也无济于事,因为该树实际上存在于私有变量 m_root 中。

    更新:

    解析字符串的更好解决方案。

    private void string(J48 j48) {
    
        String tree = j48.toString();
        String[] lines = tree.split("\n");
    
        List<List<String>> lists = new ArrayList<List<String>>();
        // Break lines into parts.
        for(String line : lines){
            List<String> temp = new ArrayList<String>();
            while(line.indexOf("|") != -1){
                temp.add("|");
                line = line.replaceFirst("\\|", "");
            }
            temp.add(line.trim());
            lists.add(temp);
        }
    
        // remove first 3 lines of the output.
        for(int i = 0; i < 3; i++){
            lists.remove(0);
        }
        // remove last 4 lines of the output.
        for(int i = 0; i < 4; i++){
            lists.remove(lists.size()-1);
        }
    
        // This is a ordered list of parents for any given node while traversing the tree.
        List<String> parentClauses = new ArrayList<String>();
        // this describes the depth
        //int depth = -1;
    
        // all the paths in the tree.
        List<List<String>> paths = new ArrayList<List<String>>();
    
    
        for (List<String> list : lists) {
            int currDepth = 0;
            for(int i = 0; i < list.size(); i++){
                String token = list.get(i);
                // find how deep is this node in the tree.
                if (token.equals("|")) {
                    currDepth++;
                }
                else {    // now we get to the string token for the node.
                    // if leaf, so we get one path..
                    if (token.contains(":")) {
                        List<String> path = new ArrayList<String>();
                        for (int index = 0; index < currDepth; index++) {
                            path.add(parentClauses.get(index));
                        }
                        path.add(token);
                        paths.add(path);
                    }
                    else {
                        // add this to the current parents list
                        parentClauses.add(currDepth, token);
                    }
                }
            }
        }
    
        // print each of the paths.
        for (List<String> path : paths) {
            String str = "";
            for (String token : path) {
                str += token + " AND ";
            }
            LOG.info(str + "\n");
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2014-11-23
      • 2015-02-06
      • 2021-05-16
      • 2020-08-25
      • 2014-12-29
      • 2017-01-25
      • 2018-09-27
      • 2021-12-10
      • 2016-09-02
      相关资源
      最近更新 更多