svmpredict.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "../svm.h"
5 
6 #include "mex.h"
7 #include "svm_model_matlab.h"
8 
9 #ifdef MX_API_VER
10 #if MX_API_VER < 0x07030000
11 typedef int mwIndex;
12 #endif
13 #endif
14 
15 #define CMD_LEN 2048
16 
17 int print_null(const char *s, ...) {}
18 int (*info)(const char *fmt, ...) = &mexPrintf;
19 
20 void read_sparse_instance(const mxArray *prhs, int index, struct svm_node *x)
21 {
22  int i, j, low, high;
23  mwIndex *ir, *jc;
24  double *samples;
25 
26  ir = mxGetIr(prhs);
27  jc = mxGetJc(prhs);
28  samples = mxGetPr(prhs);
29 
30  // each column is one instance
31  j = 0;
32  low = (int)jc[index], high = (int)jc[index + 1];
33  for (i = low; i < high; i++)
34  {
35  x[j].index = (int)ir[i] + 1;
36  x[j].value = samples[i];
37  j++;
38  }
39  x[j].index = -1;
40 }
41 
42 static void fake_answer(mxArray *plhs[])
43 {
44  plhs[0] = mxCreateDoubleMatrix(0, 0, mxREAL);
45  plhs[1] = mxCreateDoubleMatrix(0, 0, mxREAL);
46  plhs[2] = mxCreateDoubleMatrix(0, 0, mxREAL);
47 }
48 
49 void predict(mxArray *plhs[], const mxArray *prhs[], struct svm_model *model, const int predict_probability)
50 {
51  int label_vector_row_num, label_vector_col_num;
52  int feature_number, testing_instance_number;
53  int instance_index;
54  double *ptr_instance, *ptr_label, *ptr_predict_label;
55  double *ptr_prob_estimates, *ptr_dec_values, *ptr;
56  struct svm_node *x;
57  mxArray *pplhs[1]; // transposed instance sparse matrix
58 
59  int correct = 0;
60  int total = 0;
61  double error = 0;
62  double sump = 0, sumt = 0, sumpp = 0, sumtt = 0, sumpt = 0;
63 
64  int svm_type = svm_get_svm_type(model);
65  int nr_class = svm_get_nr_class(model);
66  double *prob_estimates = NULL;
67 
68  // prhs[1] = testing instance matrix
69  feature_number = (int)mxGetN(prhs[1]);
70  testing_instance_number = (int)mxGetM(prhs[1]);
71  label_vector_row_num = (int)mxGetM(prhs[0]);
72  label_vector_col_num = (int)mxGetN(prhs[0]);
73 
74  if (label_vector_row_num != testing_instance_number)
75  {
76  mexPrintf("Length of label vector does not match # of instances.\n");
77  fake_answer(plhs);
78  return;
79  }
80  if (label_vector_col_num != 1)
81  {
82  mexPrintf("label (1st argument) should be a vector (# of column is 1).\n");
83  fake_answer(plhs);
84  return;
85  }
86 
87  ptr_instance = mxGetPr(prhs[1]);
88  ptr_label = mxGetPr(prhs[0]);
89 
90  // transpose instance matrix
91  if (mxIsSparse(prhs[1]))
92  {
93  if (model->param.kernel_type == PRECOMPUTED)
94  {
95  // precomputed kernel requires dense matrix, so we make one
96  mxArray *rhs[1], *lhs[1];
97  rhs[0] = mxDuplicateArray(prhs[1]);
98  if (mexCallMATLAB(1, lhs, 1, rhs, "full"))
99  {
100  mexPrintf("Error: cannot full testing instance matrix\n");
101  fake_answer(plhs);
102  return;
103  }
104  ptr_instance = mxGetPr(lhs[0]);
105  mxDestroyArray(rhs[0]);
106  }
107  else
108  {
109  mxArray *pprhs[1];
110  pprhs[0] = mxDuplicateArray(prhs[1]);
111  if (mexCallMATLAB(1, pplhs, 1, pprhs, "transpose"))
112  {
113  mexPrintf("Error: cannot transpose testing instance matrix\n");
114  fake_answer(plhs);
115  return;
116  }
117  }
118  }
119 
120  if (predict_probability)
121  {
122  if (svm_type == NU_SVR || svm_type == EPSILON_SVR)
123  info("Prob. model for test data: target value = predicted value + z,\nz: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma=%g\n", svm_get_svr_probability(model));
124  else
125  prob_estimates = (double *) malloc(nr_class * sizeof(double));
126  }
127 
128  plhs[0] = mxCreateDoubleMatrix(testing_instance_number, 1, mxREAL);
129  if (predict_probability)
130  {
131  // prob estimates are in plhs[2]
132  if (svm_type == C_SVC || svm_type == NU_SVC)
133  plhs[2] = mxCreateDoubleMatrix(testing_instance_number, nr_class, mxREAL);
134  else
135  plhs[2] = mxCreateDoubleMatrix(0, 0, mxREAL);
136  }
137  else
138  {
139  // decision values are in plhs[2]
140  if (svm_type == ONE_CLASS ||
141  svm_type == EPSILON_SVR ||
142  svm_type == NU_SVR ||
143  nr_class == 1) // if only one class in training data, decision values are still returned.
144  plhs[2] = mxCreateDoubleMatrix(testing_instance_number, 1, mxREAL);
145  else
146  plhs[2] = mxCreateDoubleMatrix(testing_instance_number, nr_class * (nr_class - 1) / 2, mxREAL);
147  }
148 
149  ptr_predict_label = mxGetPr(plhs[0]);
150  ptr_prob_estimates = mxGetPr(plhs[2]);
151  ptr_dec_values = mxGetPr(plhs[2]);
152  x = (struct svm_node*)malloc((feature_number + 1) * sizeof(struct svm_node));
153  for (instance_index = 0; instance_index < testing_instance_number; instance_index++)
154  {
155  int i;
156  double target_label, predict_label;
157 
158  target_label = ptr_label[instance_index];
159 
160  if (mxIsSparse(prhs[1]) && model->param.kernel_type != PRECOMPUTED) // prhs[1]^T is still sparse
161  read_sparse_instance(pplhs[0], instance_index, x);
162  else
163  {
164  for (i = 0; i < feature_number; i++)
165  {
166  x[i].index = i + 1;
167  x[i].value = ptr_instance[testing_instance_number * i + instance_index];
168  }
169  x[feature_number].index = -1;
170  }
171 
172  if (predict_probability)
173  {
174  if (svm_type == C_SVC || svm_type == NU_SVC)
175  {
176  predict_label = svm_predict_probability(model, x, prob_estimates);
177  ptr_predict_label[instance_index] = predict_label;
178  for (i = 0; i < nr_class; i++)
179  ptr_prob_estimates[instance_index + i * testing_instance_number] = prob_estimates[i];
180  }
181  else
182  {
183  predict_label = svm_predict(model, x);
184  ptr_predict_label[instance_index] = predict_label;
185  }
186  }
187  else
188  {
189  if (svm_type == ONE_CLASS ||
190  svm_type == EPSILON_SVR ||
191  svm_type == NU_SVR)
192  {
193  double res;
194  predict_label = svm_predict_values(model, x, &res);
195  ptr_dec_values[instance_index] = res;
196  }
197  else
198  {
199  double *dec_values = (double *) malloc(sizeof(double) * nr_class * (nr_class - 1) / 2);
200  predict_label = svm_predict_values(model, x, dec_values);
201  if (nr_class == 1)
202  ptr_dec_values[instance_index] = 1;
203  else
204  for (i = 0; i < (nr_class * (nr_class - 1)) / 2; i++)
205  ptr_dec_values[instance_index + i * testing_instance_number] = dec_values[i];
206  free(dec_values);
207  }
208  ptr_predict_label[instance_index] = predict_label;
209  }
210 
211  if (predict_label == target_label)
212  ++correct;
213  error += (predict_label - target_label) * (predict_label - target_label);
214  sump += predict_label;
215  sumt += target_label;
216  sumpp += predict_label * predict_label;
217  sumtt += target_label * target_label;
218  sumpt += predict_label * target_label;
219  ++total;
220  }
221  if (svm_type == NU_SVR || svm_type == EPSILON_SVR)
222  {
223  info("Mean squared error = %g (regression)\n", error / total);
224  info("Squared correlation coefficient = %g (regression)\n",
225  ((total * sumpt - sump * sumt) * (total * sumpt - sump * sumt)) /
226  ((total * sumpp - sump * sump) * (total * sumtt - sumt * sumt))
227  );
228  }
229  else
230  info("Accuracy = %g%% (%d/%d) (classification)\n",
231  (double)correct / total * 100, correct, total);
232 
233  // return accuracy, mean squared error, squared correlation coefficient
234  plhs[1] = mxCreateDoubleMatrix(3, 1, mxREAL);
235  ptr = mxGetPr(plhs[1]);
236  ptr[0] = (double)correct / total * 100;
237  ptr[1] = error / total;
238  ptr[2] = ((total * sumpt - sump * sumt) * (total * sumpt - sump * sumt)) /
239  ((total * sumpp - sump * sump) * (total * sumtt - sumt * sumt));
240 
241  free(x);
242  if (prob_estimates != NULL)
243  free(prob_estimates);
244 }
245 
247 {
248  mexPrintf(
249  "Usage: [predicted_label, accuracy, decision_values/prob_estimates] = svmpredict(testing_label_vector, testing_instance_matrix, model, 'libsvm_options')\n"
250  "Parameters:\n"
251  " model: SVM model structure from svmtrain.\n"
252  " libsvm_options:\n"
253  " -b probability_estimates: whether to predict probability estimates, 0 or 1 (default 0); one-class SVM not supported yet\n"
254  " -q : quiet mode (no outputs)\n"
255  "Returns:\n"
256  " predicted_label: SVM prediction output vector.\n"
257  " accuracy: a vector with accuracy, mean squared error, squared correlation coefficient.\n"
258  " prob_estimates: If selected, probability estimate vector.\n"
259  );
260 }
261 
262 void mexFunction(int nlhs, mxArray *plhs[],
263  int nrhs, const mxArray *prhs[])
264 {
265  int prob_estimate_flag = 0;
266  struct svm_model *model;
267  info = &mexPrintf;
268 
269  if (nrhs > 4 || nrhs < 3)
270  {
271  exit_with_help();
272  fake_answer(plhs);
273  return;
274  }
275 
276  if (!mxIsDouble(prhs[0]) || !mxIsDouble(prhs[1]))
277  {
278  mexPrintf("Error: label vector and instance matrix must be double\n");
279  fake_answer(plhs);
280  return;
281  }
282 
283  if (mxIsStruct(prhs[2]))
284  {
285  const char *error_msg;
286 
287  // parse options
288  if (nrhs == 4)
289  {
290  int i, argc = 1;
291  char cmd[CMD_LEN], *argv[CMD_LEN / 2];
292 
293  // put options in argv[]
294  mxGetString(prhs[3], cmd, mxGetN(prhs[3]) + 1);
295  if ((argv[argc] = strtok(cmd, " ")) != NULL)
296  while ((argv[++argc] = strtok(NULL, " ")) != NULL)
297  ;
298 
299  for (i = 1; i < argc; i++)
300  {
301  if (argv[i][0] != '-') break;
302  if ((++i >= argc) && argv[i - 1][1] != 'q')
303  {
304  exit_with_help();
305  fake_answer(plhs);
306  return;
307  }
308  switch (argv[i - 1][1])
309  {
310  case 'b':
311  prob_estimate_flag = atoi(argv[i]);
312  break;
313  case 'q':
314  i--;
315  info = &print_null;
316  break;
317  default:
318  mexPrintf("Unknown option: -%c\n", argv[i - 1][1]);
319  exit_with_help();
320  fake_answer(plhs);
321  return;
322  }
323  }
324  }
325 
326  model = matlab_matrix_to_model(prhs[2], &error_msg);
327  if (model == NULL)
328  {
329  mexPrintf("Error: can't read model: %s\n", error_msg);
330  fake_answer(plhs);
331  return;
332  }
333 
334  if (prob_estimate_flag)
335  {
336  if (svm_check_probability_model(model) == 0)
337  {
338  mexPrintf("Model does not support probabiliy estimates\n");
339  fake_answer(plhs);
341  return;
342  }
343  }
344  else
345  {
346  if (svm_check_probability_model(model) != 0)
347  info("Model supports probability estimates, but disabled in predicton.\n");
348  }
349 
350  predict(plhs, prhs, model, prob_estimate_flag);
351  // destroy model
353  }
354  else
355  {
356  mexPrintf("model file should be a struct array\n");
357  fake_answer(plhs);
358  }
359 
360  return;
361 }
void exit_with_help()
Definition: svmpredict.c:246
string cmd
Definition: easy.py:48
void read_sparse_instance(const mxArray *prhs, int index, struct svm_node *x)
Definition: svmpredict.c:20
Definition: svm.h:25
double value
Definition: svm.h:15
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
Definition: svmpredict.c:262
void predict(mxArray *plhs[], const mxArray *prhs[], struct svm_model *model, const int predict_probability)
Definition: svmpredict.c:49
Definition: svm.h:25
double svm_get_svr_probability(const svm_model *model)
Definition: svm.cpp:2499
Definition: svm.h:52
def svm_predict(y, x, m, options="")
Definition: svmutil.py:164
struct svm_node * x
Definition: svm-predict.c:12
Definition: svm.h:25
static void fake_answer(mxArray *plhs[])
Definition: svmpredict.c:42
int svm_get_nr_class(const svm_model *model)
Definition: svm.cpp:2475
int svm_check_probability_model(const svm_model *model)
Definition: svm.cpp:3150
int(* info)(const char *fmt,...)
Definition: svmpredict.c:18
int predict_probability
Definition: svm-predict.c:16
struct svm_model * matlab_matrix_to_model(const mxArray *matlab_struct, const char **msg)
void svm_free_and_destroy_model(svm_model **model_ptr_ptr)
Definition: svm.cpp:3013
double svm_predict_values(const svm_model *model, const svm_node *x, double *dec_values)
Definition: svm.cpp:2511
double svm_predict_probability(const svm_model *model, const svm_node *x, double *prob_estimates)
Definition: svm.cpp:2602
struct svm_parameter param
Definition: svm.h:54
#define CMD_LEN
Definition: svmpredict.c:15
int index
Definition: svm.h:14
int svm_get_svm_type(const svm_model *model)
Definition: svm.cpp:2470
Definition: svm.h:25
Definition: svm.h:12
int print_null(const char *s,...)
Definition: svmpredict.c:17
struct svm_model * model
Definition: svmtrain.c:61
int kernel_type
Definition: svm.h:31


ml_classifiers
Author(s): Scott Niekum , Joshua Whitley
autogenerated on Mon Feb 28 2022 22:46:49