#encoding:latin-1 import _libsvm as L from numpy import * # Kernel objects instead of enumeration as in C ############################# # class Kernel(object): def __init__(self, **param): self.param=param class LinearKernel(Kernel): pass class PolynomialKernel(Kernel): pass class RadialKernel(Kernel): pass # CSVM class ################################################################# # class CSVM(object): """ pythonic wrapper for C-SVM from svmlib """ def __init__(self, kernel, **param): """ needed params: kernel optional params: eps, cache_size, maxiter, verbose """ self.kernel = kernel self.handle = None # set global parameters in _libsvm.pyd: if "eps" in param: L.set_eps(param["eps"]) if "cache_size" in param: L.set_cache_size(param["cache_size"]) if "maxiter" in param.keys(): L.set_maxiter(param["maxiter"]) if "verbose" in param: L.set_verbose(param["verbose"]) if "C" in param: if "Cp" in param or "Cm" in param: raise ValueError, "parameters C, Cp, Cm not consistent" L.set_C(param["C"]) if "Cp" in param: if "C" in param: raise ValueError, "parameters C, Cp, Cm not consistent" if not "Cm" in param: raise ValueError, "parameters C, Cp, Cm not consistent" L.set_Cpm(param["Cp"], param["Cm"]) def learn(self, matrix_good, matrix_bad): """ datatables for learning: each matrix has one sample per row """ matrix_good = require(matrix_good, double) matrix_bad = require(matrix_bad, double) # check input parameters if matrix_good.ndim !=2: raise ValueError,"matrix_good is not square matrix" if matrix_bad.ndim !=2: raise ValueError,"matrix_bad is not square matrix" if matrix_good.shape[1] != matrix_bad.shape[1]: raise ValueError,"matrix_bad and matrix_good have different " \ "number of features" self.num_features = matrix_good.shape[1] kernel = self.kernel if isinstance(kernel, type): # standard error for linear kernel: if one forgets '()' # this exception is thrown raise ValueError, "kernel parameter has to be an instance "\ "of Kernel class" # set global parameters depending on kernel if isinstance(kernel, LinearKernel): L.set_linear_kernel() elif isinstance(kernel, PolynomialKernel): L.set_polynomial_kernel() L.set_degree(kernel.param["degree"]) L.set_coef0(kernel.param["coef0"]) L.set_gamma(kernel.param["gamma"]) elif isinstance(kernel, RadialKernel): L.set_radial_kernel() L.set_gamma(kernel.param["gamma"]) else: # unknown kernel object raise ValueError, "invalid kernel given" # train and store handle to generated svm model self.handle = L.wrap_train(matrix_good, matrix_bad) def get_num_iter(self): # check if model was trained if self.handle is None: raise ValueError, "you have to learn first" return L.get_num_iter(self.handle) def get_bias(self): # check if model was trained if self.handle is None: raise ValueError, "you have to learn first" return L.get_bias(self.handle) def set_bias(self, value): # check if model was trained if self.handle is None: raise ValueError, "you have to learn first" L.set_bias(self.handle, value) def classify(self, vec): """ classifies vector """ # check if model was trained if self.handle is None: raise ValueError, "you can not classify without learning" # check input vec = require(vec, double, "C") if vec.ndim != 1: raise ValueError, "vec is not a vector" if len(vec) != self.num_features: raise ValueError, "vec has wrong length" # apply model return L.wrap_classify(self.handle, vec) def classify_matrix(self, mat): """ classifies vector """ # check if model was trained if self.handle is None: raise ValueError, "you can not classify without learning" # convert input if needed mat = asarray(mat, double, "C") # check input if mat.ndim != 2: raise ValueError, "mat is not a matrix" if mat.shape[1] != self.num_features: raise ValueError, "mat has wrong size" # apply model rv = zeros((mat.shape[0],), dtype=byte) L.wrap_classify_matrix(self.handle, mat, rv) return rv def __del__(self): """ free resources """ if self.handle is not None: L.wrap_free(self.handle) self.handle = None release = __del__ def save(self, path): """ saves model to plain text format file """ # check if model was trained if self.handle is None: raise ValueError, "you have to learn first" # saves model L.wrap_savemodel(self.handle, path) def get_num_sv(self): # check if model was trained if self.handle is None: raise ValueError, "you have to learn first" return L.get_num_sv(self.handle) def get_alpha(self, i): # check if model was trained if self.handle is None: raise ValueError, "you have to learn first" return L.get_alpha(self.handle, i) def get_sv(self, i): # check if model was trained if self.handle is None: raise ValueError, "you have to learn first" return L.get_sv(self.handle, i, self.num_features) if __name__ == "__main__": # here come a test: M = CSVM(LinearKernel(), maxiter=40, Cp=1, Cm=1, verbose=1) print print "learning with verbose output:" print M.learn([[0,2,0],[0,1,0]],[[0,3,0]]) print print M.get_num_iter(), "iterations" num_sv= M.get_num_sv() for i in range(num_sv): print " alpha %d = %f" % (i, M.get_alpha(i)) print " ", M.get_sv(i) print M.save("log.mod") print "test classifier:" print " should be -1: ", M.classify([0,2.9,0]) print " should be +1: ", M.classify([0,2.1,0]) print print M.classify_matrix([[0,2.9,0],[0,2.1,0]]) print "test release:" M.release() try: print M.classify([0,2.9]) except ValueError, e: if e.message=="you can not classify without learning": print " test ok" else: print " test failed" else: print " test failed"