source: orange/Orange/OrangeWidgets/Regression/OWSVMRegression.py @ 11096:cf7d2ae9d22b

Revision 11096:cf7d2ae9d22b, 11.4 KB checked in by Ales Erjavec <ales.erjavec@…>, 19 months ago (diff)

Added new svg icons for the widgets/categories.

Line 
1# coding=utf-8
2"""
3<name>SVM Regression</name>
4<description>Support Vector Machine Regression.</description>
5<icon>icons/SVMRegression.svg</icon>
6<contact>Ales Erjavec (ales.erjavec(@at@)fri.uni-lj.si)</contact>
7<priority>100</priority>
8<keywords>Support, Vector, Machine, Regression</keywords>
9
10"""
11
12import orngSVM
13
14from OWSVM import *
15
16import Orange
17from Orange.classification import svm
18
19class OWSVMRegression(OWSVM):
20    settingsList = OWSVM.settingsList + ["C_epsilon", "C_nu"]
21
22    def __init__(self, parent=None, signalManager=None, title="SVM Regression"):
23        OWWidget.__init__(self, parent, signalManager, title, wantMainArea=False)
24
25        self.inputs=[("Data", Orange.data.Table, self.setData), 
26                     ("Preprocess", PreprocessedLearner, self.setPreprocessor)]
27
28        self.outputs=[("Learner", orange.Learner, Default),
29                      ("Predictor", orange.Classifier, Default),
30                      ("Support Vectors", Orange.data.Table)]
31
32        ##########
33        # Settings
34        ##########
35        self.kernel_type = 2
36        self.gamma = 0.0
37        self.coef0 = 0.0
38        self.degree = 3
39        self.C_epsilon = 1.0
40        self.C_nu = 1.0
41        self.p = 0.1
42        self.eps = 1e-3
43        self.nu = 0.5
44        self.shrinking = 1
45        self.probability = 1
46        self.useNu = 0
47        self.nomogram = 0
48        self.normalization = 1
49        self.data = None
50        self.selFlag = False
51        self.preprocessor = None
52        self.name = "SVM Regression"
53
54        self.loadSettings()
55
56        OWGUI.lineEdit(self.controlArea, self, 'name',
57                       box='Learner/predictor Name',
58                       tooltip='Name to be used by other widgets to identify your learner/predictor.')
59        OWGUI.separator(self.controlArea)
60
61        b = OWGUI.radioButtonsInBox(self.controlArea, self, "useNu", [], 
62                                    box="SVM Type",
63                                    orientation = QGridLayout(),
64                                    addSpace=True)
65
66        # Epsilon SVR
67        b.layout().addWidget(OWGUI.appendRadioButton(b, self, 
68                                                "useNu", u"ε-SVR",
69                                                tooltip="Epsilon SVR",
70                                                addToLayout=False),
71                             0, 0, Qt.AlignLeft)
72       
73        b.layout().addWidget(QLabel("Cost (C)", b), 0, 1, Qt.AlignRight)
74        b.layout().addWidget(OWGUI.doubleSpin(b, self, "C_epsilon", 0.1, 512.0, 0.1,
75                          decimals=2,
76                          addToLayout=False,
77                          callback=lambda *x: self.setType(0),
78                          alignment=Qt.AlignRight,
79                          tooltip="Cost for out of epsilon training points."),
80                          0, 2)
81   
82        b.layout().addWidget(QLabel(u"Loss Epsilon (ε)", b), 1, 1, Qt.AlignRight)
83        b.layout().addWidget(OWGUI.doubleSpin(b, self, "p", 0.05, 1.0, 0.05,
84                                      addToLayout=False,
85                                      callback=lambda *x: self.setType(0),
86                                      alignment=Qt.AlignRight,
87                                      tooltip="Epsilon bound (all points inside this interval are not penalized)."
88                                      ),
89                             1, 2)
90
91        # Nu SVR
92        b.layout().addWidget(OWGUI.appendRadioButton(b, self,
93                                                "useNu", u"ν-SVR",
94                                                tooltip="Nu SVR",
95                                                addToLayout=False),
96                             2, 0, Qt.AlignLeft)
97       
98        b.layout().addWidget(QLabel("Cost (C)", b),
99                             2, 1, Qt.AlignRight)
100        b.layout().addWidget(OWGUI.doubleSpin(b, self, "C_nu", 0.1, 512.0, 0.1,
101                        decimals=2, 
102                        addToLayout=False,
103                        callback=lambda *x: self.setType(1),
104                        alignment=Qt.AlignRight,
105                        tooltip="Cost for out of epsilon training points."),
106                        2, 2)
107       
108        b.layout().addWidget(QLabel(u"Complexity bound (\u03bd)", b),
109                             3, 1, Qt.AlignRight)
110        b.layout().addWidget(OWGUI.doubleSpin(b, self, "nu", 0.05, 1.0, 0.05,
111                        tooltip="Lower bound on the ratio of support vectors",
112                        addToLayout=False, 
113                        callback=lambda *x: self.setType(1), 
114                        alignment=Qt.AlignRight),
115                        3, 2)
116       
117        # Kernel
118        self.kernelBox=b = OWGUI.widgetBox(self.controlArea, "Kernel")
119        self.kernelradio = OWGUI.radioButtonsInBox(b, self, "kernel_type", 
120                                btnLabels=[u"Linear,   x∙y", 
121                                           u"Polynomial,   (g x∙y + c)^d",
122                                           u"RBF,   exp(-g|x-y|²)", 
123                                           u"Sigmoid,   tanh(g x∙y + c)"],
124                                callback=self.changeKernel)
125
126        OWGUI.separator(b)
127        self.gcd = OWGUI.widgetBox(b, orientation="horizontal")
128        self.leg = OWGUI.doubleSpin(self.gcd, self, "gamma", 0.0, 10.0, 0.0001,
129                                    decimals=5,
130                                    label="  g: ", orientation="horizontal",
131                                    callback=self.changeKernel, 
132                                    alignment=Qt.AlignRight)
133       
134        self.led = OWGUI.doubleSpin(self.gcd, self, "coef0", 0.0, 10.0, 0.0001,
135                                    label="  c: ", orientation="horizontal", 
136                                    callback=self.changeKernel, 
137                                    alignment=Qt.AlignRight)
138       
139        self.lec = OWGUI.doubleSpin(self.gcd, self, "degree", 0.0,10.0,0.5, 
140                                    label="  d: ", orientation="horizontal", 
141                                    callback=self.changeKernel, 
142                                    alignment=Qt.AlignRight)
143
144        OWGUI.separator(self.controlArea)
145       
146        self.optionsBox=b=OWGUI.widgetBox(self.controlArea, "Options", addSpace=True)
147       
148        OWGUI.doubleSpin(b,self, "eps", 0.0005, 1.0, 0.0005, 
149                         label=u"Numerical tolerance", 
150                         labelWidth = 180, 
151                         orientation="horizontal",
152                         tooltip="Numerical tolerance of termination criterion.", 
153                         alignment=Qt.AlignRight)
154
155        OWGUI.checkBox(b, self, "normalization", 
156                       label="Normalize data", 
157                       tooltip="Use data normalization")
158
159        self.paramButton = OWGUI.button(self.controlArea, self,
160                                         "Automatic parameter search", 
161                                         callback=self.parameterSearch,
162                                         tooltip="Automatically searches for parameters that optimize classifier accuracy", 
163                                         debuggingEnabled=0)
164       
165        self.paramButton.setDisabled(True)
166
167        OWGUI.button(self.controlArea, self,"&Apply", 
168                     callback=self.applySettings, 
169                     default=True)
170       
171        OWGUI.rubber(self.controlArea)
172       
173       
174        self.changeKernel()
175        self.searching=False
176        self.applySettings()
177
178    def setData(self, data=None):
179        self.data = self.isDataWithClass(data, 
180                    wantedVarType=Orange.core.VarTypes.Continuous,
181                    checkMissing=True) and data or None
182        self.paramButton.setDisabled(not self.data)
183       
184    def applySettings(self):
185        if self.useNu:
186            svm_type = svm.SVMLearner.Nu_SVR
187            C = self.C_nu
188        else:
189            svm_type = svm.SVMLearner.Epsilon_SVR
190            C = self.C_epsilon
191
192        learner = svm.SVMLearner(svm_type=svm_type,
193                                 C=C,
194                                 p=self.p,
195                                 nu=self.nu,
196                                 kernel_type=self.kernel_type,
197                                 gamma=self.gamma,
198                                 degree=self.degree,
199                                 coef0=self.coef0,
200                                 eps=self.eps,
201                                 probability=self.probability,
202                                 normalization=self.normalization,
203                                 name=self.name)
204        predictor = None
205        support_vectors = None
206        if self.preprocessor:
207            learner = self.preprocessor.wrapLearner(learner)
208
209        if self.data is not None:
210            predictor = learner(self.data)
211            support_vectors = predictor.support_vectors
212            predictor.name = self.name
213
214        self.send("Learner", learner)
215        self.send("Predictor", predictor)
216        self.send("Support Vectors", support_vectors)
217
218    def sendReport(self):
219        if self.useNu:
220            settings = [("Type", "Nu SVM regression"),
221                        ("Cost (C)", "%.3f" % self.C_nu),
222                        ("Complexity bound (nu)", "%.3f" % self.nu)]
223        else:
224            settings = [("Type", "Epsilon SVM regression"),
225                        ("Cost (C)", "%.3f" % self.C_epsilon),
226                        ("Loss epsilon", "%.3f" % self.p)]
227
228        if self.kernel_type == 0:
229            kernel = "Linear, x.y"
230        elif self.kernel_type == 1:
231            kernel = "Polynomial, (%.4f*x.y+%.4f)<sup>%.4f</sup>" % (self.gamma, self.coef0, self.degree)
232        elif self.kernel_type == 2:
233            kernel = "RBF, e<sup>-%.4f*(x-y).(x-y)</sup>" % self.gamma
234        else:
235            kernel = "Sigmoid, tanh(%.4f*x.y+%.4f)" % (self.gamma, self.coef0)
236
237        settings.extend([("Kernel", kernel),
238                         ("Tolerance", self.eps),
239                         ("Normalize data", OWGUI.YesNo[self.normalization])])
240
241        self.reportSettings("Settings", settings)
242        self.reportData(self.data)
243
244    def search_(self):
245        learner = orngSVM.SVMLearner()
246        for attr in ("name", "kernel_type", "degree", "shrinking", "probability", "normalization"):
247            setattr(learner, attr, getattr(self, attr))
248
249        for attr in ("gamma", "coef0", "p", "eps", "nu"):
250            setattr(learner, attr, float(getattr(self, attr)))
251
252        if self.useNu:
253            learner.svm_type = learner.Nu_SVR
254            learner.C = self.C_nu
255        else:
256            learner.svm_type = learner.Epsilon_SVR
257            learner.C = self.C_epsilon
258
259        params = []       
260        params.append("C")
261        if self.kernel_type in [1, 2]:
262            params.append("gamma")
263        if self.kernel_type == 1:
264            params.append("degree")
265        try:
266            learner.tuneParameters(self.data, params, 4, verbose=0,
267                                   progressCallback=self.progres)
268        except UnhandledException:
269            pass
270        for param in params:
271            setattr(self, param, getattr(learner, param))
272
273        if self.useNu:
274            self.C_nu = learner.C
275        else:
276            self.C_epsilon = learner.C
277
278        self.finishSearch()
279
280if __name__ == "__main__":
281    app = QApplication([])
282    w = OWSVMRegression()
283    w.show()
284    data = Orange.data.Table("housing")
285    w.setData(data)
286    app.exec_()
Note: See TracBrowser for help on using the repository browser.