Mercurial > forge
changeset 12589:06a805605e9a octave-forge
[nan] upgrade libsvm to v3.12
author | schloegl |
---|---|
date | Sun, 12 Apr 2015 14:37:46 +0000 |
parents | 3f24658504ab |
children | fae7c16ebcb4 |
files | extra/NaN/src/svm.cpp extra/NaN/src/svm.h extra/NaN/src/svm_model_matlab.c extra/NaN/src/svmpredict_mex.cpp extra/NaN/src/svmtrain_mex.cpp |
diffstat | 5 files changed, 198 insertions(+), 154 deletions(-) [+] |
line wrap: on
line diff
--- a/extra/NaN/src/svm.cpp Thu Apr 09 17:43:15 2015 +0000 +++ b/extra/NaN/src/svm.cpp Sun Apr 12 14:37:46 2015 +0000 @@ -1,13 +1,11 @@ /* - -$Id$ -Copyright (c) 2000-2009 Chih-Chung Chang and Chih-Jen Lin -Copyright (c) 2010 Alois Schloegl <alois.schloegl@gmail.com> +Copyright (c) 2000-2012 Chih-Chung Chang and Chih-Jen Lin +Copyright (c) 2010,2011,2015 Alois Schloegl <alois.schloegl@ist.ac.at> This function is part of the NaN-toolbox http://pub.ist.ac.at/~schloegl/matlab/NaN/ -This code was extracted from libsvm-mat-2.9-1 in Jan 2010 and +This code was extracted from libsvm-3.12 in Apr 2015 and modified for the use with Octave This program is free software; you can redistribute it and/or modify @@ -32,6 +30,8 @@ #include <float.h> #include <string.h> #include <stdarg.h> +#include <limits.h> +#include <locale.h> #include "svm.h" int libsvm_version = LIBSVM_VERSION; @@ -69,7 +69,7 @@ fputs(s,stdout); fflush(stdout); } -void (*svm_print_string) (const char *) = &print_string_stdout; +static void (*svm_print_string) (const char *) = &print_string_stdout; #if 1 static void info(const char *fmt,...) { @@ -220,7 +220,7 @@ class QMatrix { public: virtual Qfloat *get_Q(int column, int len) const = 0; - virtual Qfloat *get_QD() const = 0; + virtual double *get_QD() const = 0; virtual void swap_index(int i, int j) const = 0; virtual ~QMatrix() {} }; @@ -233,7 +233,7 @@ static double k_function(const svm_node *x, const svm_node *y, const svm_parameter& param); virtual Qfloat *get_Q(int column, int len) const = 0; - virtual Qfloat *get_QD() const = 0; + virtual double *get_QD() const = 0; virtual void swap_index(int i, int j) const // no so const... { swap(x[i],x[j]); @@ -440,7 +440,7 @@ char *alpha_status; // LOWER_BOUND, UPPER_BOUND, FREE double *alpha; const QMatrix *Q; - const Qfloat *QD; + const double *QD; double eps; double Cp,Cn; double *p; @@ -502,7 +502,7 @@ nr_free++; if(2*nr_free < active_size) - info("\nWarning: using -h 0 may be faster\n"); + info("\nWARNING: using -h 0 may be faster\n"); if (nr_free*l > 2*active_size*(l-active_size)) { @@ -584,9 +584,10 @@ // optimization step int iter = 0; + int max_iter = max(10000000, l>INT_MAX/100 ? INT_MAX : 100*l); int counter = min(l,1000)+1; - - while(1) + + while(iter < max_iter) { // show progress and do shrinking @@ -626,7 +627,7 @@ if(y[i]!=y[j]) { - double quad_coef = Q_i[i]+Q_j[j]+2*Q_i[j]; + double quad_coef = QD[i]+QD[j]+2*Q_i[j]; if (quad_coef <= 0) quad_coef = TAU; double delta = (-G[i]-G[j])/quad_coef; @@ -669,7 +670,7 @@ } else { - double quad_coef = Q_i[i]+Q_j[j]-2*Q_i[j]; + double quad_coef = QD[i]+QD[j]-2*Q_i[j]; if (quad_coef <= 0) quad_coef = TAU; double delta = (G[i]-G[j])/quad_coef; @@ -753,6 +754,18 @@ } } + if(iter >= max_iter) + { + if(active_size < l) + { + // reconstruct the whole gradient to calculate objective value + reconstruct_gradient(); + active_size = l; + info("*"); + } + info("\nWARNING: reaching max number of iterations"); + } + // calculate rho si->rho = calculate_rho(); @@ -847,7 +860,7 @@ if (grad_diff > 0) { double obj_diff; - double quad_coef=Q_i[i]+QD[j]-2.0*y[i]*Q_i[j]; + double quad_coef = QD[i]+QD[j]-2.0*y[i]*Q_i[j]; if (quad_coef > 0) obj_diff = -(grad_diff*grad_diff)/quad_coef; else @@ -871,7 +884,7 @@ if (grad_diff > 0) { double obj_diff; - double quad_coef=Q_i[i]+QD[j]+2.0*y[i]*Q_i[j]; + double quad_coef = QD[i]+QD[j]+2.0*y[i]*Q_i[j]; if (quad_coef > 0) obj_diff = -(grad_diff*grad_diff)/quad_coef; else @@ -1099,7 +1112,7 @@ if (grad_diff > 0) { double obj_diff; - double quad_coef = Q_ip[ip]+QD[j]-2*Q_ip[j]; + double quad_coef = QD[ip]+QD[j]-2*Q_ip[j]; if (quad_coef > 0) obj_diff = -(grad_diff*grad_diff)/quad_coef; else @@ -1123,7 +1136,7 @@ if (grad_diff > 0) { double obj_diff; - double quad_coef = Q_in[in]+QD[j]-2*Q_in[j]; + double quad_coef = QD[in]+QD[j]-2*Q_in[j]; if (quad_coef > 0) obj_diff = -(grad_diff*grad_diff)/quad_coef; else @@ -1284,9 +1297,9 @@ { clone(y,y_,prob.l); cache = new Cache(prob.l,(long int)(param.cache_size*(1<<20))); - QD = new Qfloat[prob.l]; + QD = new double[prob.l]; for(int i=0;i<prob.l;i++) - QD[i]= (Qfloat)(this->*kernel_function)(i,i); + QD[i] = (this->*kernel_function)(i,i); } Qfloat *get_Q(int i, int len) const @@ -1301,7 +1314,7 @@ return data; } - Qfloat *get_QD() const + double *get_QD() const { return QD; } @@ -1323,7 +1336,7 @@ private: schar *y; Cache *cache; - Qfloat *QD; + double *QD; }; class ONE_CLASS_Q: public Kernel @@ -1333,9 +1346,9 @@ :Kernel(prob.l, prob.x, param) { cache = new Cache(prob.l,(long int)(param.cache_size*(1<<20))); - QD = new Qfloat[prob.l]; + QD = new double[prob.l]; for(int i=0;i<prob.l;i++) - QD[i]= (Qfloat)(this->*kernel_function)(i,i); + QD[i] = (this->*kernel_function)(i,i); } Qfloat *get_Q(int i, int len) const @@ -1350,7 +1363,7 @@ return data; } - Qfloat *get_QD() const + double *get_QD() const { return QD; } @@ -1369,7 +1382,7 @@ } private: Cache *cache; - Qfloat *QD; + double *QD; }; class SVR_Q: public Kernel @@ -1380,7 +1393,7 @@ { l = prob.l; cache = new Cache(l,(long int)(param.cache_size*(1<<20))); - QD = new Qfloat[2*l]; + QD = new double[2*l]; sign = new schar[2*l]; index = new int[2*l]; for(int k=0;k<l;k++) @@ -1389,8 +1402,8 @@ sign[k+l] = -1; index[k] = k; index[k+l] = k; - QD[k]= (Qfloat)(this->*kernel_function)(k,k); - QD[k+l]=QD[k]; + QD[k] = (this->*kernel_function)(k,k); + QD[k+l] = QD[k]; } buffer[0] = new Qfloat[2*l]; buffer[1] = new Qfloat[2*l]; @@ -1423,7 +1436,7 @@ return buf; } - Qfloat *get_QD() const + double *get_QD() const { return QD; } @@ -1444,7 +1457,7 @@ int *index; mutable int next_buffer; Qfloat *buffer[2]; - Qfloat *QD; + double *QD; }; // @@ -1464,7 +1477,7 @@ { alpha[i] = 0; minus_ones[i] = -1; - if(prob->y[i] > 0) y[i] = +1; else y[i]=-1; + if(prob->y[i] > 0) y[i] = +1; else y[i] = -1; } Solver s; @@ -1714,31 +1727,6 @@ return f; } -// -// svm_model -// -/* -struct svm_model -{ - svm_parameter param; // parameter - int nr_class; // number of classes, = 2 in regression/one class svm - int l; // total #SV - svm_node **SV; // SVs (SV[l]) - double **sv_coef; // coefficients for SVs in decision functions (sv_coef[k-1][l]) - double *rho; // constants in decision functions (rho[k*(k-1)/2]) - double *probA; // pariwise probability information - double *probB; - - // for classification only - - int *label; // label of each class (label[k]) - int *nSV; // number of SVs for each class (nSV[k]) - // nSV[0] + nSV[1] + ... + nSV[k-1] = l - // XXX - int free_sv; // 1 if svm_model is created by svm_load_model - // 0 if svm_model is created by svm_train -}; -*/ // Platt's binary SVM Probablistic Output: an improvement from Lin et al. static void sigmoid_train( int l, const double *dec_values, const double *labels, @@ -1856,6 +1844,7 @@ static double sigmoid_predict(double decision_value, double A, double B) { double fApB = decision_value*A+B; + // 1-p used later; avoid catastrophic cancellation if (fApB >= 0) return exp(-fApB)/(1.0+exp(-fApB)); else @@ -2002,7 +1991,7 @@ // ensure +1 -1 order; reason not using CV subroutine dec_values[perm[j]] *= submodel->label[0]; } - svm_destroy_model(submodel); + svm_free_and_destroy_model(&submodel); svm_destroy_param(&subparam); } free(subprob.x); @@ -2166,7 +2155,10 @@ int *perm = Malloc(int,l); // group training data of the same class - svm_group_classes(prob,&nr_class,&label,&start,&count,perm); + svm_group_classes(prob,&nr_class,&label,&start,&count,perm); + if(nr_class == 1) + info("WARNING: training data in only one class. See README for details.\n"); + svm_node **x = Malloc(svm_node *,l); int i; for(i=0;i<l;i++) @@ -2184,7 +2176,7 @@ if(param->weight_label[i] == label[j]) break; if(j == nr_class) - fprintf(stderr,"warning: class label %d specified in weight is not found\n", param->weight_label[i]); + fprintf(stderr,"WARNING: class label %d specified in weight is not found\n", param->weight_label[i]); else weighted_C[j] *= param->weight[i]; } @@ -2452,7 +2444,7 @@ else for(j=begin;j<end;j++) target[perm[j]] = svm_predict(submodel,prob->x[perm[j]]); - svm_destroy_model(submodel); + svm_free_and_destroy_model(&submodel); free(subprob.x); free(subprob.y); } @@ -2490,22 +2482,27 @@ } } -void svm_predict_values(const svm_model *model, const svm_node *x, double* dec_values) +double svm_predict_values(const svm_model *model, const svm_node *x, double* dec_values) { + int i; if(model->param.svm_type == ONE_CLASS || model->param.svm_type == EPSILON_SVR || model->param.svm_type == NU_SVR) { double *sv_coef = model->sv_coef[0]; double sum = 0; - for(int i=0;i<model->l;i++) + for(i=0;i<model->l;i++) sum += sv_coef[i] * Kernel::k_function(x,model->SV[i],model->param); sum -= model->rho[0]; *dec_values = sum; + + if(model->param.svm_type == ONE_CLASS) + return (sum>0)?1:-1; + else + return sum; } else { - int i; int nr_class = model->nr_class; int l = model->l; @@ -2518,6 +2515,10 @@ for(i=1;i<nr_class;i++) start[i] = start[i-1]+model->nSV[i-1]; + int *vote = Malloc(int,nr_class); + for(i=0;i<nr_class;i++) + vote[i] = 0; + int p=0; for(i=0;i<nr_class;i++) for(int j=i+1;j<nr_class;j++) @@ -2537,58 +2538,41 @@ sum += coef2[sj+k] * kvalue[sj+k]; sum -= model->rho[p]; dec_values[p] = sum; - p++; - } - free(kvalue); - free(start); - } -} - -double svm_predict(const svm_model *model, const svm_node *x) -{ - if(model->param.svm_type == ONE_CLASS || - model->param.svm_type == EPSILON_SVR || - model->param.svm_type == NU_SVR) - { - double res; - svm_predict_values(model, x, &res); - - if(model->param.svm_type == ONE_CLASS) - return (res>0)?1:-1; - else - return res; - } - else - { - int i; - int nr_class = model->nr_class; - double *dec_values = Malloc(double, nr_class*(nr_class-1)/2); - svm_predict_values(model, x, dec_values); - - int *vote = Malloc(int,nr_class); - for(i=0;i<nr_class;i++) - vote[i] = 0; - int pos=0; - for(i=0;i<nr_class;i++) - for(int j=i+1;j<nr_class;j++) - { - if(dec_values[pos++] > 0) + if(dec_values[p] > 0) ++vote[i]; else ++vote[j]; + p++; } int vote_max_idx = 0; for(i=1;i<nr_class;i++) if(vote[i] > vote[vote_max_idx]) vote_max_idx = i; + + free(kvalue); + free(start); free(vote); - free(dec_values); return model->label[vote_max_idx]; } } +double svm_predict(const svm_model *model, const svm_node *x) +{ + int nr_class = model->nr_class; + double *dec_values; + if(model->param.svm_type == ONE_CLASS || + model->param.svm_type == EPSILON_SVR || + model->param.svm_type == NU_SVR) + dec_values = Malloc(double, 1); + else + dec_values = Malloc(double, nr_class*(nr_class-1)/2); + double pred_result = svm_predict_values(model, x, dec_values); + free(dec_values); + return pred_result; +} + double svm_predict_probability( const svm_model *model, const svm_node *x, double *prob_estimates) { @@ -2643,6 +2627,9 @@ FILE *fp = fopen(model_file_name,"w"); if(fp==NULL) return -1; + char *old_locale = strdup(setlocale(LC_ALL, NULL)); + setlocale(LC_ALL, "C"); + const svm_parameter& param = model->param; fprintf(fp,"svm_type %s\n", svm_type_table[param.svm_type]); @@ -2721,6 +2708,10 @@ } fprintf(fp, "\n"); } + + setlocale(LC_ALL, old_locale); + free(old_locale); + if (ferror(fp) != 0 || fclose(fp) != 0) return -1; else return 0; } @@ -2750,7 +2741,10 @@ { FILE *fp = fopen(model_file_name,"rb"); if(fp==NULL) return NULL; - + + char *old_locale = strdup(setlocale(LC_ALL, NULL)); + setlocale(LC_ALL, "C"); + // read parameters svm_model *model = Malloc(svm_model,1); @@ -2781,6 +2775,9 @@ if(svm_type_table[i] == NULL) { fprintf(stderr,"unknown svm type.\n"); + + setlocale(LC_ALL, old_locale); + free(old_locale); free(model->rho); free(model->label); free(model->nSV); @@ -2803,6 +2800,9 @@ if(kernel_type_table[i] == NULL) { fprintf(stderr,"unknown kernel function.\n"); + + setlocale(LC_ALL, old_locale); + free(old_locale); free(model->rho); free(model->label); free(model->nSV); @@ -2867,6 +2867,9 @@ else { fprintf(stderr,"unknown text in model file: [%s]\n",cmd); + + setlocale(LC_ALL, old_locale); + free(old_locale); free(model->rho); free(model->label); free(model->nSV); @@ -2939,6 +2942,9 @@ } free(line); + setlocale(LC_ALL, old_locale); + free(old_locale); + if (ferror(fp) != 0 || fclose(fp) != 0) return NULL; @@ -2946,20 +2952,46 @@ return model; } -void svm_destroy_model(svm_model* model) +void svm_free_model_content(svm_model* model_ptr) { - if(model->free_sv && model->l > 0) - free((void *)(model->SV[0])); - for(int i=0;i<model->nr_class-1;i++) - free(model->sv_coef[i]); - free(model->SV); - free(model->sv_coef); - free(model->rho); - free(model->label); - free(model->probA); - free(model->probB); - free(model->nSV); - free(model); + if(model_ptr->free_sv && model_ptr->l > 0 && model_ptr->SV != NULL) + free((void *)(model_ptr->SV[0])); + if(model_ptr->sv_coef) + { + for(int i=0;i<model_ptr->nr_class-1;i++) + free(model_ptr->sv_coef[i]); + } + + free(model_ptr->SV); + model_ptr->SV = NULL; + + free(model_ptr->sv_coef); + model_ptr->sv_coef = NULL; + + free(model_ptr->rho); + model_ptr->rho = NULL; + + free(model_ptr->label); + model_ptr->label= NULL; + + free(model_ptr->probA); + model_ptr->probA = NULL; + + free(model_ptr->probB); + model_ptr->probB= NULL; + + free(model_ptr->nSV); + model_ptr->nSV = NULL; +} + +void svm_free_and_destroy_model(svm_model** model_ptr_ptr) +{ + if(model_ptr_ptr != NULL && *model_ptr_ptr != NULL) + { + svm_free_model_content(*model_ptr_ptr); + free(*model_ptr_ptr); + *model_ptr_ptr = NULL; + } } void svm_destroy_param(svm_parameter* param) @@ -3096,3 +3128,11 @@ ((model->param.svm_type == EPSILON_SVR || model->param.svm_type == NU_SVR) && model->probA!=NULL); } + +void svm_set_print_string_function(void (*print_func)(const char *)) +{ + if(print_func == NULL) + svm_print_string = &print_string_stdout; + else + svm_print_string = print_func; +}
--- a/extra/NaN/src/svm.h Thu Apr 09 17:43:15 2015 +0000 +++ b/extra/NaN/src/svm.h Sun Apr 12 14:37:46 2015 +0000 @@ -1,10 +1,12 @@ /* -This code was extracted from libsvm-mat-2.9-1 in Jan 2010 -Copyright (C) 2010 Alois Schloegl <alois.schloegl@gmail.com> + +This code was extracted from libsvm-3.12 in Apr 2015 and +modified for the use with Octave +Copyright (c) 2010,2011,2015 Alois Schloegl <alois.schloegl@ist.ac.at> This function is part of the NaN-toolbox http://pub.ist.ac.at/~schloegl/matlab/NaN/ -Copyright (c) 2000-2009 Chih-Chung Chang and Chih-Jen Lin +Copyright (c) 2000-2012 Chih-Chung Chang and Chih-Jen Lin All rights reserved. Redistribution and use in source and binary forms, with or without @@ -42,7 +44,7 @@ #ifndef _LIBSVM_H #define _LIBSVM_H -#define LIBSVM_VERSION 290 +#define LIBSVM_VERSION 312 #ifdef __cplusplus extern "C" { @@ -87,6 +89,9 @@ int probability; /* do probability estimates */ }; +// +// svm_model +// struct svm_model { struct svm_parameter param; /* parameter */ @@ -119,17 +124,18 @@ void svm_get_labels(const struct svm_model *model, int *label); double svm_get_svr_probability(const struct svm_model *model); -void svm_predict_values(const struct svm_model *model, const struct svm_node *x, double* dec_values); +double svm_predict_values(const struct svm_model *model, const struct svm_node *x, double* dec_values); 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); +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); const char *svm_check_parameter(const struct svm_problem *prob, const struct svm_parameter *param); int svm_check_probability_model(const struct svm_model *model); -extern void (*svm_print_string) (const char *); +void svm_set_print_string_function(void (*print_func)(const char *)); #ifdef __cplusplus }
--- a/extra/NaN/src/svm_model_matlab.c Thu Apr 09 17:43:15 2015 +0000 +++ b/extra/NaN/src/svm_model_matlab.c Sun Apr 12 14:37:46 2015 +0000 @@ -372,7 +372,7 @@ pprhs[0] = rhs[id]; if(mexCallMATLAB(1, pplhs, 1, pprhs, "transpose")) { - svm_destroy_model(model); + svm_free_and_destroy_model(model); *msg = "cannot transpose SV matrix"; return NULL; }
--- a/extra/NaN/src/svmpredict_mex.cpp Thu Apr 09 17:43:15 2015 +0000 +++ b/extra/NaN/src/svmpredict_mex.cpp Sun Apr 12 14:37:46 2015 +0000 @@ -1,12 +1,12 @@ /* $Id$ -Copyright (c) 2000-2009 Chih-Chung Chang and Chih-Jen Lin -Copyright (c) 2010,2011 Alois Schloegl <alois.schloegl@gmail.com> +Copyright (c) 2000-2012 Chih-Chung Chang and Chih-Jen Lin +Copyright (c) 2010,2011,2015 Alois Schloegl <alois.schloegl@ist.ac.at> This function is part of the NaN-toolbox http://pub.ist.ac.at/~schloegl/matlab/NaN/ -This code was extracted from libsvm-mat-2.9-1 in Jan 2010 and +This code was extracted from libsvm-3.12 in Apr 2015 and modified for the use with Octave This program is free software; you can redistribute it and/or modify @@ -164,7 +164,8 @@ // decision values are in plhs[2] if(svm_type == ONE_CLASS || svm_type == EPSILON_SVR || - svm_type == NU_SVR) + svm_type == NU_SVR || + nr_class == 1) // if only one class in training data, decision values are still returned. plhs[2] = mxCreateDoubleMatrix(testing_instance_number, 1, mxREAL); else plhs[2] = mxCreateDoubleMatrix(testing_instance_number, nr_class*(nr_class-1)/2, mxREAL); @@ -208,25 +209,26 @@ } else { - predict_label = svm_predict(model,x); - ptr_predict_label[instance_index] = predict_label; - if(svm_type == ONE_CLASS || svm_type == EPSILON_SVR || svm_type == NU_SVR) { double res; - svm_predict_values(model, x, &res); + predict_label = svm_predict_values(model, x, &res); ptr_dec_values[instance_index] = res; } else { double *dec_values = (double *) malloc(sizeof(double) * nr_class*(nr_class-1)/2); - svm_predict_values(model, x, dec_values); - for(i=0;i<(nr_class*(nr_class-1))/2;i++) - ptr_dec_values[instance_index + i * testing_instance_number] = dec_values[i]; + predict_label = svm_predict_values(model, x, dec_values); + if(nr_class == 1) + ptr_dec_values[instance_index] = 1; + else + for(i=0;i<(nr_class*(nr_class-1))/2;i++) + ptr_dec_values[instance_index + i * testing_instance_number] = dec_values[i]; free(dec_values); } + ptr_predict_label[instance_index] = predict_label; } if(predict_label == target_label) @@ -239,9 +241,7 @@ sumpt += predict_label*target_label; ++total; } - if (1) - ; // avoid output to command line - else if(svm_type==NU_SVR || svm_type==EPSILON_SVR) + if(svm_type==NU_SVR || svm_type==EPSILON_SVR) { mexPrintf("Mean squared error = %g (regression)\n",error/total); mexPrintf("Squared correlation coefficient = %g (regression)\n", @@ -269,7 +269,7 @@ void exit_with_help() { mexPrintf( - "Usage: [predicted_label, accuracy, decision_values/prob_estimates] = svmpredict(testing_label_vector, testing_instance_matrix, model, 'libsvm_options')\n" + "Usage: [predicted_label, accuracy, decision_values/prob_estimates] = svmpredict_mex(testing_label_vector, testing_instance_matrix, model, 'libsvm_options')\n" "Parameters:\n" " model: SVM model structure from svmtrain.\n" " libsvm_options:\n" @@ -353,19 +353,19 @@ { mexPrintf("Model does not support probabiliy estimates\n"); fake_answer(plhs); - svm_destroy_model(model); + svm_free_and_destroy_model(&model); return; } } else { if(svm_check_probability_model(model)!=0) - printf("Model supports probability estimates, but disabled in predicton.\n"); + mexPrintf("Model supports probability estimates, but disabled in predicton.\n"); } predict(plhs, prhs, model, prob_estimate_flag); // destroy model - svm_destroy_model(model); + svm_free_and_destroy_model(&model); } else {
--- a/extra/NaN/src/svmtrain_mex.cpp Thu Apr 09 17:43:15 2015 +0000 +++ b/extra/NaN/src/svmtrain_mex.cpp Sun Apr 12 14:37:46 2015 +0000 @@ -1,12 +1,12 @@ /* $Id$ -Copyright (c) 2000-2009 Chih-Chung Chang and Chih-Jen Lin -Copyright (c) 2010 Alois Schloegl <alois.schloegl@gmail.com> +Copyright (c) 2000-2012 Chih-Chung Chang and Chih-Jen Lin +Copyright (c) 2010,2015 Alois Schloegl <alois.schloegl@ist.ac.at> This function is part of the NaN-toolbox http://pub.ist.ac.at/~schloegl/matlab/NaN/ -This code was extracted from libsvm-mat-2.9-1 in Jan 2010 and +This code was extracted from libsvm-3.12 in Apr 2015 and modified for the use with Octave This program is free software; you can redistribute it and/or modify @@ -45,6 +45,7 @@ #define Malloc(type,n) (type *)malloc((n)*sizeof(type)) void print_null(const char *s) {} +void print_string_matlab(const char *s) {mexPrintf(s);} void exit_with_help() { @@ -87,7 +88,6 @@ int cross_validation; int nr_fold; -void (*svm_default_print_string) (const char *) = NULL; double do_cross_validation() { @@ -138,6 +138,7 @@ int i, argc = 1; char cmd[CMD_LEN]; char *argv[CMD_LEN/2]; + void (*print_func)(const char *) = print_string_matlab; // default printing to matlab display // default values param.svm_type = C_SVC; @@ -156,12 +157,6 @@ param.weight_label = NULL; param.weight = NULL; cross_validation = 0; - // svmtrain loaded only once under matlab - if (svm_default_print_string == NULL) - svm_default_print_string = svm_print_string; - else - svm_print_string = svm_default_print_string; - if(nrhs <= 1) return 1; @@ -221,7 +216,7 @@ param.probability = atoi(argv[i]); break; case 'q': - svm_print_string = &print_null; + print_func = &print_null; i--; break; case 'v': @@ -245,6 +240,9 @@ return 1; } } + + svm_set_print_string_function(print_func); + return 0; } @@ -415,7 +413,7 @@ srand(1); // Transform the input Matrix to libsvm format - if(nrhs > 0 && nrhs < 4) + if(nrhs > 1 && nrhs < 4) { int err; @@ -488,7 +486,7 @@ error_msg = model_to_matlab_structure(plhs, nr_feat, model); if(error_msg) mexPrintf("Error: can't convert libsvm model to matrix structure: %s\n", error_msg); - svm_destroy_model(model); + svm_free_and_destroy_model(&model); } svm_destroy_param(¶m); free(prob.y);