source: orange/Orange/OrangeWidgets/Regression/OWSVMRegression.py @ 11765:1546cd04481b

Revision 11765:1546cd04481b, 11.4 KB checked in by Ales Erjavec <ales.erjavec@…>, 5 months ago (diff)

Fixed widget layouts.

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