packages feed

HSvm 0.1.2.3.25 → 0.1.2.3.32

raw patch · 4 files changed

+371/−179 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

Data/SVM.hs view
@@ -1,107 +1,165 @@-{-|-This module provides a safe bindings to libsvm functions and structures with implicit memory handling.--}+-- |+-- This module provides a safe bindings to libsvm functions and structures with implicit memory handling. module Data.SVM-  ( Vector-  , Problem-  , KernelType (..)-  , Algorithm (..)-  , ExtraParam (..)-  , Model-  , train-  , train'-  , crossValidate-  , crossValidate'-  , loadModel-  , saveModel-  , predict-  , withPrintFn-  , CSvmPrintFn-  ) where+  ( Vector,+    Problem,+    KernelType (..),+    Algorithm (..),+    ExtraParam (..),+    Model,+    train,+    train',+    crossValidate,+    crossValidate',+    loadModel,+    saveModel,+    predict,+    withPrintFn,+    CSvmPrintFn,+  )+where -import           Control.Exception-import           Control.Monad         (when)-import           Data.IntMap           (IntMap, toList)-import qualified Data.IntMap           as M-import           Data.SVM.Raw          (CSvmModel, CSvmNode (..), CSvmParameter,-                                        CSvmPrintFn, CSvmProblem (..),-                                        c_clone_model_support_vectors,-                                        c_svm_check_parameter,-                                        c_svm_cross_validation,-                                        c_svm_destroy_model, c_svm_load_model,-                                        c_svm_predict, c_svm_save_model,-                                        c_svm_set_print_string_function,-                                        c_svm_train, createSvmPrintFnPtr,-                                        defaultCParam)-import qualified Data.SVM.Raw          as R-import           Foreign.C.String-import           Foreign.ForeignPtr-import           Foreign.Marshal.Alloc (alloca, free, malloc)-import           Foreign.Marshal.Array-import           Foreign.Ptr           (Ptr, freeHaskellFunPtr, nullPtr)-import           Foreign.Storable      (peek, poke)+import Control.Exception+import Control.Monad (when)+import Data.IntMap (IntMap, toList)+import qualified Data.IntMap as M+import Data.SVM.Raw+  ( CSvmModel,+    CSvmNode (..),+    CSvmParameter,+    CSvmPrintFn,+    CSvmProblem (..),+    c_clone_model_support_vectors,+    c_svm_check_parameter,+    c_svm_cross_validation,+    c_svm_destroy_model,+    c_svm_load_model,+    c_svm_predict,+    c_svm_save_model,+    c_svm_set_print_string_function,+    c_svm_train,+    createSvmPrintFnPtr,+    defaultCParam,+  )+import qualified Data.SVM.Raw as R+import Foreign.C.String (newCString, peekCString)+import Foreign.ForeignPtr+  ( ForeignPtr,+    newForeignPtr,+    withForeignPtr,+  )+import Foreign.Marshal.Alloc (alloca, free, malloc)+import Foreign.Marshal.Array+  ( allocaArray,+    newArray,+    newArray0,+    peekArray,+    withArray0,+  )+import Foreign.Ptr (Ptr, freeHaskellFunPtr, nullPtr)+import Foreign.Storable (peek, poke) --- |Vector type provides a sparse implementation of vector. It uses IntMap as underlying implementation.+-- | Vector type provides a sparse implementation of vector. It uses IntMap as underlying implementation. type Vector = IntMap Double --- |SVM problem is a list of maps from training vectors to 1.0 or -1.0+-- | SVM problem is a list of maps from training vectors to 1.0 or -1.0 type Problem = [(Double, Vector)] --- |'Model' is a wrapper over foreign pointer to 'CSvmModel'+-- | 'Model' is a wrapper over foreign pointer to 'CSvmModel' newtype Model = Model (ForeignPtr CSvmModel) --- |Kernel function for SVM algorithm.-data KernelType = Linear -- ^Linear kernel function, i.e. dot product-                | RBF     { gamma :: Double } -- ^Gaussian radial basis function with parameter 'gamma'-                | Sigmoid { gamma :: Double, coef0 :: Double } -- ^Sigmoid kernel function-                | Poly    { gamma :: Double, coef0 :: Double, degree :: Int} -- ^Inhomogeneous polynomial function+-- | Kernel function for SVM algorithm.+data KernelType+  = -- | Linear kernel function, i.e. dot product+    Linear+  | -- | Gaussian radial basis function with parameter 'gamma'+    RBF {gamma :: Double}+  | -- | Sigmoid kernel function+    Sigmoid {gamma :: Double, coef0 :: Double}+  | -- | Inhomogeneous polynomial function+    Poly {gamma :: Double, coef0 :: Double, degree :: Int} --- |SVM Algorithm with parameters-data Algorithm = CSvc  { c :: Double } -- ^c-SVC algorithm-               | NuSvc { nu :: Double } -- ^nu-SVC algorithm-               | NuSvr { nu :: Double, c :: Double } -- ^nu-SVR algorithm-               | EpsilonSvr { epsilon :: Double, c :: Double } -- ^eps-SVR algorithm-               | OneClassSvm { nu :: Double } -- ^One class SVM+-- | SVM Algorithm with parameters+data Algorithm+  = -- | c-SVC algorithm+    CSvc {c :: Double}+  | -- | nu-SVC algorithm+    NuSvc {nu :: Double}+  | -- | nu-SVR algorithm+    NuSvr {nu :: Double, c :: Double}+  | -- | eps-SVR algorithm+    EpsilonSvr {epsilon :: Double, c :: Double}+  | -- | One class SVM+    OneClassSvm {nu :: Double} --- |Extra parameters of SVM implementation-data ExtraParam = ExtraParam {cacheSize   :: Double,-                              shrinking   :: Int,-                              probability :: Int}+-- | Extra parameters of SVM implementation+data ExtraParam = ExtraParam+  { cacheSize :: Double,+    shrinking :: Int,+    probability :: Int+  } --- |Default extra parameters of SVM implamentation+-- | Default extra parameters of SVM implamentation defaultExtra :: ExtraParam defaultExtra = ExtraParam {cacheSize = 1000, shrinking = 1, probability = 0}  mergeKernel :: KernelType -> CSvmParameter -> CSvmParameter-mergeKernel Linear p        = p { R.kernel_type = R.linear }-mergeKernel (RBF g) p       = p { R.kernel_type = R.rbf,-                                  R.gamma = realToFrac g }-mergeKernel (Sigmoid g cf) p = p { R.kernel_type = R.sigmoid,-                                  R.gamma = realToFrac g,-                                  R.coef0 = realToFrac cf }-mergeKernel (Poly g cf d) p  = p { R.kernel_type = R.poly,-                                  R.gamma = realToFrac g,-                                  R.coef0 = realToFrac cf,-                                  R.degree = fromIntegral d}+mergeKernel Linear p = p {R.kernel_type = R.linear}+mergeKernel (RBF g) p =+  p+    { R.kernel_type = R.rbf,+      R.gamma = realToFrac g+    }+mergeKernel (Sigmoid g cf) p =+  p+    { R.kernel_type = R.sigmoid,+      R.gamma = realToFrac g,+      R.coef0 = realToFrac cf+    }+mergeKernel (Poly g cf d) p =+  p+    { R.kernel_type = R.poly,+      R.gamma = realToFrac g,+      R.coef0 = realToFrac cf,+      R.degree = fromIntegral d+    }  mergeAlgo :: Algorithm -> CSvmParameter -> CSvmParameter-mergeAlgo (CSvc cf) p         = p { R.svm_type = R.cSvc,-                                   R.c = realToFrac cf }-mergeAlgo (NuSvc n) p       = p { R.svm_type = R.nuSvc,-                                   R.nu = realToFrac n }-mergeAlgo (NuSvr n cf) p     = p { R.svm_type = R.nuSvr,-                                   R.nu = realToFrac n,-                                   R.c = realToFrac cf }-mergeAlgo (EpsilonSvr e cf) p = p { R.svm_type = R.epsilonSvr,-                                   R.eps = realToFrac e,-                                   R.c = realToFrac cf }-mergeAlgo (OneClassSvm n) p = p { R.svm_type = R.oneClass,-                                   R.nu = realToFrac n }+mergeAlgo (CSvc cf) p =+  p+    { R.svm_type = R.cSvc,+      R.c = realToFrac cf+    }+mergeAlgo (NuSvc n) p =+  p+    { R.svm_type = R.nuSvc,+      R.nu = realToFrac n+    }+mergeAlgo (NuSvr n cf) p =+  p+    { R.svm_type = R.nuSvr,+      R.nu = realToFrac n,+      R.c = realToFrac cf+    }+mergeAlgo (EpsilonSvr e cf) p =+  p+    { R.svm_type = R.epsilonSvr,+      R.eps = realToFrac e,+      R.c = realToFrac cf+    }+mergeAlgo (OneClassSvm n) p =+  p+    { R.svm_type = R.oneClass,+      R.nu = realToFrac n+    }  mergeExtra :: ExtraParam -> CSvmParameter -> CSvmParameter-mergeExtra (ExtraParam cf s pr) p = p { R.cache_size = realToFrac cf,-                                       R.shrinking = fromIntegral s,-                                       R.probability = fromIntegral pr }+mergeExtra (ExtraParam cf s pr) p =+  p+    { R.cache_size = realToFrac cf,+      R.shrinking = fromIntegral s,+      R.probability = fromIntegral pr+    }  ------------------------------------------------------------------------------- @@ -120,117 +178,123 @@ withCSvmNodeArray v = withArray0 endMarker (convertToNodeArray v)  newCSvmProblem :: Problem -> IO (Ptr CSvmProblem)-newCSvmProblem lvs = do nodePtrList <- mapM (newCSvmNodeArray . snd) lvs-                        nodePtrPtr  <- newArray nodePtrList-                        labelPtr <- newArray (map (realToFrac . fst) lvs)-                        let z = fromIntegral . length $ lvs-                        ptr <- malloc-                        poke ptr $ CSvmProblem z labelPtr nodePtrPtr-                        return ptr+newCSvmProblem lvs = do+  nodePtrList <- mapM (newCSvmNodeArray . snd) lvs+  nodePtrPtr <- newArray nodePtrList+  labelPtr <- newArray (map (realToFrac . fst) lvs)+  let z = fromIntegral . length $ lvs+  ptr <- malloc+  poke ptr $ CSvmProblem z labelPtr nodePtrPtr+  return ptr  freeCSVmProblem :: Ptr CSvmProblem -> IO ()-freeCSVmProblem ptr = do prob <- peek ptr-                         free $ y prob-                         vecList <- peekArray (fromIntegral $ l prob) (x prob)-                         mapM_ free vecList-                         free $ x prob-                         free ptr+freeCSVmProblem ptr = do+  prob <- peek ptr+  free $ y prob+  vecList <- peekArray (fromIntegral $ l prob) (x prob)+  mapM_ free vecList+  free $ x prob+  free ptr  withProblem :: Problem -> (Ptr CSvmProblem -> IO a) -> IO a withProblem prob = bracket (newCSvmProblem prob) freeCSVmProblem  --- -withParam :: ExtraParam-             -> Algorithm-             -> KernelType-             -> (Ptr CSvmParameter -> IO a)-             -> IO a+withParam ::+  ExtraParam ->+  Algorithm ->+  KernelType ->+  (Ptr CSvmParameter -> IO a) ->+  IO a withParam extra algo kern f =-    let merge = mergeAlgo algo . mergeKernel kern . mergeExtra extra-        param = merge defaultCParam-    in alloca $ \paramPtr -> poke paramPtr param >> f paramPtr+  let merge = mergeAlgo algo . mergeKernel kern . mergeExtra extra+      param = merge defaultCParam+   in alloca $ \paramPtr -> poke paramPtr param >> f paramPtr  checkParam :: Ptr CSvmProblem -> Ptr CSvmParameter -> IO () checkParam probPtr paramPtr = do-    let errStr = c_svm_check_parameter probPtr paramPtr-    when (errStr /= nullPtr) $ peekCString errStr >>= error . ("svm: "++)+  let errStr = c_svm_check_parameter probPtr paramPtr+  when (errStr /= nullPtr) $ peekCString errStr >>= error . ("svm: " ++)  -- --- |Like 'train' but with extra parameters+-- | Like 'train' but with extra parameters train' :: ExtraParam -> Algorithm -> KernelType -> Problem -> IO Model train' extra algo kern prob =-    withProblem prob $ \probPtr ->+  withProblem prob $ \probPtr ->     withParam extra algo kern $ \paramPtr -> do-        checkParam probPtr paramPtr-        modelPtr <- c_svm_train probPtr paramPtr-        _ <- c_clone_model_support_vectors modelPtr-        modelForeignPtr <- newForeignPtr c_svm_destroy_model modelPtr-        return $ Model modelForeignPtr-+      checkParam probPtr paramPtr+      modelPtr <- c_svm_train probPtr paramPtr+      _ <- c_clone_model_support_vectors modelPtr+      modelForeignPtr <- newForeignPtr c_svm_destroy_model modelPtr+      return $ Model modelForeignPtr  -- | The 'train' function allows training a 'Model' starting from a 'Problem' -- by specifying an 'Algorithm' and a 'KernelType' train :: Algorithm -> KernelType -> Problem -> IO Model train = train' defaultExtra --- |Like 'crossvalidate' but with extra parameters-crossValidate' :: ExtraParam-                  -> Algorithm-                  -> KernelType-                  -> Problem-                  -> Int-                  -> IO [Double]+-- | Like 'crossvalidate' but with extra parameters+crossValidate' ::+  ExtraParam ->+  Algorithm ->+  KernelType ->+  Problem ->+  Int ->+  IO [Double] crossValidate' extra algo kern prob nFold =-    withProblem prob $ \probPtr ->+  withProblem prob $ \probPtr ->     withParam extra algo kern $ \paramPtr -> do-        probLen <- (fromIntegral . R.l) `fmap` peek probPtr-        allocaArray probLen $ \targetPtr -> do -- (length prob is inefficient)-            checkParam probPtr paramPtr-            let c_nFold = fromIntegral nFold-            c_svm_cross_validation probPtr paramPtr c_nFold targetPtr-            map realToFrac `fmap` peekArray probLen targetPtr+      probLen <- (fromIntegral . R.l) `fmap` peek probPtr+      allocaArray probLen $ \targetPtr -> do+        -- (length prob is inefficient)+        checkParam probPtr paramPtr+        let c_nFold = fromIntegral nFold+        c_svm_cross_validation probPtr paramPtr c_nFold targetPtr+        map realToFrac `fmap` peekArray probLen targetPtr --- |Stratified cross validation+-- | Stratified cross validation crossValidate :: Algorithm -> KernelType -> Problem -> Int -> IO [Double] crossValidate = crossValidate' defaultExtra  ----------------------------------------------------------------------- --- |Save model to the file+-- | Save model to the file saveModel :: Model -> FilePath -> IO () saveModel (Model modelForeignPtr) path =-    withForeignPtr modelForeignPtr $ \modelPtr -> do-        pathString <- newCString path-        ret <- c_svm_save_model pathString modelPtr-        when (ret /= 0) $ error $ "svm: error saving the model:" ++ show ret+  withForeignPtr modelForeignPtr $ \modelPtr -> do+    pathString <- newCString path+    ret <- c_svm_save_model pathString modelPtr+    when (ret /= 0) $ error $ "svm: error saving the model:" ++ show ret --- |Load model from the file+-- | Load model from the file loadModel :: FilePath -> IO Model loadModel path = do-    modelPtr <- c_svm_load_model =<< newCString path-    Model `fmap` newForeignPtr c_svm_destroy_model modelPtr+  modelPtr <- c_svm_load_model =<< newCString path+  Model `fmap` newForeignPtr c_svm_destroy_model modelPtr --- |Predict a value for 'Vector' by using 'Model'+-- | Predict a value for 'Vector' by using 'Model' predict :: Model -> Vector -> IO Double predict (Model modelForeignPtr) vector = action-    where action :: IO Double-          action = withForeignPtr modelForeignPtr $ \modelPtr ->-                   withCSvmNodeArray vector (fmap realToFrac . c_svm_predict modelPtr)+  where+    action :: IO Double+    action = withForeignPtr modelForeignPtr $ \modelPtr ->+      withCSvmNodeArray vector (fmap realToFrac . c_svm_predict modelPtr) --- |Wrapper to change the libsvm output reporting function.+-- | Wrapper to change the libsvm output reporting function. ----- libsvm by default writes some statistics to stdout. If you don't--- want any output from libsvm, you can do e.g.:+--  libsvm by default writes some statistics to stdout. If you don't+--  want any output from libsvm, you can do e.g.: ----- >>> withPrintFn (\_ -> return ()) $ train (NuSvc 0.25) (RBF 1) feats+--  >>> withPrintFn (\_ -> return ()) $ train (NuSvc 0.25) (RBF 1) feats withPrintFn :: CSvmPrintFn -> IO a -> IO a-withPrintFn printfn body = bracket-  (do-    c_printfn <- createSvmPrintFnPtr printfn-    c_svm_set_print_string_function c_printfn-    return c_printfn-  )-  freeHaskellFunPtr-  (const body)+withPrintFn printfn body =+  bracket+    ( do+        c_printfn <- createSvmPrintFnPtr printfn+        c_svm_set_print_string_function c_printfn+        return c_printfn+    )+    freeHaskellFunPtr+    (const body)
HSvm.cabal view
@@ -1,6 +1,6 @@ Cabal-Version:      2.2 Name:               HSvm-Version:            0.1.2.3.25+Version:            0.1.2.3.32 Copyright:          (c) 2009 Paolo Losi, 2017 Pavel Ryzhov Maintainer:         Pavel Ryzhov <paul@paulrz.cz> License:            BSD-3-Clause
cbits/svm.cpp view
@@ -8,6 +8,10 @@ #include <limits.h> #include <locale.h> #include "svm.h"+#ifdef _OPENMP+#include <omp.h>+#endif+ int libsvm_version = LIBSVM_VERSION; typedef float Qfloat; typedef signed char schar;@@ -1290,6 +1294,9 @@ 		int start, j; 		if((start = cache->get_data(i,&data,len)) < len) 		{+#ifdef _OPENMP+#pragma omp parallel for private(j) schedule(guided)+#endif 			for(j=start;j<len;j++) 				data[j] = (Qfloat)(y[i]*y[j]*(this->*kernel_function)(i,j)); 		}@@ -1405,6 +1412,9 @@ 		int j, real_i = index[i]; 		if(cache->get_data(real_i,&data,l) < l) 		{+#ifdef _OPENMP+#pragma omp parallel for private(j) schedule(guided)+#endif 			for(j=0;j<l;j++) 				data[j] = (Qfloat)(this->*kernel_function)(real_i,j); 		}@@ -1833,7 +1843,7 @@ 		return 1.0/(1+exp(fApB)) ; } -// Method 2 from the multiclass_prob paper by Wu, Lin, and Weng+// Method 2 from the multiclass_prob paper by Wu, Lin, and Weng to predict probabilities static void multiclass_probability(int k, double **r, double *p) { 	int t,j;@@ -1897,7 +1907,7 @@ 	free(Qp); } -// Cross-validation decision values for probability estimates+// Using cross-validation decision values to get parameters for SVC probability estimates static void svm_binary_svc_probability( 	const svm_problem *prob, const svm_parameter *param, 	double Cp, double Cn, double& probA, double& probB)@@ -1984,6 +1994,83 @@ 	free(perm); } +// Binning method from the oneclass_prob paper by Que and Lin to predict the probability as a normal instance (i.e., not an outlier)+static double predict_one_class_probability(const svm_model *model, double dec_value)+{+	double prob_estimate = 0.0;+	int nr_marks = 10;++	if(dec_value < model->prob_density_marks[0])+		prob_estimate = 0.001;+	else if(dec_value > model->prob_density_marks[nr_marks-1])+		prob_estimate = 0.999;+	else+	{+		for(int i=1;i<nr_marks;i++)+			if(dec_value < model->prob_density_marks[i])+			{+				prob_estimate = (double)i/nr_marks;+				break;+			}+	}+	return prob_estimate;+}++static int compare_double(const void *a, const void *b)+{+	if(*(double *)a > *(double *)b)+		return 1;+	else if(*(double *)a < *(double *)b)+		return -1;+	return 0;+}++// Get parameters for one-class SVM probability estimates+static int svm_one_class_probability(const svm_problem *prob, const svm_model *model, double *prob_density_marks)+{+	double *dec_values = Malloc(double,prob->l);+	double *pred_results = Malloc(double,prob->l);+	int ret = 0;+	int nr_marks = 10;++	for(int i=0;i<prob->l;i++)+		pred_results[i] = svm_predict_values(model,prob->x[i],&dec_values[i]);+	qsort(dec_values,prob->l,sizeof(double),compare_double);++	int neg_counter=0;+	for(int i=0;i<prob->l;i++)+		if(dec_values[i]>=0)+		{+			neg_counter = i;+			break;+		}++	int pos_counter = prob->l-neg_counter;+	if(neg_counter<nr_marks/2 || pos_counter<nr_marks/2)+	{+		fprintf(stderr,"WARNING: number of positive or negative decision values <%d; too few to do a probability estimation.\n",nr_marks/2);+		ret = -1;+	}+	else+	{+		// Binning by density+		double *tmp_marks = Malloc(double,nr_marks+1);+		int mid = nr_marks/2;+		for(int i=0;i<mid;i++)+			tmp_marks[i] = dec_values[i*neg_counter/mid];+		tmp_marks[mid] = 0;+		for(int i=mid+1;i<nr_marks+1;i++)+			tmp_marks[i] = dec_values[neg_counter-1+(i-mid)*pos_counter/mid];++		for(int i=0;i<nr_marks;i++)+			prob_density_marks[i] = (tmp_marks[i]+tmp_marks[i+1])/2;+		free(tmp_marks);+	}+	free(dec_values);+	free(pred_results);+	return ret;+}+ // Return parameter of a Laplace distribution static double svm_svr_probability( 	const svm_problem *prob, const svm_parameter *param)@@ -2107,24 +2194,14 @@ 	   param->svm_type == EPSILON_SVR || 	   param->svm_type == NU_SVR) 	{-		printf("SVM type %d\n", param->svm_type);-		printf("Kernel type %d\n", param->kernel_type);-		printf("Gamma %f\n", param->gamma); 		// regression or one-class-svm 		model->nr_class = 2; 		model->label = NULL; 		model->nSV = NULL; 		model->probA = NULL; model->probB = NULL;+		model->prob_density_marks = NULL; 		model->sv_coef = Malloc(double *,1); -		if(param->probability &&-		   (param->svm_type == EPSILON_SVR ||-		    param->svm_type == NU_SVR))-		{-			model->probA = Malloc(double,1);-			model->probA[0] = svm_svr_probability(prob,param);-		}- 		decision_function f = svm_train_one(prob,param,0,0); 		model->rho = Malloc(double,1); 		model->rho[0] = f.rho;@@ -2147,6 +2224,24 @@ 				++j; 			} +		if(param->probability &&+		   (param->svm_type == EPSILON_SVR ||+		    param->svm_type == NU_SVR))+		{+			model->probA = Malloc(double,1);+			model->probA[0] = svm_svr_probability(prob,param);+		}+		else if(param->probability && param->svm_type == ONE_CLASS)+		{+			int nr_marks = 10;+			double *prob_density_marks = Malloc(double,nr_marks);++			if(svm_one_class_probability(prob,model,prob_density_marks) == 0)+				model->prob_density_marks = prob_density_marks;+			else+				free(prob_density_marks);+		}+ 		free(f.alpha); 	} 	else@@ -2264,6 +2359,7 @@ 			model->probA=NULL; 			model->probB=NULL; 		}+		model->prob_density_marks=NULL;	// for one-class SVM probabilistic outputs only  		int total_sv = 0; 		int *nz_count = Malloc(int,nr_class);@@ -2356,8 +2452,8 @@ 	int nr_class; 	if (nr_fold > l) 	{+		fprintf(stderr,"WARNING: # folds (%d) > # data (%d). Will use # folds = # data instead (i.e., leave-one-out cross validation)\n", nr_fold, l); 		nr_fold = l;-		fprintf(stderr,"WARNING: # folds > # data. Will use # folds = # data instead (i.e., leave-one-out cross validation)\n"); 	} 	fold_start = Malloc(int,nr_fold+1); 	// stratified cv may not give leave-one-out rate@@ -2518,6 +2614,9 @@ 	{ 		double *sv_coef = model->sv_coef[0]; 		double sum = 0;+#ifdef _OPENMP+#pragma omp parallel for private(i) reduction(+:sum) schedule(guided)+#endif 		for(i=0;i<model->l;i++) 			sum += sv_coef[i] * Kernel::k_function(x,model->SV[i],model->param); 		sum -= model->rho[0];@@ -2534,6 +2633,9 @@ 		int l = model->l;  		double *kvalue = Malloc(double,l);+#ifdef _OPENMP+#pragma omp parallel for private(i) schedule(guided)+#endif 		for(i=0;i<l;i++) 			kvalue[i] = Kernel::k_function(x,model->SV[i],model->param); @@ -2641,6 +2743,14 @@ 		free(pairwise_prob); 		return model->label[prob_max_idx]; 	}+	else if(model->param.svm_type == ONE_CLASS && model->prob_density_marks!=NULL)+	{+		double dec_value;+		double pred_result = svm_predict_values(model,x,&dec_value);+		prob_estimates[0] = predict_one_class_probability(model,dec_value);+		prob_estimates[1] = 1-prob_estimates[0];+		return pred_result;+	} 	else 		return svm_predict(model, x); }@@ -2714,6 +2824,14 @@ 			fprintf(fp," %.17g",model->probB[i]); 		fprintf(fp, "\n"); 	}+	if(model->prob_density_marks)+	{+		fprintf(fp, "prob_density_marks");+		int nr_marks=10;+		for(int i=0;i<nr_marks;i++)+			fprintf(fp," %.17g",model->prob_density_marks[i]);+		fprintf(fp, "\n");+	}  	if(model->nSV) 	{@@ -2868,6 +2986,13 @@ 			for(int i=0;i<n;i++) 				FSCANF(fp,"%lf",&model->probB[i]); 		}+		else if(strcmp(cmd,"prob_density_marks")==0)+		{+			int n = 10;	// nr_marks+			model->prob_density_marks = Malloc(double,n);+			for(int i=0;i<n;i++)+				FSCANF(fp,"%lf",&model->prob_density_marks[i]);+		} 		else if(strcmp(cmd,"nr_sv")==0) 		{ 			int n = model->nr_class;@@ -2912,6 +3037,7 @@ 	model->rho = NULL; 	model->probA = NULL; 	model->probB = NULL;+	model->prob_density_marks = NULL; 	model->sv_indices = NULL; 	model->label = NULL; 	model->nSV = NULL;@@ -3023,14 +3149,17 @@ 	model_ptr->rho = NULL;  	free(model_ptr->label);-	model_ptr->label= NULL;+	model_ptr->label = NULL;  	free(model_ptr->probA); 	model_ptr->probA = NULL;  	free(model_ptr->probB);-	model_ptr->probB= NULL;+	model_ptr->probB = NULL; +	free(model_ptr->prob_density_marks);+	model_ptr->prob_density_marks = NULL;+ 	free(model_ptr->sv_indices); 	model_ptr->sv_indices = NULL; @@ -3124,11 +3253,7 @@ 	   param->probability != 1) 		return "probability != 0 and probability != 1"; -	if(param->probability == 1 &&-	   svm_type == ONE_CLASS)-		return "one-class SVM probability output not supported yet"; - 	// check whether nu-svc is feasible  	if(svm_type == NU_SVC)@@ -3187,8 +3312,10 @@  int svm_check_probability_model(const svm_model *model) {-	return ((model->param.svm_type == C_SVC || model->param.svm_type == NU_SVC) &&-		model->probA!=NULL && model->probB!=NULL) ||+	return+		((model->param.svm_type == C_SVC || model->param.svm_type == NU_SVC) &&+		 model->probA!=NULL && model->probB!=NULL) ||+		(model->param.svm_type == ONE_CLASS && model->prob_density_marks!=NULL) || 		((model->param.svm_type == EPSILON_SVR || model->param.svm_type == NU_SVR) && 		 model->probA!=NULL); }
cbits/svm.h view
@@ -1,7 +1,7 @@ #ifndef _LIBSVM_H #define _LIBSVM_H -#define LIBSVM_VERSION 325+#define LIBSVM_VERSION 332  #ifdef __cplusplus extern "C" {@@ -59,6 +59,7 @@ 	double *rho;		/* constants in decision functions (rho[k*(k-1)/2]) */ 	double *probA;		/* pariwise probability information */ 	double *probB;+	double *prob_density_marks;	/* probability information for ONE_CLASS */ 	int *sv_indices;        /* sv_indices[0,...,nSV-1] are values in [1,...,num_traning_data] to indicate SVs in the training set */  	/* for classification only */@@ -88,7 +89,6 @@ double svm_predict(const struct svm_model *model, const struct svm_node *x); double svm_predict_probability(const struct svm_model *model, const struct svm_node *x, double* prob_estimates); -void svm_destroy_model(struct svm_model *model_ptr); void svm_free_model_content(struct svm_model *model_ptr); void svm_free_and_destroy_model(struct svm_model **model_ptr_ptr); void svm_destroy_param(struct svm_parameter *param);@@ -99,6 +99,7 @@ void svm_set_print_string_function(void (*print_func)(const char *));  // added by HSvm+void svm_destroy_model(struct svm_model *model_ptr); int clone_model_support_vectors(struct svm_model *model);