source: orange/docs/extend-widgets/rst/OWLearningCurveA.py @ 11593:6edc44eb9655

Revision 11593:6edc44eb9655, 7.9 KB checked in by Ales Erjavec <ales.erjavec@…>, 10 months ago (diff)

Updated Widget development tutorial.

Line 
1"""
2<name>Learning Curve (A)</name>
3<description>Takes a data set and a set of learners and shows a learning curve in a table</description>
4<icon>icons/LearningCurve.svg</icon>
5<priority>1000</priority>
6"""
7
8import Orange
9
10from OWWidget import *
11import OWGUI
12
13class OWLearningCurveA(OWWidget):
14    settingsList = ["folds", "steps", "scoringF", "commitOnChange"]
15
16    def __init__(self, parent=None, signalManager=None):
17        OWWidget.__init__(self, parent, signalManager, 'LearningCurveA')
18
19        self.inputs = [("Data", Orange.data.Table, self.dataset),
20                       ("Learner", Orange.core.Learner, self.learner,
21                        Multiple)]
22
23        self.folds = 5     # cross validation folds
24        self.steps = 10    # points in the learning curve
25        self.scoringF = 0  # scoring function
26        self.commitOnChange = 1 # compute curve on any change of parameters
27        self.loadSettings()
28        self.setCurvePoints() # sets self.curvePoints, self.steps equidistant points from 1/self.steps to 1
29        self.scoring = [("Classification Accuracy", Orange.evaluation.scoring.CA),
30                        ("AUC", Orange.evaluation.scoring.AUC),
31                        ("BrierScore", Orange.evaluation.scoring.Brier_score),
32                        ("Information Score", Orange.evaluation.scoring.IS),
33                        ("Sensitivity", Orange.evaluation.scoring.Sensitivity),
34                        ("Specificity", Orange.evaluation.scoring.Specificity)]
35        self.learners = [] # list of current learners from input channel, tuples (id, learner)
36        self.data = None   # data on which to construct the learning curve
37        self.curves = []   # list of evaluation results (one per learning curve point)
38        self.scores = []   # list of current scores, learnerID:[learner scores]
39
40        # GUI
41        box = OWGUI.widgetBox(self.controlArea, "Info")
42        self.infoa = OWGUI.widgetLabel(box, 'No data on input.')
43        self.infob = OWGUI.widgetLabel(box, 'No learners.')
44
45        OWGUI.separator(self.controlArea)
46
47        box = OWGUI.widgetBox(self.controlArea, "Evaluation Scores")
48        scoringNames = [x[0] for x in self.scoring]
49        OWGUI.comboBox(box, self, "scoringF", items=scoringNames,
50                       callback=self.computeScores)
51
52        OWGUI.separator(self.controlArea)
53
54        box = OWGUI.widgetBox(self.controlArea, "Options")
55        OWGUI.spin(box, self, 'folds', 2, 100, step=1,
56                   label='Cross validation folds:  ',
57                   callback=lambda: self.computeCurve(self.commitOnChange))
58        OWGUI.spin(box, self, 'steps', 2, 100, step=1,
59                   label='Learning curve points:  ',
60                   callback=[self.setCurvePoints,
61                             lambda: self.computeCurve(self.commitOnChange)])
62        OWGUI.checkBox(box, self, 'commitOnChange', 'Apply setting on any change')
63        self.commitBtn = OWGUI.button(box, self, "Apply Setting",
64                                      callback=self.computeCurve, disabled=1)
65
66        OWGUI.rubber(self.controlArea)
67
68        # table widget
69        self.table = OWGUI.table(self.mainArea,
70                                 selectionMode=QTableWidget.NoSelection)
71
72        self.resize(500,200)
73
74    ##############################################################################   
75    # slots: handle input signals
76
77    def dataset(self, data):
78        if data:
79            self.infoa.setText('%d instances in input data set' % len(data))
80            self.data = data
81            if (len(self.learners)):
82                self.computeCurve()
83        else:
84            self.infoa.setText('No data on input.')
85            self.curves = []
86            self.scores = []
87        self.commitBtn.setEnabled(self.data is not None)
88
89    def learner(self, learner, id=None):
90        ids = [x[0] for x in self.learners]
91        if not learner: # remove a learner and corresponding results
92            if not ids.count(id):
93                return # no such learner, removed before
94            indx = ids.index(id)
95            for i in range(self.steps):
96                self.curves[i].remove(indx)
97            del self.scores[indx]
98            del self.learners[indx]
99            self.setTable()
100        else:
101            if ids.count(id): # update (already seen a learner from this source)
102                indx = ids.index(id)
103                self.learners[indx] = (id, learner)
104                if self.data:
105                    curve = self.getLearningCurve([learner])
106                    score = [self.scoring[self.scoringF][1](x)[0] for x in curve]
107                    self.scores[indx] = score
108                    for i in range(self.steps):
109                        self.curves[i].add(curve[i], 0, replace=indx)
110            else: # add new learner
111                self.learners.append((id, learner))
112                if self.data:
113                    curve = self.getLearningCurve([learner])
114                    score = [self.scoring[self.scoringF][1](x)[0] for x in curve]
115                    self.scores.append(score)
116                    if len(self.curves):
117                        for i in range(self.steps):
118                            self.curves[i].add(curve[i], 0)
119                    else:
120                        self.curves = curve
121        if len(self.learners):
122            self.infob.setText("%d learners on input." % len(self.learners))
123        else:
124            self.infob.setText("No learners.")
125        self.commitBtn.setEnabled(len(self.learners))
126
127        if self.data:
128            self.setTable()
129
130    ##############################################################################   
131    # learning curve table, callbacks
132
133    # recomputes the learning curve
134    def computeCurve(self, condition=1):
135        if condition:
136            learners = [x[1] for x in self.learners]
137            self.curves = self.getLearningCurve(learners)
138            self.computeScores()
139
140    def computeScores(self):           
141        self.scores = [[] for i in range(len(self.learners))]
142        for x in self.curves:
143            for (i,s) in enumerate(self.scoring[self.scoringF][1](x)):
144                self.scores[i].append(s)
145        self.setTable()
146
147    def getLearningCurve(self, learners):   
148        pb = OWGUI.ProgressBar(self, iterations=self.steps*self.folds)
149        curve = Orange.evaluation.testing.learning_curve_n(
150            learners, self.data, folds=self.folds,
151            proportions=self.curvePoints, callback=pb.advance)
152        pb.finish()
153        return curve
154
155    def setCurvePoints(self):
156        self.curvePoints = [(x + 1.)/self.steps for x in range(self.steps)]
157
158    def setTable(self):
159        self.table.setColumnCount(0)
160        self.table.setColumnCount(len(self.learners))
161        self.table.setRowCount(self.steps)
162
163        # set the headers
164        self.table.setHorizontalHeaderLabels([l.name for i,l in self.learners])
165        self.table.setVerticalHeaderLabels(["%4.2f" % p for p in self.curvePoints])
166
167        # set the table contents
168        for l in range(len(self.learners)):
169            for p in range(self.steps):
170                OWGUI.tableItem(self.table, p, l, "%7.5f" % self.scores[l][p])
171
172        for i in range(len(self.learners)):
173            self.table.setColumnWidth(i, 80)
174
175
176if __name__=="__main__":
177    appl = QApplication(sys.argv)
178    ow = OWLearningCurveA()
179    ow.show()
180   
181    l1 = Orange.classification.bayes.NaiveLearner()
182    l1.name = 'Naive Bayes'
183    ow.learner(l1, 1)
184
185    data = Orange.data.Table('iris.tab')
186    ow.dataset(data)
187
188    l2 = Orange.classification.bayes.NaiveLearner()
189    l2.name = 'Naive Bayes (m=10)'
190    l2.estimatorConstructor = Orange.statistics.estimate.M(m=10)
191    l2.conditionalEstimatorConstructor = \
192        Orange.statistics.estimate.ConditionalByRows(
193            estimatorConstructor = Orange.statistics.estimate.M(m=10))
194    ow.learner(l2, 2)
195
196    l4 = Orange.classification.tree.TreeLearner(minSubset=2)
197    l4.name = "Decision Tree"
198    ow.learner(l4, 4)
199
200#    ow.learner(None, 1)
201#    ow.learner(None, 2)
202#    ow.learner(None, 4)
203
204    appl.exec_()
Note: See TracBrowser for help on using the repository browser.