⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 owitree.py

📁 orange源码 数据挖掘技术
💻 PY
字号:
"""
<name>Interactive Tree Builder</name>
<description>Interactive Tree Builder</description>
<icon>icons/ITree.png</icon>
<contact>Janez Demsar (janez.demsar(@at@)fri.uni-lj.si)</contact> 
<priority>50</priority>
"""
from OWWidget import *
from OWFile import *
from OWClassificationTreeViewer import *
import OWGUI, sys, orngTree

class FixedTreeLearner(orange.Learner):
    def __init__(self, classifier, name):
        self.classifier = classifier
        self.name = name

    def __call__(self, *d):
        return self.classifier

class OWITree(OWClassificationTreeViewer):
    settingsList = OWClassificationTreeViewer.settingsList + ["discretizationMethod"]
    
    def __init__(self,parent = None, signalManager = None):
        OWClassificationTreeViewer.__init__(self, parent, signalManager, 'I&nteractive Tree Builder')
        self.inputs = [("Examples", ExampleTable, self.cdata), ("Tree Learner", orange.Learner, self.learner)]
        self.outputs = [("Classified Examples", ExampleTableWithClass), ("Classifier", orange.TreeClassifier), ("Tree Learner", orange.Learner)]

        self.discretizationMethod = 0
        self.attridx = 0
        self.cutoffPoint = 0.0
        self.loadSettings()

        self.data = None
        self.treeLearner = None
        self.tree = None

        OWGUI.separator(self.space, height=40)
        box = OWGUI.widgetBox(self.space, "Split selection")
        box.setSizePolicy(QSizePolicy(QSizePolicy.Minimum , QSizePolicy.Fixed ))
#        OWGUI.widgetLabel(box, "Split By:")
        self.attrsCombo = OWGUI.comboBox(box, self, 'attridx', orientation="horizontal", callback=self.cbAttributeSelected)
        self.cutoffEdit = OWGUI.lineEdit(box, self, 'cutoffPoint', label = 'Cut off point: ', orientation='horizontal', validator=QDoubleValidator(self))
        OWGUI.button(box, self, "Split", callback=self.btnSplitClicked)

        OWGUI.separator(self.space)
        box = OWGUI.widgetBox(self.space, "Modify Tree")
        box.setSizePolicy(QSizePolicy(QSizePolicy.Minimum , QSizePolicy.Fixed ))
        self.btnPrune = OWGUI.button(box, self, "Cut", callback = self.btnPruneClicked)
        self.btnBuild = OWGUI.button(box, self, "Build", callback = self.btnBuildClicked)

        b = QVBox(self.controlArea)
        self.activateLoadedSettings()
        self.space.updateGeometry()

    def cbAttributeSelected(self):
        val = ""
        if self.data:
            attr = self.data.domain[self.attridx]
            if attr.varType == orange.VarTypes.Continuous:
                val = str(orange.Value(attr, self.basstat[attr].avg))
        self.cutoffEdit.setDisabled(not val)
        self.cutoffEdit.setText(val)

    def activateLoadedSettings(self):
        self.cbAttributeSelected()

    def updateTree(self):
        self.setTreeView()
        self.learner = FixedTreeLearner(self.tree, self.title)
#        self.send("Classified Examples", self.tree)
        self.send("Classifier", self.tree)
        self.send("Tree Learner", self.learner)

    def newTreeNode(self, data):
        node = orange.TreeNode()
        node.examples = data
        node.contingency = orange.DomainContingency(data)
        node.distribution = node.contingency.classes
        nodeLearner = self.treeLearner and getattr(self.treeLearner, "nodeLearner", None) or orange.MajorityLearner()
        node.nodeClassifier = nodeLearner(data)
        return node

    def cutNode(self, node):
        if not node:
            return
        node.branchDescriptions = node.branchSelector = node.branchSizes = node.branches = None

    def findCurrentNode(self, exhaustively=0):
        sitem = self.v.selectedItem()
        if not sitem and (1 or exhaustively):
            sitem = self.v.currentItem() or (self.v.childCount() == 1 and self.v.firstChild())
            if sitem.childCount():
                return
        return sitem and self.nodeClassDict[sitem]

    def btnSplitClicked(self):
        node = self.findCurrentNode(1)
        if not node:
            return
        
        attr = self.data.domain[self.attridx]
        if attr.varType == orange.VarTypes.Continuous:
            cutstr = str(self.cutoffEdit.text())
            if not cutstr:
                return
            cutoff = float(cutstr)

            node.branchSelector = orange.ClassifierFromVarFD(position=self.attridx, domain=self.data.domain, classVar=attr)
            node.branchSelector.transformer = orange.ThresholdDiscretizer(threshold = cutoff)
            node.branchDescriptions = ["<%5.3f" % cutoff, ">=%5.3f" % cutoff]

            cutvar = orange.EnumVariable(node.examples.domain[self.attridx].name, values = node.branchDescriptions)
            cutvar.getValueFrom = node.branchSelector
            node.branchSizes = orange.Distribution(cutvar, node.examples)
            node.branchSelector.classVar = cutvar

        else:
            node.branchSelector = orange.ClassifierFromVarFD(position=self.attridx, domain=self.data.domain, classVar=attr)
            node.branchDescriptions=node.branchSelector.classVar.values
            node.branchSizes = orange.Distribution(attr, node.examples)

        splitter = self.treeLearner and getattr(self.treeLearner, "splitter", None) or orange.TreeExampleSplitter_IgnoreUnknowns()
        node.branches = [subset and self.newTreeNode(subset) or None   for subset in splitter(node, node.examples)[0]]
        self.updateTree()

    def btnPruneClicked(self):
        self.cutNode(node = self.findCurrentNode())
        self.updateTree()

    def btnBuildClicked(self):
        node = self.findCurrentNode()
        if not node:
            return

        newtree = (self.treeLearner or orngTree.TreeLearner(storeExamples = 1))(node.examples)
        if not hasattr(newtree, "tree"):
            QMessageBox.critical( None, "Invalid Learner", "The learner on the input built a classifier which is not a tree.", QMessageBox.Ok)

        for k, v in newtree.tree.__dict__.items():
            node.setattr(k, v)
        self.updateTree()

    def cdata(self, data):
        if self.data and data and data.domain == self.data.domain and data.version == self.data.version:
            return

        self.attrsCombo.clear()

        if data and not data.domain.classVar:
            self.error("This data set has no class.")
            self.data = None
        elif data and data.domain.classVar.varType != orange.VarTypes.Discrete:
            self.error("This widget only works with discrete classes.")
            self.data = None
        else:
            self.error()
            self.data = data
        if self.data:
            for attr in data.domain.attributes:
                self.attrsCombo.insertItem(attr.name)
            self.basstat = orange.DomainBasicAttrStat(data)
#            self.attrsCombo.adjustSize()
            self.attridx = 0
            self.cbAttributeSelected()
            self.tree = orange.TreeClassifier(domain = data.domain)
            self.tree.descender = orange.TreeDescender_UnknownMergeAsBranchSizes()
            self.tree.tree = self.newTreeNode(self.data)
        else:
            self.tree = None
            self.send("Classifier", self.tree)
            self.send("Tree Learner", self.learner)
        
        self.send("Classified Examples", None)
        self.updateTree()
        self.v.setSelected(self.v.firstChild(), TRUE)

    def learner(self, learner):
        self.treeLearner = learner


if __name__ == "__main__":
    a=QApplication(sys.argv)
    owi=OWITree()

#    d = orange.ExampleTable('d:\\ai\\orange\\test\\iris')
    d = orange.ExampleTable('d:\\ai\\orange\\test\\crush')
    owi.cdata(d)

    a.setMainWidget(owi)
    owi.show()
    a.exec_loop()

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -