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 +218/−154
- HSvm.cabal +1/−1
- cbits/svm.cpp +149/−22
- cbits/svm.h +3/−2
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);