Commits

Aleš Erjavec committed 8ecd483

Changed (simplified) SVMClassifier constructors (and pickling).

  • Participants
  • Parent commits f27665a

Comments (0)

Files changed (3)

File source/orange/lib_learner.cpp

     if (svm_save_model_alt(buf, svm->getModel())){
     	raiseError("Error saving SVM model");
     }
-    if(svm->kernelFunc)
-        return Py_BuildValue("O(OOOsO)N", self->ob_type,
-                                    WrapOrange(svm->classVar),
+
+    return Py_BuildValue("O(OsOOO)N", self->ob_type,
+                                    WrapOrange(svm->domain),
+                                    buf.c_str(),
+                                    WrapOrange(svm->supportVectors),
+                                    WrapOrange(svm->kernelFunc),
                                     WrapOrange(svm->examples),
-                                    WrapOrange(svm->supportVectors),
-                                    buf.c_str(),
-                                    WrapOrange(svm->kernelFunc),
-                                    packOrangeDictionary(self));
-    else
-        return Py_BuildValue("O(OOOs)N", self->ob_type,
-                                    WrapOrange(svm->classVar),
-                                    WrapOrange(svm->examples),
-                                    WrapOrange(svm->supportVectors),
-                                    buf.c_str(),
                                     packOrangeDictionary(self));
   PyCATCH
 }
     if (svm_save_model_alt(buf, svm->getModel())){
         raiseError("Error saving SVM model.");
     }
-    if(svm->kernelFunc)
-        return Py_BuildValue("O(OOOsbO)N", self->ob_type,
-                                    WrapOrange(svm->classVar),
-                                    WrapOrange(svm->examples),
-                                    WrapOrange(svm->supportVectors),
-                                    buf.c_str(),
-									(char)(svm->useNonMeta? 1: 0),
-                                    WrapOrange(svm->kernelFunc),
-                                    packOrangeDictionary(self));
-    else
-        return Py_BuildValue("O(OOOsb)N", self->ob_type,
-                                    WrapOrange(svm->classVar),
-                                    WrapOrange(svm->examples),
-                                    WrapOrange(svm->supportVectors),
+
+    return Py_BuildValue("O(OsbOOO)N", self->ob_type,
+                                    WrapOrange(svm->domain),
                                     buf.c_str(),
                                     (char)(svm->useNonMeta? 1: 0),
+                                    WrapOrange(svm->supportVectors),
+                                    WrapOrange(svm->kernelFunc),
+                                    WrapOrange(svm->examples),
                                     packOrangeDictionary(self));
   PyCATCH
 }
 }
 
 
-PyObject * SVMClassifier_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) BASED_ON(ClassifierFD, "(Variable, Examples, Examples, string, [kernelFunc]) -> SVMClassifier")
-{PyTRY
-	PVariable classVar;
+PyObject * SVMClassifier_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) BASED_ON(ClassifierFD, "(Domain, model_string, supportVectors, [kernelFunc, examples]) -> SVMClassifier")
+{
+PyTRY
+	PDomain domain;
+	char*  model_string = NULL;
+	PExampleTable supportVectors;
+	PKernelFunc kernel;
 	PExampleTable examples;
-	PExampleTable supportVectors;
-	char*  model_string;
-	PKernelFunc kernel;
+
 	if (PyArg_ParseTuple(args, ""))
 		return WrapNewOrange(mlnew TSVMClassifier(), type);
+
 	PyErr_Clear();
-	
-	if (!PyArg_ParseTuple(args, "O&O&O&s|O&:__new__", cc_Variable, &classVar, ccn_ExampleTable, &examples, cc_ExampleTable, &supportVectors, &model_string, cc_KernelFunc, &kernel))
-		return NULL;
+
+	if (!PyArg_ParseTuple(args, "O&sO&|O&O&",
+			cc_Domain, &domain,
+			&model_string,
+			cc_ExampleTable, &supportVectors,
+			ccn_KernelFunc, &kernel,
+			ccn_ExampleTable, &examples)) {
+		 // Old pickle arguments format.
+		PVariable classVar;
+		if (!PyArg_ParseTuple(args, "O&O&O&s|O&:__new__",
+				cc_Variable, &classVar,
+				ccn_ExampleTable, &examples,
+				cc_ExampleTable, &supportVectors,
+				&model_string,
+				cc_KernelFunc, &kernel)) {
+			return NULL;
+		}
+		PyErr_Clear();
+		domain = supportVectors->domain;
+	}
 
 	string buffer(model_string);
 	svm_model* model = svm_load_model_alt(buffer);
 	if (!model)
 		raiseError("Error building LibSVM Model");
 
-	PSVMClassifier svm = mlnew TSVMClassifier(classVar, examples, supportVectors, model, kernel);
+	PSVMClassifier svm = mlnew TSVMClassifier(domain, model, supportVectors, kernel, examples);
 
 	return WrapOrange(svm);
 PyCATCH
 
 
 
-PyObject * SVMClassifierSparse_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) BASED_ON(SVMClassifier, "(Variable, Examples, Examples, string, [useNonMeta, kernelFunc]) -> SVMClassifierSparse")
-{PyTRY
-	PVariable classVar;
+PyObject * SVMClassifierSparse_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) BASED_ON(SVMClassifier, "(Domain, model_string, useNonMeta, supportVectors, [kernelFunc, examples]) -> SVMClassifierSparse")
+{
+PyTRY
+	PDomain domain;
+	char*  model_string = NULL;
+	char useNonMeta = 0;
+
+	PExampleTable supportVectors;
+	PKernelFunc kernel;
 	PExampleTable examples;
-	PExampleTable supportVectors;
-	char*  model_string;
-	char useNonMeta;
-	PKernelFunc kernel;
+
 	if (PyArg_ParseTuple(args, ""))
 		return WrapNewOrange(mlnew TSVMClassifierSparse(), type);
+
 	PyErr_Clear();
-	
-	if (!PyArg_ParseTuple(args, "O&O&O&s|bO&:__new__", cc_Variable, &classVar, ccn_ExampleTable, &examples, cc_ExampleTable, &supportVectors, &model_string, &useNonMeta, cc_KernelFunc, &kernel))
-		return NULL;
-	
+
+	if (!PyArg_ParseTuple(args, "O&sbO&|O&O&:__new__",
+			cc_Domain, &domain,
+			&model_string,
+			&useNonMeta,
+			cc_ExampleTable, &supportVectors,
+			ccn_KernelFunc, &kernel,
+			ccn_ExampleTable, &examples)) {
+
+		 // Old pickle arguments format.
+		PVariable classVar;
+		if (!PyArg_ParseTuple(args, "O&O&O&s|bO&:__new__",
+				cc_Variable, &classVar,
+				ccn_ExampleTable, &examples,
+				cc_ExampleTable, &supportVectors,
+				&model_string,
+				&useNonMeta,
+				cc_KernelFunc, &kernel)) {
+			return NULL;
+		}
+
+		PyErr_Clear();
+		domain = supportVectors->domain;
+	}
+
 	string buffer(model_string);
 	svm_model* model = svm_load_model_alt(buffer);
 	if (!model)
 		raiseError("Error building LibSVM Model");
 
-	PSVMClassifier svm = mlnew TSVMClassifierSparse(classVar, examples, supportVectors, model, useNonMeta != 0, kernel);
+	PSVMClassifier svm = mlnew TSVMClassifierSparse(domain, model, useNonMeta != 0, supportVectors, kernel, examples);
 
 	return WrapOrange(svm);
 PyCATCH

File source/orange/libsvm_interface.cpp

 
 	PExampleTable supportVectors = extract_support_vectors(model, examples);
 
-	PVariable classVar;
+	PDomain domain = examples->domain;
 
-	if (param.svm_type == ONE_CLASS) {
-		classVar = mlnew TFloatVariable("one class");
-	} else {
-		classVar = examples->domain->classVar;
-	}
-
-	return PClassifier(createClassifier(classVar, examples, supportVectors, model));
+	return PClassifier(createClassifier(examples->domain, model, supportVectors, examples));
 }
 
 svm_node* TSVMLearner::example_to_svm(const TExample &ex, svm_node* node, float last, int type){
 }
 
 TSVMClassifier* TSVMLearner::createClassifier(
-		PVariable classVar, PExampleTable examples, PExampleTable supportVectors, svm_model* model) {
+		PDomain domain, svm_model* model, PExampleTable supportVectors, PExampleTable examples) {
 	if (kernel_type != PRECOMPUTED) {
 		examples = NULL;
 	}
-	return mlnew TSVMClassifier(classVar, examples, supportVectors, model, kernelFunc);
+	return mlnew TSVMClassifier(domain, model, supportVectors, kernelFunc, examples);
 }
 
 TSVMLearner::~TSVMLearner(){
 }
 
 TSVMClassifier* TSVMLearnerSparse::createClassifier(
-		PVariable classVar, PExampleTable examples, PExampleTable supportVectors, svm_model* model) {
+		PDomain domain, svm_model* model, PExampleTable supportVectors, PExampleTable examples) {
 	if (kernel_type != PRECOMPUTED) {
 		examples = NULL;
 	}
-	return mlnew TSVMClassifierSparse(classVar, examples, supportVectors, model, useNonMeta, kernelFunc);
+	return mlnew TSVMClassifierSparse(domain, model, useNonMeta, supportVectors, kernelFunc, examples);
 }
 
 
 TSVMClassifier::TSVMClassifier(
-		const PVariable &var,
-		PExampleTable examples,
+		PDomain domain, svm_model * model,
 		PExampleTable supportVectors,
-		svm_model* model,
-		PKernelFunc kernelFunc) {
-	this->classVar = var;
+		PKernelFunc kernelFunc,
+		PExampleTable examples
+		) : TClassifierFD(domain) {
+	this->model = model;
+	this->supportVectors = supportVectors;
+	this->kernelFunc = kernelFunc;
 	this->examples = examples;
-	this->supportVectors = supportVectors;
-	this->model = model;
-	this->kernelFunc = kernelFunc;
 
-	domain = supportVectors->domain;
 	svm_type = svm_get_svm_type(model);
 	kernel_type = model->param.kernel_type;
 
+	if (svm_type == ONE_CLASS) {
+		this->classVar = mlnew TFloatVariable("one class");
+	}
+
 	computesProbabilities = model && svm_check_probability_model(model) && \
-			(svm_type != NU_SVR && svm_type != EPSILON_SVR); // Disable prob. estimation for regression
+				(svm_type != NU_SVR && svm_type != EPSILON_SVR); // Disable prob. estimation for regression
 
 	int nr_class = svm_get_nr_class(model);
 	int i = 0;
 	/* Expose (copy) the model data (coef, rho, probA) to public
 	 * class interface.
 	 */
-    if (svm_type == C_SVC || svm_type == NU_SVC){
-	    nSV = mlnew TIntList(nr_class); // num of SVs for each class (sum = model->l)
-	    for(i = 0;i < nr_class; i++)
-		    nSV->at(i) = model->nSV[i];
-    }
+	if (svm_type == C_SVC || svm_type == NU_SVC) {
+		nSV = mlnew TIntList(nr_class); // num of SVs for each class (sum(nSV) == model->l)
+		for(i = 0;i < nr_class; i++) {
+			nSV->at(i) = model->nSV[i];
+		}
+	}
 
 	coef = mlnew TFloatListList(nr_class-1);
-	for(i = 0; i < nr_class - 1; i++){
+	for(i = 0; i < nr_class - 1; i++) {
 		TFloatList *coefs = mlnew TFloatList(model->l);
-		for(int j = 0;j < model->l; j++)
+		for(int j = 0;j < model->l; j++) {
 			coefs->at(j) = model->sv_coef[i][j];
-		coef->at(i)=coefs;
+		}
+		coef->at(i) = coefs;
 	}
-	rho = mlnew TFloatList(nr_class*(nr_class-1)/2);
-	for(i = 0; i < nr_class*(nr_class-1)/2; i++)
+
+	// Number of binary classifiers in the model
+	int nr_bin_cls = nr_class * (nr_class - 1) / 2;
+
+	rho = mlnew TFloatList(nr_bin_cls);
+	for(i = 0; i < nr_bin_cls; i++) {
 		rho->at(i) = model->rho[i];
-	if(model->probA){
-		probA = mlnew TFloatList(nr_class*(nr_class-1)/2);
-		if (model->param.svm_type != NU_SVR && model->param.svm_type != EPSILON_SVR && model->probB) // Regression has only probA
-			probB = mlnew TFloatList(nr_class*(nr_class-1)/2);
-		for(i=0; i<nr_class*(nr_class-1)/2; i++){
+	}
+
+	if(model->probA) {
+		probA = mlnew TFloatList(nr_bin_cls);
+		if (model->param.svm_type != NU_SVR && model->param.svm_type != EPSILON_SVR && model->probB) {
+			// Regression only has probA
+			probB = mlnew TFloatList(nr_bin_cls);
+		}
+
+		for(i=0; i<nr_bin_cls; i++) {
 			probA->at(i) = model->probA[i];
-			if (model->param.svm_type != NU_SVR && model->param.svm_type != EPSILON_SVR && model->probB)
+			if (model->param.svm_type != NU_SVR && model->param.svm_type != EPSILON_SVR && model->probB) {
 				probB->at(i) = model->probB[i];
+			}
 		}
 	}
 }
 
+
 TSVMClassifier::~TSVMClassifier(){
 	if (model) {
 		svm_free_and_destroy_model(&model);
 	}
 }
 
+
 PDistribution TSVMClassifier::classDistribution(const TExample & example){
 	if(!model)
 		raiseError("No Model");

File source/orange/libsvm_interface.hpp

 
 WRAPPER(KernelFunc)
 
-//#include "callback.hpp"
 
 class ORANGE_API TSVMLearner : public TLearner{
 public:
 	virtual svm_node* init_problem(svm_problem &problem, PExampleTable examples, int n_elements);
 	virtual int getNumOfElements(PExampleGenerator examples);
 	virtual TSVMClassifier* createClassifier(
-			PVariable var, PExampleTable examples, PExampleTable supportVectors, svm_model* model);
+				PDomain domain, svm_model* model, PExampleTable supportVectors, PExampleTable examples);
 };
 
 class ORANGE_API TSVMLearnerSparse : public TSVMLearner{
 	virtual svm_node* example_to_svm(const TExample &ex, svm_node* node, float last=0.0, int type=0);
 	virtual int getNumOfElements(PExampleGenerator examples);
 	virtual TSVMClassifier* createClassifier(
-			PVariable classVar, PExampleTable examples, PExampleTable supportVectors, svm_model* model);
+			PDomain domain, svm_model* model, PExampleTable supportVectors, PExampleTable examples);
 };
 
 
-class ORANGE_API TSVMClassifier : public TClassifierFD{
+class ORANGE_API TSVMClassifier : public TClassifierFD {
 public:
 	__REGISTER_CLASS
-	TSVMClassifier(){
+	TSVMClassifier() {
 		this->model = NULL;
 	};
 
-	TSVMClassifier(const PVariable & , PExampleTable examples, PExampleTable supportVectors,
-			svm_model* model, PKernelFunc kernelFunc);
+	TSVMClassifier(PDomain, svm_model * model, PExampleTable supportVectors,
+			PKernelFunc kernelFunc=NULL, PExampleTable examples=NULL);
 
 	~TSVMClassifier();
 
 	PFloatList probA; //P probA - pairwise probability information
 	PFloatList probB; //P probB - pairwise probability information
 	PExampleTable supportVectors; //P support vectors
-	PExampleTable examples;	//P (training instances when svm_type == Custom)
-	PKernelFunc kernelFunc;	//P custom kernel function
+
+	PExampleTable examples;	//P training instances when svm_type == Custom
+	PKernelFunc kernelFunc;	//P custom kernel function used when svm_type == Custom
 
 	int svm_type; //P(&SVMLearner_SVMType)  SVM type (C_SVC=0, NU_SVC, ONE_CLASS, EPSILON_SVR=3, NU_SVR=4)
 	int kernel_type; //P(&SVMLearner_Kernel)  kernel type (LINEAR=0, POLY, RBF, SIGMOID, CUSTOM=4)
 	svm_model *model;
 };
 
-class ORANGE_API TSVMClassifierSparse : public TSVMClassifier{
+class ORANGE_API TSVMClassifierSparse : public TSVMClassifier {
 public:
 	__REGISTER_CLASS
-	TSVMClassifierSparse(){};
-	TSVMClassifierSparse(PVariable var, PExampleTable examples,  PExampleTable supportVectors,
-			svm_model* model, bool useNonMeta, PKernelFunc kernelFunc
-			) :TSVMClassifier(var, examples, supportVectors, model, kernelFunc){
+	TSVMClassifierSparse() {};
+
+	TSVMClassifierSparse(
+			PDomain domain, svm_model * model, bool useNonMeta,
+			PExampleTable supportVectors,
+			PKernelFunc kernelFunc=NULL,
+			PExampleTable examples=NULL
+			) : TSVMClassifier(domain, model, supportVectors, kernelFunc, examples) {
 		this->useNonMeta = useNonMeta;
 	}
 
-	bool useNonMeta; //P include non meta attributes
+	bool useNonMeta; //PR include non meta attributes
 
 protected:
 	virtual svm_node* example_to_svm(const TExample &ex, svm_node* node, float last=0.0, int type=0);