Commits

Aleš Erjavec committed d7a63c6

Separated the C parameter for nu-SVR and Epsilon-SVR. Fixed parameter search accordingly. More precise GUI controls.

Comments (0)

Files changed (1)

Orange/OrangeWidgets/Regression/OWSVMRegression.py

 from Orange.classification import svm
 
 class OWSVMRegression(OWSVM):
+    settingsList = OWSVM.settingsList + ["C_epsilon", "C_nu"]
+
     def __init__(self, parent=None, signalManager=None, title="SVM Regression"):
         OWWidget.__init__(self, parent, signalManager, title, wantMainArea=False)
-        
+
         self.inputs=[("Data", Orange.data.Table, self.setData), 
                      ("Preprocess", PreprocessedLearner, self.setPreprocessor)]
-        
+
         self.outputs=[("Learner", orange.Learner, Default),
                       ("Predictor", orange.Classifier, Default),
                       ("Support Vectors", Orange.data.Table)]
         self.gamma = 0.0
         self.coef0 = 0.0
         self.degree = 3
-        self.C = 1.0
+        self.C_epsilon = 1.0
+        self.C_nu = 1.0
         self.p = 0.1
         self.eps = 1e-3
         self.nu = 0.5
         self.shrinking = 1
-        self.probability=1
-        self.useNu=0
-        self.nomogram=0
-        self.normalization=1
+        self.probability = 1
+        self.useNu = 0
+        self.nomogram = 0
+        self.normalization = 1
         self.data = None
-        self.selFlag=False
+        self.selFlag = False
         self.preprocessor = None
         self.name = "SVM Regression"
-        
+
         self.loadSettings()
 
-        
-        OWGUI.lineEdit(self.controlArea, self, 'name', box='Learner/predictor Name',
+        OWGUI.lineEdit(self.controlArea, self, 'name',
+                       box='Learner/predictor Name',
                        tooltip='Name to be used by other widgets to identify your learner/predictor.')
         OWGUI.separator(self.controlArea)
 
         b = OWGUI.radioButtonsInBox(self.controlArea, self, "useNu", [], 
-                                    box="SVM Type", 
-                                    orientation = QGridLayout(), 
+                                    box="SVM Type",
+                                    orientation = QGridLayout(),
                                     addSpace=True)
-        
+
         # Epsilon SVR
         b.layout().addWidget(OWGUI.appendRadioButton(b, self, 
                                                 "useNu", u"ε-SVR",
                              0, 0, Qt.AlignLeft)
         
         b.layout().addWidget(QLabel("Cost (C)", b), 0, 1, Qt.AlignRight)
-        b.layout().addWidget(OWGUI.doubleSpin(b, self, "C", 0.5, 512.0, 0.5, 
-                          addToLayout=False, 
-                          callback=lambda *x: self.setType(0), 
+        b.layout().addWidget(OWGUI.doubleSpin(b, self, "C_epsilon", 0.1, 512.0, 0.1,
+                          decimals=2,
+                          addToLayout=False,
+                          callback=lambda *x: self.setType(0),
                           alignment=Qt.AlignRight,
                           tooltip="Cost for out of epsilon training points."),
                           0, 2)
-        
+    
         b.layout().addWidget(QLabel(u"Loss Epsilon (ε)", b), 1, 1, Qt.AlignRight)
         b.layout().addWidget(OWGUI.doubleSpin(b, self, "p", 0.05, 1.0, 0.05,
                                       addToLayout=False,
                                       tooltip="Epsilon bound (all points inside this interval are not penalized)."
                                       ),
                              1, 2)
-        
+
         # Nu SVR
-        b.layout().addWidget(OWGUI.appendRadioButton(b, self, 
+        b.layout().addWidget(OWGUI.appendRadioButton(b, self,
                                                 "useNu", u"ν-SVR",
                                                 tooltip="Nu SVR",
                                                 addToLayout=False),
                              2, 0, Qt.AlignLeft)
         
-        b.layout().addWidget(QLabel("Cost (C)", b), 
+        b.layout().addWidget(QLabel("Cost (C)", b),
                              2, 1, Qt.AlignRight)
-        b.layout().addWidget(OWGUI.doubleSpin(b, self, "C", 0.5, 512.0, 0.5, 
-                        addToLayout=False, 
-                        callback=lambda *x: self.setType(0), 
+        b.layout().addWidget(OWGUI.doubleSpin(b, self, "C_nu", 0.1, 512.0, 0.1,
+                        decimals=2, 
+                        addToLayout=False,
+                        callback=lambda *x: self.setType(1),
                         alignment=Qt.AlignRight,
                         tooltip="Cost for out of epsilon training points."),
                         2, 2)
         
         b.layout().addWidget(QLabel(u"Complexity bound (\u03bd)", b),
                              3, 1, Qt.AlignRight)
-        b.layout().addWidget(OWGUI.doubleSpin(b, self, "nu", 0.1, 1.0, 0.1,
+        b.layout().addWidget(OWGUI.doubleSpin(b, self, "nu", 0.05, 1.0, 0.05,
                         tooltip="Lower bound on the ratio of support vectors",
                         addToLayout=False, 
                         callback=lambda *x: self.setType(1), 
         OWGUI.separator(b)
         self.gcd = OWGUI.widgetBox(b, orientation="horizontal")
         self.leg = OWGUI.doubleSpin(self.gcd, self, "gamma", 0.0, 10.0, 0.0001,
+                                    decimals=5,
                                     label="  g: ", orientation="horizontal",
                                     callback=self.changeKernel, 
                                     alignment=Qt.AlignRight)
         self.paramButton.setDisabled(not self.data)
         
     def applySettings(self):
-        learner = svm.SVMLearner(svm_type=svm.SVMLearner.Nu_SVR 
-                                          if self.useNu else
-                                          svm.SVMLearner.Epsilon_SVR,
-                                 C=self.C,
+        if self.useNu:
+            svm_type = svm.SVMLearner.Nu_SVR
+            C = self.C_nu
+        else:
+            svm_type = svm.SVMLearner.Epsilon_SVR
+            C = self.C_epsilon
+
+        learner = svm.SVMLearner(svm_type=svm_type,
+                                 C=C,
                                  p=self.p,
                                  nu=self.nu,
                                  kernel_type=self.kernel_type,
         support_vectors = None
         if self.preprocessor:
             learner = self.preprocessor.wrapLearner(learner)
-        
+
         if self.data is not None:
             predictor = learner(self.data)
             support_vectors = predictor.support_vectors
             predictor.name = self.name
-            
+
         self.send("Learner", learner)
         self.send("Predictor", predictor)
         self.send("Support Vectors", support_vectors)
-        
+
     def sendReport(self):
         if self.useNu:
             settings = [("Type", "Nu SVM regression"),
-                        ("Cost (C)", "%.3f" % self.C),
-                        ("Complexity bound (nu)", "%.2f" % self.nu)]
+                        ("Cost (C)", "%.3f" % self.C_nu),
+                        ("Complexity bound (nu)", "%.3f" % self.nu)]
         else:
             settings = [("Type", "Epsilon SVM regression"),
-                        ("Cost (C)", "%.3f" % self.C),
+                        ("Cost (C)", "%.3f" % self.C_epsilon),
                         ("Loss epsilon", "%.3f" % self.p)]
-            
+
         if self.kernel_type == 0:
             kernel = "Linear, x.y"
         elif self.kernel_type == 1:
             kernel = "RBF, e<sup>-%.4f*(x-y).(x-y)</sup>" % self.gamma
         else:
             kernel = "Sigmoid, tanh(%.4f*x.y+%.4f)" % (self.gamma, self.coef0)
-            
+
         settings.extend([("Kernel", kernel),
                          ("Tolerance", self.eps),
                          ("Normalize data", OWGUI.YesNo[self.normalization])])
-        
-            
+
         self.reportSettings("Settings", settings)
         self.reportData(self.data)
-            
-        
+
+    def search_(self):
+        learner = orngSVM.SVMLearner()
+        for attr in ("name", "kernel_type", "degree", "shrinking", "probability", "normalization"):
+            setattr(learner, attr, getattr(self, attr))
+
+        for attr in ("gamma", "coef0", "p", "eps", "nu"):
+            setattr(learner, attr, float(getattr(self, attr)))
+
+        if self.useNu:
+            learner.svm_type = learner.Nu_SVR
+            learner.C = self.C_nu
+        else:
+            learner.svm_type = learner.Epsilon_SVR
+            learner.C = self.C_epsilon
+
+        params = []        
+        params.append("C")
+        if self.kernel_type in [1, 2]:
+            params.append("gamma")
+        if self.kernel_type == 1:
+            params.append("degree")
+        try:
+            learner.tuneParameters(self.data, params, 4, verbose=0,
+                                   progressCallback=self.progres)
+        except UnhandledException:
+            pass
+        for param in params:
+            setattr(self, param, getattr(learner, param))
+
+        if self.useNu:
+            self.C_nu = learner.C
+        else:
+            self.C_epsilon = learner.C
+
+        self.finishSearch()
+
 if __name__ == "__main__":
     app = QApplication([])
     w = OWSVMRegression()
     w.show()
     data = Orange.data.Table("housing")
     w.setData(data)
-    app.exec_()
+    app.exec_()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.