Point Cloud Library (PCL)  1.14.1-dev
svm_wrapper.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2012, Willow Garage, Inc.
6  * Copyright (c) 2000-2012 Chih-Chung Chang and Chih-Jen Lin
7  *
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * * Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * * Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  * * Neither the name of copyright holders nor the names of its
21  * contributors may be used to endorse or promote products derived
22  * from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  */
38 
39 #pragma once
40 
41 #include <pcl/console/print.h> // for PCL_ERROR
42 #include <pcl/ml/svm.h>
43 
44 #include <cassert> // for assert
45 #include <cstdio>
46 #include <cstdlib>
47 #include <limits> // for numeric_limits
48 #include <string> // for string
49 #include <vector>
50 // NOLINTNEXTLINE(bugprone-macro-parentheses)
51 #define Malloc(type, n) static_cast<type*>(malloc((n) * sizeof(type)))
52 
53 namespace pcl {
54 
55 /** The structure stores the parameters for the classificationa nd must be initialized
56  * and passed to the training method pcl::SVMTrain.
57  *
58  * \param svm_type {C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR}
59  * \param kernel_type {LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED}
60  * \param probability sets the probability estimates
61  */
64  {
65  svm_type = C_SVC; // C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR
66  kernel_type = RBF; // LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED
67  degree = 3; // for poly
68  gamma = 0; // 1/num_features {for poly/rbf/sigmoid}
69  coef0 = 0; // for poly/sigmoid
70 
71  nu = 0.5; // for NU_SVC, ONE_CLASS, and NU_SVR
72  cache_size = 100; // in MB
73  C = 1; // for C_SVC, EPSILON_SVR and NU_SVR
74  eps = 1e-3; // stopping criteria
75  p = 0.1; // for EPSILON_SVR
76  shrinking = 0; // use the shrinking heuristics
77  probability = 0; // do probability estimates
78 
79  nr_weight = 0; // for C_SVC
80  weight_label = nullptr; // for C_SVC
81  weight = nullptr; // for C_SVC
82  }
83 };
84 
85 /** The structure initialize a model created by the SVM (Support Vector Machines)
86  * classifier (pcl::SVMTrain).
87  */
88 struct SVMModel : svm_model {
90  {
91  l = 0;
92  probA = nullptr;
93  probB = nullptr;
94  }
95 };
96 
97 /** The structure initialize a single feature value for the classification using
98  * SVM (Support Vector Machines).
99  */
100 struct SVMDataPoint {
101  /// It's the feature index. It has to be an integer number greater or equal to zero
102  int idx{-1};
103  /// The value assigned to the correspondent feature.
104  float value{0.0f};
105 
106  SVMDataPoint() = default;
107 };
108 
109 /** The structure stores the features and the label of a single sample which has to be
110  * used for the training or the classification of the SVM (Support Vector Machines).
111  */
112 struct SVMData {
113  /// Pointer to the label value. It is a mandatory to train the classifier
114  double label;
115  /// Vector of features for the specific sample.
116  std::vector<pcl::SVMDataPoint> SV;
117 
118  SVMData() : label(std::numeric_limits<double>::signaling_NaN()) {}
119 };
120 
121 /** Base class for SVM SVM (Support Vector Machines). */
122 class SVM {
123 protected:
124  std::vector<SVMData> training_set_; // Basic training set
125  svm_problem prob_; // contains the problem (vector of samples with their features)
126  SVMModel model_; // model of the classifier
127  svm_scaling scaling_; // for the best model training, the input dataset is scaled and
128  // the scaling factors are stored here
129  SVMParam param_; // it stores the training parameters
130  std::string class_name_; // The SVM class name.
131 
132  char* line_{nullptr}; // buffer for line reading
133  int max_line_len_{10000}; // max line length in the input file
135  true}; // it stores whether the input set of samples is labelled
136 
137  /** Set for output printings during classification. */
138  static void
139  printNull(const char*){};
140 
141  /** To read a line from the input file. Stored in "line_". */
142  char*
143  readline(FILE* input);
144 
145  /** Outputs an error in file reading. */
146  void
147  exitInputError(int line_num)
148  {
149  fprintf(stderr, "Wrong input format at line %d\n", line_num);
150  exit(1);
151  }
152 
153  /** Get a string representation of the name of this class. */
154  inline const std::string&
155  getClassName() const
156  {
157  return (class_name_);
158  }
159 
160  /** Convert the input format (vector of SVMData) into a readable format for libSVM. */
161  void
162  adaptInputToLibSVM(std::vector<SVMData> training_set, svm_problem& prob);
163 
164  /** Convert the libSVM format (svm_problem) into a easier output format. */
165  void
166  adaptLibSVMToInput(std::vector<SVMData>& training_set, svm_problem prob) const;
167 
168  /** Load a problem from an extern file. */
169  bool
170  loadProblem(const char* filename, svm_problem& prob);
171 
172  /** Save the raw problem in an extern file.*/
173  bool
174  saveProblem(const char* filename, bool labelled);
175 
176  /** Save the problem (with normalized values) in an extern file.*/
177  bool
178  saveProblemNorm(const char* filename, svm_problem prob_, bool labelled);
179 
180 public:
181  /** Constructor. */
182  SVM() : prob_() {}
183 
184  /** Destructor. */
186  {
187  svm_destroy_param(&param_); // delete parameters
188 
189  if (scaling_.max > 0)
190  free(scaling_.obj); // delete scaling factors
191 
192  // delete the problem
193  if (prob_.l > 0) {
194  free(prob_.x);
195  free(prob_.y);
196  }
197  }
198 
199  /** Return the labels order from the classifier model. */
200  void
201  getLabel(std::vector<int>& labels)
202  {
203  int nr_class = svm_get_nr_class(&model_);
204  int* labels_ = static_cast<int*>(malloc(nr_class * sizeof(int)));
205  svm_get_labels(&model_, labels_);
206 
207  for (int j = 0; j < nr_class; j++)
208  labels.push_back(labels_[j]);
209 
210  free(labels_);
211  };
212 
213  /** Save the classifier model in an extern file (in svmlight format). */
214  void
215  saveClassifierModel(const char* filename)
216  {
217  // exit if model has no data
218  if (model_.l == 0)
219  return;
220 
221  if (svm_save_model(filename, &model_)) {
222  fprintf(stderr, "can't save model to file %s\n", filename);
223  exit(1);
224  }
225  };
226 };
227 
228 /** SVM (Support Vector Machines) training class for the SVM machine learning.
229  *
230  * It creates a model for the classifier from a labelled input dataset.
231  *
232  * OPTIONAL: pcl::SVMParam has to be given as input to vary the default training method
233  * and parameters.
234  */
235 class SVMTrain : public SVM {
236 protected:
237  using SVM::class_name_;
239  using SVM::line_;
240  using SVM::max_line_len_;
241  using SVM::model_;
242  using SVM::param_;
243  using SVM::prob_;
244  using SVM::scaling_;
245  using SVM::training_set_;
246 
247  /// Set to 1 to see the training output
248  bool debug_{false};
249  /// Set too 1 for cross validating the classifier
251  /// Number of folds to be used during cross validation. It indicates in how many parts
252  /// is split the input training set.
253  int nr_fold_{0};
254 
255  /** To cross validate the classifier. It is automatic for probability estimate. */
256  void
258 
259  /** It extracts scaling factors from the input training_set.
260  *
261  * The scaling of the training_set is a mandatory for a good training of the
262  * classifier. */
263  void
264  scaleFactors(std::vector<SVMData> training_set, svm_scaling& scaling);
265 
266 public:
267  /** Constructor. */
269  {
270  class_name_ = "SVMTrain";
271  svm_set_print_string_function(
272  &printNull); // Default to NULL to not print debugging info
273  }
274 
275  /** Destructor. */
277  {
278  if (model_.l > 0)
279  svm_free_model_content(&model_);
280  }
281 
282  /** Change default training parameters (pcl::SVMParam). */
283  void
285  {
286  param_ = param;
287  }
288 
289  /** Return the current training parameters. */
290  SVMParam
292  {
293  return param_;
294  }
295 
296  /** Return the result of the training. */
297  SVMModel
299  {
300  return model_;
301  }
302 
303  /** It adds/store the training set with labelled data. */
304  void
305  setInputTrainingSet(std::vector<SVMData> training_set)
306  {
307  training_set_.insert(training_set_.end(), training_set.begin(), training_set.end());
308  }
309 
310  /** Return the current training set. */
311  std::vector<SVMData>
313  {
314  return training_set_;
315  }
316 
317  /** Reset the training set. */
318  void
320  {
321  training_set_.clear();
322  }
323 
324  /** Start the training of the SVM classifier.
325  *
326  * \return false if fails
327  */
328  bool
330 
331  /** Read in a problem (in svmlight format).
332  *
333  * \return false if fails
334  */
335  bool
336  loadProblem(const char* filename)
337  {
338  return SVM::loadProblem(filename, prob_);
339  };
340 
341  /** Set to 1 for debugging info. */
342  void
343  setDebugMode(bool in)
344  {
345  debug_ = in;
346 
347  if (in)
348  svm_set_print_string_function(nullptr);
349  else
350  svm_set_print_string_function(&printNull);
351  };
352 
353  /** Save the raw training set in a file (in svmlight format).
354  *
355  * \return false if fails
356  */
357  bool
358  saveTrainingSet(const char* filename)
359  {
360  return SVM::saveProblem(filename, true);
361  };
362 
363  /** Save the normalized training set in a file (in svmlight format).
364  *
365  * \return false if fails
366  */
367  bool
368  saveNormTrainingSet(const char* filename)
369  {
370  return SVM::saveProblemNorm(filename, prob_, true);
371  };
372 };
373 
374 /** SVM (Support Vector Machines) classification of a dataset.
375  *
376  * It can be used both for testing a classifier model and for classify of new data.
377  */
378 class SVMClassify : public SVM {
379 protected:
380  using SVM::class_name_;
382  using SVM::line_;
383  using SVM::max_line_len_;
384  using SVM::model_;
385  using SVM::param_;
386  using SVM::prob_;
387  using SVM::scaling_;
388  using SVM::training_set_;
389 
391  false}; // Set to 0 if the model is loaded from an extern file.
392  bool predict_probability_{false}; // Set to 1 to predict probabilities.
393  std::vector<std::vector<double>> prediction_; // It stores the resulting prediction.
394 
395  /** It scales the input dataset using the model information. */
396  void
398 
399 public:
400  /** Constructor. */
401  SVMClassify() { class_name_ = "SvmClassify"; }
402 
403  /** Destructor. */
405  {
406  if (!model_extern_copied_ && model_.l > 0)
407  svm_free_model_content(&model_);
408  }
409 
410  /** It adds/store the training set with labelled data. */
411  void
412  setInputTrainingSet(std::vector<SVMData> training_set)
413  {
414  assert(training_set.size() > 0);
415 
416  if (scaling_.max == 0) {
417  // to be sure to have loaded the scaling
418  PCL_ERROR("[pcl::%s::setInputTrainingSet] Classifier model not loaded!\n",
419  getClassName().c_str());
420  return;
421  }
422 
423  training_set_.insert(training_set_.end(), training_set.begin(), training_set.end());
425  }
426 
427  /** Return the current training set. */
428  std::vector<SVMData>
430  {
431  return training_set_;
432  }
433 
434  /** Reset the training set. */
435  void
437  {
438  training_set_.clear();
439  }
440 
441  /** Read in a classifier model (in svmlight format).
442  *
443  * \return false if fails
444  */
445  bool
446  loadClassifierModel(const char* filename);
447 
448  /** Get the result of the classification. */
449  void
450  getClassificationResult(std::vector<std::vector<double>>& out)
451  {
452  out.clear();
453  out.insert(out.begin(), prediction_.begin(), prediction_.end());
454  }
455 
456  /** Save the classification result in an extern file. */
457  void
458  saveClassificationResult(const char* filename);
459 
460  /** Set the classifier model. */
461  void
463  {
464  // model (inner pointers are references)
465  model_ = model;
466  int i = 0;
467 
468  while (model_.scaling[i].index != -1)
469  i++;
470 
471  scaling_.max = i;
472  scaling_.obj = Malloc(struct svm_node, i + 1);
473  scaling_.obj[i].index = -1;
474 
475  // Performing full scaling copy
476  for (int j = 0; j < i; j++) {
477  scaling_.obj[j] = model_.scaling[j];
478  }
479 
480  model_extern_copied_ = true;
481  };
482 
483  /** Read in a raw classification problem (in svmlight format).
484  *
485  * The values are normalized using the classifier model information.
486  *
487  * \return false if fails
488  */
489  bool
490  loadClassProblem(const char* filename)
491  {
492  assert(model_.l != 0);
493 
494  bool out = SVM::loadProblem(filename, prob_);
497  return out;
498  };
499 
500  /** Read in a normalized classification problem (in svmlight format).
501  *
502  * The data is kept without normalizing.
503  *
504  * \return false if fails
505  */
506  bool
507  loadNormClassProblem(const char* filename)
508  {
509  bool out = SVM::loadProblem(filename, prob_);
511  return out;
512  };
513 
514  /** Set whether the classification has to be done with the probability estimate. (The
515  * classifier model has to support it). */
516  void
518  {
519  predict_probability_ = set;
520  };
521 
522  /** Start the classification on labelled input dataset.
523  *
524  * It returns the accuracy percentage. To get the classification result, use
525  * getClassificationResult().
526  *
527  * \return false if fails
528  */
529  bool
531 
532  /** Start the classification on un-labelled input dataset.
533  *
534  * To get the classification result, use getClassificationResult().
535  *
536  * \return false if fails
537  */
538  bool
540 
541  /** Start the classification on a single set. */
542  std::vector<double>
544 
545  /** Save the raw classification problem in a file (in svmlight format).
546  *
547  * \return false if fails
548  */
549  bool
550  saveClassProblem(const char* filename)
551  {
552  return SVM::saveProblem(filename, false);
553  };
554 
555  /** Save the normalized classification problem in a file (in svmlight format).
556  *
557  * \return false if fails
558  */
559  bool
560  saveNormClassProblem(const char* filename)
561  {
562  return SVM::saveProblemNorm(filename, prob_, false);
563  };
564 };
565 
566 } // namespace pcl
SVM (Support Vector Machines) classification of a dataset.
Definition: svm_wrapper.h:378
bool saveClassProblem(const char *filename)
Save the raw classification problem in a file (in svmlight format).
Definition: svm_wrapper.h:550
bool saveNormClassProblem(const char *filename)
Save the normalized classification problem in a file (in svmlight format).
Definition: svm_wrapper.h:560
std::vector< std::vector< double > > prediction_
Definition: svm_wrapper.h:393
bool loadClassProblem(const char *filename)
Read in a raw classification problem (in svmlight format).
Definition: svm_wrapper.h:490
void resetTrainingSet()
Reset the training set.
Definition: svm_wrapper.h:436
bool predict_probability_
Definition: svm_wrapper.h:392
~SVMClassify()
Destructor.
Definition: svm_wrapper.h:404
std::vector< SVMData > getInputTrainingSet()
Return the current training set.
Definition: svm_wrapper.h:429
std::vector< double > classification(SVMData in)
Start the classification on a single set.
bool classification()
Start the classification on un-labelled input dataset.
void saveClassificationResult(const char *filename)
Save the classification result in an extern file.
void setProbabilityEstimates(bool set)
Set whether the classification has to be done with the probability estimate.
Definition: svm_wrapper.h:517
void getClassificationResult(std::vector< std::vector< double >> &out)
Get the result of the classification.
Definition: svm_wrapper.h:450
SVMClassify()
Constructor.
Definition: svm_wrapper.h:401
bool model_extern_copied_
Definition: svm_wrapper.h:390
bool classificationTest()
Start the classification on labelled input dataset.
void setClassifierModel(SVMModel model)
Set the classifier model.
Definition: svm_wrapper.h:462
void setInputTrainingSet(std::vector< SVMData > training_set)
It adds/store the training set with labelled data.
Definition: svm_wrapper.h:412
bool loadClassifierModel(const char *filename)
Read in a classifier model (in svmlight format).
std::string class_name_
Definition: svm_wrapper.h:130
svm_scaling scaling_
Definition: svm_wrapper.h:127
svm_problem prob_
Definition: svm_wrapper.h:125
void scaleProblem(svm_problem &input, svm_scaling scaling)
It scales the input dataset using the model information.
std::vector< SVMData > training_set_
Definition: svm_wrapper.h:124
bool loadNormClassProblem(const char *filename)
Read in a normalized classification problem (in svmlight format).
Definition: svm_wrapper.h:507
Base class for SVM SVM (Support Vector Machines).
Definition: svm_wrapper.h:122
SVMModel model_
Definition: svm_wrapper.h:126
bool loadProblem(const char *filename, svm_problem &prob)
Load a problem from an extern file.
char * readline(FILE *input)
To read a line from the input file.
void saveClassifierModel(const char *filename)
Save the classifier model in an extern file (in svmlight format).
Definition: svm_wrapper.h:215
const std::string & getClassName() const
Get a string representation of the name of this class.
Definition: svm_wrapper.h:155
int max_line_len_
Definition: svm_wrapper.h:133
char * line_
Definition: svm_wrapper.h:132
bool labelled_training_set_
Definition: svm_wrapper.h:134
void adaptLibSVMToInput(std::vector< SVMData > &training_set, svm_problem prob) const
Convert the libSVM format (svm_problem) into a easier output format.
~SVM()
Destructor.
Definition: svm_wrapper.h:185
void adaptInputToLibSVM(std::vector< SVMData > training_set, svm_problem &prob)
Convert the input format (vector of SVMData) into a readable format for libSVM.
std::string class_name_
Definition: svm_wrapper.h:130
bool saveProblem(const char *filename, bool labelled)
Save the raw problem in an extern file.
void getLabel(std::vector< int > &labels)
Return the labels order from the classifier model.
Definition: svm_wrapper.h:201
SVM()
Constructor.
Definition: svm_wrapper.h:182
svm_scaling scaling_
Definition: svm_wrapper.h:127
SVMParam param_
Definition: svm_wrapper.h:129
svm_problem prob_
Definition: svm_wrapper.h:125
void exitInputError(int line_num)
Outputs an error in file reading.
Definition: svm_wrapper.h:147
std::vector< SVMData > training_set_
Definition: svm_wrapper.h:124
bool saveProblemNorm(const char *filename, svm_problem prob_, bool labelled)
Save the problem (with normalized values) in an extern file.
static void printNull(const char *)
Set for output printings during classification.
Definition: svm_wrapper.h:139
SVM (Support Vector Machines) training class for the SVM machine learning.
Definition: svm_wrapper.h:235
SVMModel model_
Definition: svm_wrapper.h:126
void doCrossValidation()
To cross validate the classifier.
void resetTrainingSet()
Reset the training set.
Definition: svm_wrapper.h:319
~SVMTrain()
Destructor.
Definition: svm_wrapper.h:276
int cross_validation_
Set too 1 for cross validating the classifier.
Definition: svm_wrapper.h:250
SVMModel getClassifierModel()
Return the result of the training.
Definition: svm_wrapper.h:298
bool debug_
Set to 1 to see the training output.
Definition: svm_wrapper.h:248
void setInputTrainingSet(std::vector< SVMData > training_set)
It adds/store the training set with labelled data.
Definition: svm_wrapper.h:305
bool loadProblem(const char *filename)
Read in a problem (in svmlight format).
Definition: svm_wrapper.h:336
std::vector< SVMData > getInputTrainingSet()
Return the current training set.
Definition: svm_wrapper.h:312
bool saveNormTrainingSet(const char *filename)
Save the normalized training set in a file (in svmlight format).
Definition: svm_wrapper.h:368
bool saveTrainingSet(const char *filename)
Save the raw training set in a file (in svmlight format).
Definition: svm_wrapper.h:358
bool trainClassifier()
Start the training of the SVM classifier.
void setDebugMode(bool in)
Set to 1 for debugging info.
Definition: svm_wrapper.h:343
void scaleFactors(std::vector< SVMData > training_set, svm_scaling &scaling)
It extracts scaling factors from the input training_set.
void setParameters(SVMParam param)
Change default training parameters (pcl::SVMParam).
Definition: svm_wrapper.h:284
std::string class_name_
Definition: svm_wrapper.h:130
SVMParam param_
Definition: svm_wrapper.h:129
svm_problem prob_
Definition: svm_wrapper.h:125
std::vector< SVMData > training_set_
Definition: svm_wrapper.h:124
int nr_fold_
Number of folds to be used during cross validation.
Definition: svm_wrapper.h:253
SVMParam getParameters()
Return the current training parameters.
Definition: svm_wrapper.h:291
SVMTrain()
Constructor.
Definition: svm_wrapper.h:268
The structure stores the features and the label of a single sample which has to be used for the train...
Definition: svm_wrapper.h:112
std::vector< pcl::SVMDataPoint > SV
Vector of features for the specific sample.
Definition: svm_wrapper.h:116
double label
Pointer to the label value. It is a mandatory to train the classifier.
Definition: svm_wrapper.h:114
The structure initialize a single feature value for the classification using SVM (Support Vector Mach...
Definition: svm_wrapper.h:100
int idx
It's the feature index. It has to be an integer number greater or equal to zero.
Definition: svm_wrapper.h:102
float value
The value assigned to the correspondent feature.
Definition: svm_wrapper.h:104
SVMDataPoint()=default
The structure initialize a model created by the SVM (Support Vector Machines) classifier (pcl::SVMTra...
Definition: svm_wrapper.h:88
The structure stores the parameters for the classificationa nd must be initialized and passed to the ...
Definition: svm_wrapper.h:62
Definition: svm.h:99
struct svm_node * scaling
Definition: svm.h:122
double * probB
Definition: svm.h:109
int l
Definition: svm.h:103
double * probA
Definition: svm.h:108
Definition: svm.h:49
int index
Definition: svm.h:50
double cache_size
Definition: svm.h:83
int * weight_label
Definition: svm.h:87
double eps
Definition: svm.h:84
double coef0
Definition: svm.h:80
int svm_type
Definition: svm.h:76
double p
Definition: svm.h:90
int kernel_type
Definition: svm.h:77
int nr_weight
Definition: svm.h:86
double nu
Definition: svm.h:89
double gamma
Definition: svm.h:79
double C
Definition: svm.h:85
int probability
Definition: svm.h:92
int shrinking
Definition: svm.h:91
int degree
Definition: svm.h:78
double * weight
Definition: svm.h:88
int l
Definition: svm.h:55
double * y
Definition: svm.h:56
struct svm_node ** x
Definition: svm.h:58
struct svm_node * obj
Definition: svm.h:64
int max
Definition: svm.h:67