Orange Forum • View topic - Export big tree and rules [solved]

Export big tree and rules [solved]

A place to ask questions about methods in Orange and how they are used and other general support.

Export big tree and rules [solved]

Postby oleczek » Thu Feb 02, 2012 16:42

Hi

Is there a way to easily export a big decision tree picture. I was trying and achieved only partial results - not an entire tree.

Another question: is it possible to export it somehow into more interactive way? For example do you know any way (perhaps external app) to show it during the presentation by unfolding?

Regards!
Oleczek
Last edited by oleczek on Thu Mar 22, 2012 17:48, edited 1 time in total.

Re: Export big tree and rules

Postby oleczek » Thu Feb 02, 2012 16:43

Oh, and the second part of the question: how to dump the whole ruleset? I would like to have all rules listed in a form of "what-if". I can do it now selecting each one separately from the text tree view only. Hope there is some easy way ;)

Re: Export big tree and rules

Postby Ales » Fri Feb 03, 2012 10:20

oleczek wrote:Is there a way to easily export a big decision tree picture. I was trying and achieved only partial results - not an entire tree.

The 'Save Graph' in the 'Classification Tree Graph' should work. What kind of a problem do you have. If there is a problem with the Save Graph functionality, does it manifest for binary formats (PNG, ...) as well as vector graphics format (SVG)?
oleczek wrote:how to dump the whole ruleset? I would like to have all rules listed in a form of "what-if". I can do it now selecting each one separately from the text tree view only. Hope there is some easy way ;)

I don't think there is any easy way to do this without resorting to python scripting.

Re: Export big tree and rules

Postby oleczek » Sun Feb 12, 2012 21:47

Ok, so I have managed to put my visual code into the python. I can get the tree model, but I have still very limited ideas on how to parse it. Does it require me to parse the tree with text functions, or perhaps there is some better methods?

I need to go from this:
Code: Select all
a
| b
| | d
| | c


To this:

Code: Select all
if [ a & b &d ]; then "class x"
if [ a & b &c ]; then "class y"


for each rule.

Thank you for any hints.

Regards,
oleczek

Re: Export big tree and rules

Postby Ales » Wed Feb 15, 2012 10:33

Use something like this:
Code: Select all
rules = []
stack = []
def to_rules(node):
    if node.branches:
        for branch, desc in zip(node.branches, node.branch_descriptions):
             stack.append((node.branch_selector.class_var.name, desc))
             to_rules(branch)
             stack.pop(-1)
    else:
        rules.append((list(stack), node.node_classifier.default_value))

to_rules(tree_classifier.tree)
print rules

Then transform the resulting rules list into a suitable format.

Re: Export big tree and rules

Postby oleczek » Mon Feb 20, 2012 2:13

Thank you Ales.

I've been trying to implement it with C4.5 (not with the default Tree) but the names (branches etc) in the class are different.

I've found this in the docs:

Code: Select all
def printTree0(node, classvar, lev):
    var = node.tested

    if node.nodeType == 0:
        print "%s (%.1f)" % (classvar.values[int(node.leaf)], node.items),

    elif node.nodeType == 1:
        for i, val in enumerate(var.values):
            print ("\n"+"|    "*lev + "%s = %s:") % (var.name, val),
            printTree0(node.branch[i], classvar, lev+1)

    elif node.nodeType == 2:
        print ("\n"+"|    "*lev + "%s <= %.1f:") % (var.name, node.cut),
        printTree0(node.branch[0], classvar, lev+1)
        print ("\n"+"|    "*lev + "%s > %.1f:") % (var.name, node.cut),
        printTree0(node.branch[1], classvar, lev+1)

    elif node.nodeType == 3:
        for i, branch in enumerate(node.branch):
            inset = filter(lambda a:a[1]==i, enumerate(node.mapping))
            inset = [var.values[j[0]] for j in inset]
            if len(inset)==1:
                print ("\n"+"|    "*lev + "%s = %s:") % (var.name, inset[0]),
            else:
                print ("\n"+"|    "*lev + "%s in {%s}:") % (var.name, reduce(lambda x,y:x+", "+y, inset)),
            printTree0(branch, classvar, lev+1)


def printTree(tree):
    printTree0(tree.tree, tree.classVar, 0)
    print


Is it possible to "convert" it into the needed (what-if) format with C4.5?

Thank you one more time,
Oleczek


Re: Export big tree and rules

Postby oleczek » Tue Mar 20, 2012 22:05

I am stuck again. Please help me solve my problem. I guess it's simple, but I am not too much into python.

Code shows snippets:
Code: Select all
#I am learning the tree:
m = "8"
lrn = orange.C45Learner()
lrn.commandline("-g -m "+m+" -s")
tree = lrn(finaldata)


It works OK, I can display it using default widget (tree with pipes | ).

For example:
a < 2
| b > 3 : class_x
| c <= 3 : class_y


Thanks to your help from previous posts, now I am able to receive output:

a < 2 and b > 3 : class_x
c <= 3 : class_y

But I need this to be "rewinded" one level up, to contain the parent branch (aka Cut). But it starts from the Leaf.

In other words - I need full rules for every possible situation (probably ending with Leaf, not Cut).

So I would love to have this:

a < 2 and b > 3 : class_x
a < 2 and b <= 3: class_y

I am currently learning the tree as shown in the example above. Finally I use three functions (mentioned in the previous post). I have modified them, overwriting the originals:

This is how I call it first:
Code: Select all
_printTreeC45(tree)


Then it calls:

Code: Select all
def _printTreeC45(tree):
        print _c45_printRule0(tree.tree, tree.class_var, 0)


Which refers to:

Code: Select all
def _c45_printRule0(node, classvar, lev):
        var = node.tested
        str_ = ""
        if node.node_type == 0:
                str_ += " klasa: %s (%.1f)" % (classvar.values[int(node.leaf)], node.items)
                str_ += "\n\n"
        else:
                for i, branch in enumerate(node.branch):
                        if not branch.node_type: # shows leafs
                                str_ += _c45_showBranch(node, classvar, lev, i)
                for i, branch in enumerate(node.branch): #shows cuts (the first ones)
                        if branch.node_type:
                                str_ += _c45_showBranch(node, classvar, lev, i)     
        return str_


Finally, _c45_showBranch is:

Code: Select all
def _c45_showBranch(node, classvar, lev, i):
        var = node.tested
        str_ = ""
        str_ += "%s %s %.1f and " % (var.name, ["<=", ">"][i], node.cut)
        str_ += _c45_printRule0(node.branch[i], classvar, lev + 1)
        return str_


I am trying to make it work for so long, but I guess I am missing something.

Thank you for your help!

All best,
Oleczek

Re: Export big tree and rules

Postby oleczek » Thu Mar 22, 2012 17:47

Ok, got the solution. Sharing:

Code: Select all
def showCondition(i, node):
        return "%s %s %.5f" % (node.tested.name, ["<=",">"][i], node.cut)

def showDecision(node,classvar):
        return "%s (%.1f)" % (classvar.values[int(node.leaf)], node.items)

def showRule(leaf,path,classvar):
        condition = " and ".join([showCondition(i, node) for i, node in path])
        decision = showDecision(leaf,classvar)
        return condition + " : " + decision

def printRules0(node, classvar, path):
        if node.node_type == 0:
                print showRule(node,path,classvar)
        else:
                for i, branch in enumerate(node.branch):
                        printRules0(branch, classvar, path + [(i,node)])

def printRules(tree):
        printRules0(tree.tree, tree.class_var, [])


call printRules(tree) to start

Regards,
Oleczek


Return to Questions & Support



cron