source: orange/Orange/OrangeWidgets/Classify/OWCN2.py @ 11287:92efd54a02fd

Revision 11287:92efd54a02fd, 13.4 KB checked in by Ales Erjavec <ales.erjavec@…>, 15 months ago (diff)

New style meta descriptions for some widgets.

Needed for intersphinx documentation discovery.

Line 
1"""
2<name>CN2</name>
3<description>Rule-based (CN2) learner/classifier.</description>
4<icon>icons/CN2.svg</icon>
5<contact>Ales Erjavec (ales.erjavec(@at@)fri.uni-lj.si)</contact>
6<priority>300</priority>
7"""
8from OWWidget import *
9import OWGUI, orange, orngCN2, sys
10
11from orngWrap import PreprocessedLearner
12
13NAME = "CN2"
14
15DESCRIPTION = "Rule-based (CN2) learner/classifier"
16
17AUTHOR = "Ales Erjavec"
18
19PRIORITY = 300
20
21ICON = "icons/CN2.svg"
22
23# Sphinx documentation label reference
24HELP_REF = "CN2 Rules"
25
26INPUTS = (
27    dict(name="Data", type=ExampleTable, handler="dataset",
28         doc="Training data set",
29         id="train-data"),
30
31    dict(name="Preprocess", type=PreprocessedLearner,
32         handler="setPreprocessor",
33         doc="Data preprocessor",
34         id="preprocessor")
35)
36
37OUTPUTS = (
38    dict(name="Learner", type=orange.Learner,
39         doc="A CN2 Rules learner instance",
40         id="learner"),
41
42    dict(name="Classifier", type=orange.Classifier,
43         doc="A rule classifier induced from given training data.",
44         id="classifier"),
45
46    dict(name="Unordered CN2 Classifier", type=orngCN2.CN2UnorderedClassifier,
47         doc="Same as 'Classifier'",
48         id="unordered-cn2-classifier")
49)
50
51
52class CN2ProgressBar(orange.ProgressCallback):
53    def __init__(self, widget, start=0.0, end=0.0):
54        self.start = start
55        self.end = end
56        self.widget = widget
57        orange.ProgressCallback.__init__(self)
58    def __call__(self,value,a):
59        self.widget.progressBarSet(100*(self.start+(self.end-self.start)*value))
60
61class OWCN2(OWWidget):
62    settingsList=["name", "QualityButton", "CoveringButton", "m",
63                  "MaxRuleLength", "useMaxRuleLength",
64                  "MinCoverage", "BeamWidth", "Alpha", "Weight", "stepAlpha"]
65    callbackDeposit=[]
66    def __init__(self, parent=None, signalManager=None):
67        OWWidget.__init__(self,parent,signalManager,"CN2", wantMainArea = 0, resizingEnabled = 0)
68
69        self.inputs = [("Data", ExampleTable, self.dataset), ("Preprocess", PreprocessedLearner, self.setPreprocessor)]
70        self.outputs = [("Learner", orange.Learner),("Classifier",orange.Classifier),("Unordered CN2 Classifier", orngCN2.CN2UnorderedClassifier)]
71        self.QualityButton = 0
72        self.CoveringButton = 0
73        self.Alpha = 0.05
74        self.stepAlpha = 0.2
75        self.BeamWidth = 5
76        self.MinCoverage = 0
77        self.MaxRuleLength = 0
78        self.useMaxRuleLength = False
79        self.Weight = 0.9
80        self.m = 2
81        self.name = "CN2 rules"
82        self.loadSettings()
83
84        self.data=None
85        self.preprocessor = None
86
87        ##GUI
88        labelWidth = 150
89        self.learnerName = OWGUI.lineEdit(self.controlArea, self, "name", box="Learner/classifier name", tooltip="Name to be used by other widgets to identify the learner/classifier")
90        #self.learnerName.setText(self.name)
91        OWGUI.separator(self.controlArea)
92
93        self.ruleQualityBG = OWGUI.widgetBox(self.controlArea, "Rule quality estimation")
94        self.ruleQualityBG.buttons = []
95
96        OWGUI.separator(self.controlArea)
97        self.ruleValidationGroup = OWGUI.widgetBox(self.controlArea, "Pre-prunning (LRS)")
98
99        OWGUI.separator(self.controlArea)
100        OWGUI.spin(self.controlArea, self, "BeamWidth", 1, 100, box="Beam width", tooltip="The width of the search beam\n(number of rules to be specialized)")
101
102        OWGUI.separator(self.controlArea)
103        self.coveringAlgBG = OWGUI.widgetBox(self.controlArea, "Covering algorithm")
104        self.coveringAlgBG.buttons = []
105
106        """
107        self.ruleQualityBG=OWGUI.radioButtonsInBox(self.ruleQualityGroup, self, "QualityButton",
108                            btnLabels=["Laplace","m-estimate","WRACC"],
109                            box="Rule quality", callback=self.qualityButtonPressed,
110                            tooltips=["Laplace rule evaluator", "m-estimate rule evaluator",
111                            "WRACC rule evaluator"])
112        self.mSpin=Spin=OWGUI.spin(self.ruleQualityGroup, self, "m", 0, 100, label="m",
113                orientation="horizontal", labelWidth=labelWidth-100, tooltip="m value for m estimate rule evaluator")
114        """
115
116        b1 = QRadioButton("Laplace", self.ruleQualityBG); self.ruleQualityBG.layout().addWidget(b1)
117        g = OWGUI.widgetBox(self.ruleQualityBG, orientation = "horizontal");
118        b2 = QRadioButton("m-estimate", g)
119        g.layout().addWidget(b2)
120        self.mSpin = OWGUI.doubleSpin(g,self,"m",0,100)
121        b3 = QRadioButton("EVC", self.ruleQualityBG)
122        self.ruleQualityBG.layout().addWidget(b3)
123        b4 = QRadioButton("WRACC", self.ruleQualityBG)
124        self.ruleQualityBG.layout().addWidget(b4)
125        self.ruleQualityBG.buttons = [b1, b2, b3, b4]
126
127        for i, button in enumerate([b1, b2, b3, b4]):
128            self.connect(button, SIGNAL("clicked()"), lambda v=i: self.qualityButtonPressed(v))
129
130        OWGUI.doubleSpin(self.ruleValidationGroup, self, "Alpha", 0, 1,0.001, label="Alpha (vs. default rule)",
131                orientation="horizontal", labelWidth=labelWidth,
132                tooltip="Required significance of the difference between the class distribution on all example and covered examples")
133        OWGUI.doubleSpin(self.ruleValidationGroup, self, "stepAlpha", 0, 1,0.001, label="Stopping Alpha (vs. parent rule)",
134                orientation="horizontal", labelWidth=labelWidth,
135                tooltip="Required significance of each specialization of a rule.")
136        OWGUI.spin(self.ruleValidationGroup, self, "MinCoverage", 0, 100,label="Minimum coverage",
137                orientation="horizontal", labelWidth=labelWidth, tooltip=
138                "Minimum number of examples a rule must\ncover (use 0 for not setting the limit)")
139        OWGUI.checkWithSpin(self.ruleValidationGroup, self, "Maximal rule length", 0, 100, "useMaxRuleLength", "MaxRuleLength", labelWidth=labelWidth,
140                            tooltip="Maximal number of conditions in the left\npart of the rule (use 0 for don't care)")
141
142        """
143        self.coveringAlgBG=OWGUI.radioButtonsInBox(self.coveringAlgGroup, self, "CoveringButton",
144                            btnLabels=["Exclusive covering ","Weighted Covering"],
145                            tooltips=["Each example will only be used once\n for the construction of a rule",
146                                      "Examples can take part in the construction\n of many rules(CN2-SD Algorithm)"],
147                            box="Covering algorithm", callback=self.coveringAlgButtonPressed)
148        self.weightSpin=OWGUI.doubleSpin(self.coveringAlgGroup, self, "Weight",0, 0.95,0.05,label= "Weight",
149                orientation="horizontal", labelWidth=labelWidth, tooltip=
150                "Multiplication constant by which the weight of\nthe example will be reduced")
151        """
152
153        B1 = QRadioButton("Exclusive covering", self.coveringAlgBG); self.coveringAlgBG.layout().addWidget(B1)
154        g = OWGUI.widgetBox(self.coveringAlgBG, orientation = "horizontal")
155        B2 = QRadioButton("Weighted covering", g); g.layout().addWidget(B2)
156        self.coveringAlgBG.buttons = [B1, B2]
157        self.weightSpin=OWGUI.doubleSpin(g,self,"Weight",0,0.95,0.05)
158
159        for i, button in enumerate([B1, B2]):
160            self.connect(button, SIGNAL("clicked()"), lambda v=i: self.coveringAlgButtonPressed(v))
161
162        OWGUI.separator(self.controlArea)
163        self.btnApply = OWGUI.button(self.controlArea, self, "&Apply", callback=self.applySettings, default=True)
164
165        self.Alpha=float(self.Alpha)
166        self.stepAlpha=float(self.stepAlpha)
167        self.Weight=float(self.Weight)
168
169        #self.ruleQualityBG.buttons[self.QualityButton].setChecked(1)
170        self.qualityButtonPressed(self.QualityButton)
171        self.coveringAlgButtonPressed(self.CoveringButton)
172        self.resize(100,100)
173        self.setLearner()
174
175    def sendReport(self):
176        self.reportSettings("Learning parameters",
177                            [("Rule quality estimation", ["Laplace", "m-estimate with m=%.2f" % self.m, "WRACC"][self.QualityButton]),
178                             ("Pruning alpha (vs. default rule)", "%.3f" % self.Alpha),
179                             ("Stopping alpha (vs. parent rule)", "%.3f" % self.stepAlpha),
180                             ("Minimum coverage", "%.3f" % self.MinCoverage),
181                             ("Maximal rule length", self.MaxRuleLength if self.useMaxRuleLength else "unlimited"),
182                             ("Beam width", self.BeamWidth),
183                             ("Covering", ["Exclusive", "Weighted with a weight of %.2f" % self.Weight][self.CoveringButton])])
184        self.reportData(self.data)
185
186    def setLearner(self):
187        if hasattr(self, "btnApply"):
188            self.btnApply.setFocus()
189        #progress bar
190        self.progressBarInit()
191
192        #learner / specific handling in case of EVC learning (completely different type of class)
193        if self.useMaxRuleLength:
194            maxRuleLength = self.MaxRuleLength
195        else:
196            maxRuleLength = -1
197       
198        if self.QualityButton == 2:
199            self.learner=orngCN2.CN2EVCUnorderedLearner(width=self.BeamWidth, rule_sig=self.Alpha, att_sig=self.stepAlpha,
200                                                        min_coverage = self.MinCoverage, max_rule_complexity = maxRuleLength)
201            if self.preprocessor:
202                self.learner = self.preprocessor.wrapLearner(self.learner)
203            self.learner.name = self.name
204#            self.learner.progressCallback=CN2ProgressBar(self)
205            self.send("Learner",self.learner)
206        else:
207            self.learner=orngCN2.CN2UnorderedLearner()
208            self.learner.name = self.name
209#            self.learner.progressCallback=CN2ProgressBar(self)
210#            self.send("Learner",self.learner)
211
212            ruleFinder=orange.RuleBeamFinder()
213            if self.QualityButton==0:
214                ruleFinder.evaluator=orange.RuleEvaluator_Laplace()
215            elif self.QualityButton==1:
216                ruleFinder.evaluator=orngCN2.mEstimate(self.m)
217            elif self.QualityButton==3:
218                ruleFinder.evaluator=orngCN2.WRACCEvaluator()
219
220
221            ruleFinder.ruleStoppingValidator=orange.RuleValidator_LRS(alpha=self.stepAlpha,
222                        min_coverage=self.MinCoverage, max_rule_complexity=maxRuleLength)
223            ruleFinder.validator=orange.RuleValidator_LRS(alpha=self.Alpha,
224                        min_coverage=self.MinCoverage, max_rule_complexity=maxRuleLength)
225            ruleFinder.ruleFilter=orange.RuleBeamFilter_Width(width=self.BeamWidth)
226            self.learner.ruleFinder=ruleFinder
227
228            if self.CoveringButton==0:
229                self.learner.coverAndRemove=orange.RuleCovererAndRemover_Default()
230            elif self.CoveringButton==1:
231                self.learner.coverAndRemove=orngCN2.CovererAndRemover_multWeights(mult=self.Weight)
232               
233            if self.preprocessor:
234                self.learner = self.preprocessor.wrapLearner(self.learner)
235            self.learner.name = self.name
236            self.send("Learner", self.learner)
237
238        self.classifier=None
239        self.error()
240        if self.data:
241            oldDomain = orange.Domain(self.data.domain)
242            learnData = orange.ExampleTable(oldDomain, self.data)
243            self.learner.progressCallback=CN2ProgressBar(self)
244            self.classifier=self.learner(learnData)
245            self.learner.progressCallback=None
246            self.classifier.name=self.name
247            for r in self.classifier.rules:
248                r.examples = orange.ExampleTable(oldDomain, r.examples)
249            self.classifier.examples = orange.ExampleTable(oldDomain, self.classifier.examples)
250            self.classifier.setattr("data",self.classifier.examples)
251            self.error("")
252##            except orange.KernelException, (errValue):
253##                self.classifier=None
254##                self.error(errValue)
255##            except Exception:
256##                self.classifier=None
257##                if not self.data.domain.classVar:
258##                    self.error("Classless domain.")
259##                elif self.data.domain.classVar.varType == orange.VarTypes.Continuous:
260##                    self.error("CN2 can learn only from discrete class.")
261##                else:
262##                    self.error("Unknown error")
263        self.send("Classifier", self.classifier)
264        self.send("Unordered CN2 Classifier", self.classifier)
265        self.progressBarFinished()
266
267    def dataset(self, data):
268        #self.data=data
269        self.data = self.isDataWithClass(data, orange.VarTypes.Discrete, checkMissing=True) and data or None
270        self.setLearner()
271       
272    def setPreprocessor(self, pp):
273        self.preprocessor = pp
274        self.setLearner()
275
276    def qualityButtonPressed(self, id=0):
277        self.QualityButton = id
278        for i in range(len(self.ruleQualityBG.buttons)):
279            self.ruleQualityBG.buttons[i].setChecked(id == i)
280        self.mSpin.control.setEnabled(id == 1)
281        self.coveringAlgBG.setEnabled(not id == 2)
282
283    def coveringAlgButtonPressed(self,id=0):
284        self.CoveringButton = id
285        for i in range(len(self.coveringAlgBG.buttons)):
286            self.coveringAlgBG.buttons[i].setChecked(id == i)
287        self.weightSpin.control.setEnabled(id == 1)
288
289    def applySettings(self):
290        self.setLearner()
291
292if __name__=="__main__":
293    app=QApplication(sys.argv)
294    w=OWCN2()
295    #w.dataset(orange.ExampleTable("titanic.tab"))
296    w.dataset(orange.ExampleTable("titanic.tab"))
297    w.show()
298    app.exec_()
299    w.saveSettings()
Note: See TracBrowser for help on using the repository browser.