Point Cloud Library (PCL)  1.9.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
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 #ifndef PCL_SVM_WRAPPER_H_
40 #define PCL_SVM_WRAPPER_H_
41 
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <ctype.h>
46 #include <errno.h>
47 #include <iostream>
48 #include <fstream>
49 #include <pcl/common/eigen.h>
50 #include <vector>
51 
52 #include <pcl/console/time.h>
53 
54 #include <pcl/ml/svm.h>
55 #define Malloc(type,n) static_cast<type *> (malloc((n)*sizeof(type)))
56 
57 namespace pcl
58 {
59 
60  /** \brief The structure stores the parameters for the classificationa nd
61  * must be initialized and passed to the training method pcl::SVMTrain.
62  * \param svm_type {C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR}
63  * \param kernel_type {LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED}
64  * \param probability sets the probability estimates
65  */
67  {
69  {
70  svm_type = C_SVC; // C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR
71  kernel_type = RBF; // LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED
72  degree = 3; // for poly
73  gamma = 0; // 1/num_features {for poly/rbf/sigmoid}
74  coef0 = 0; // for poly/sigmoid
75 
76  nu = 0.5; // for NU_SVC, ONE_CLASS, and NU_SVR
77  cache_size = 100; // in MB
78  C = 1; // for C_SVC, EPSILON_SVR and NU_SVR
79  eps = 1e-3; // stopping criteria
80  p = 0.1; // for EPSILON_SVR
81  shrinking = 0; // use the shrinking heuristics
82  probability = 0; // do probability estimates
83 
84  nr_weight = 0; // for C_SVC
85  weight_label = NULL; // for C_SVC
86  weight = NULL; // for C_SVC
87  }
88  };
89 
90  /** \brief The structure initialize a model created by the SVM (Support Vector Machines) classifier (pcl::SVMTrain)
91  */
93  {
95  {
96  l = 0;
97  probA = NULL;
98  probB = NULL;
99  }
100  };
101 
102  /** \brief The structure initialize a single feature value for the classification using SVM (Support Vector Machines).
103  */
105  {
106  int idx; // It's the feature index. It has to be an integer number greater or equal to zero.
107  float value; // The value assigned to the correspondent feature.
108 
109  SVMDataPoint () : idx (-1), value (0)
110  {
111  }
112  };
113 
114  /** \brief The structure stores the features and the label of a single sample which has to be used
115  * for the training or the classification of the SVM (Support Vector Machines).
116  */
117  struct SVMData
118  {
119  double label; // Pointer to the label value. It is a mandatory to train the classifier.
120  std::vector<pcl::SVMDataPoint> SV; // Vector of features for the specific sample.
121 
122  SVMData () : label (std::numeric_limits<double>::signaling_NaN())
123  {
124  }
125  };
126 
127  /** \brief Base class for SVM SVM (Support Vector Machines).
128  */
129  class SVM
130  {
131  protected:
132  std::vector<SVMData> training_set_; // Basic training set
133  svm_problem prob_; // contains the problem (vector of samples with their features)
134  SVMModel model_; // model of the classifier
135  svm_scaling scaling_; // for the best model training, the input dataset is scaled and the scaling factors are stored here
136  SVMParam param_; // it stores the training parameters
137  std::string class_name_; // The SVM class name.
138 
139  char *line_; // buffer for line reading
140  int max_line_len_; // max line length in the input file
141  bool labelled_training_set_; // it stores whether the input set of samples is labelled
142  /** \brief Set for output printings during classification. */
143  static void
144  printNull (const char *) {};
145 
146  /** \brief To read a line from the input file. Stored in "line_". */
147  char*
148  readline (FILE *input);
149 
150  /** \brief Outputs an error in file reading. */
151  void exitInputError (int line_num)
152  {
153  fprintf (stderr, "Wrong input format at line %d\n", line_num);
154  exit (1);
155  }
156 
157  /** \brief Get a string representation of the name of this class. */
158  inline const std::string&
159  getClassName () const
160  {
161  return (class_name_);
162  }
163 
164  /** \brief Convert the input format (vector of SVMData) into a readable format for libSVM. */
165  void adaptInputToLibSVM (std::vector<SVMData> training_set, svm_problem &prob);
166 
167  /** \brief Convert the libSVM format (svm_problem) into a easier output format. */
168  void adaptLibSVMToInput (std::vector<SVMData> &training_set, svm_problem prob);
169 
170  /** \brief Load a problem from an extern file. */
171  bool loadProblem (const char *filename, svm_problem &prob);
172 
173  /** \brief Save the raw problem in an extern file.*/
174  bool saveProblem (const char *filename, bool labelled);
175 
176  /** \brief Save the problem (with normalized values) in an extern file.*/
177  bool saveProblemNorm (const char *filename, svm_problem prob_, bool labelled);
178 
179  public:
180  /** \brief Constructor. */
181  SVM () :
182  training_set_ (), prob_ (), model_ (), scaling_ (), param_ (),
183  class_name_ (), line_ (NULL), max_line_len_ (10000), labelled_training_set_ (1)
184  {
185  }
186 
187  /** \brief Destructor. */
188  ~SVM ()
189  {
190  svm_destroy_param (&param_); // delete parameters
191 
192  if (scaling_.max > 0)
193  free (scaling_.obj); // delete scaling factors
194 
195  // delete the problem
196  if (prob_.l > 0)
197  {
198  free (prob_.x);
199  free (prob_.y);
200  }
201  }
202 
203  /** \brief Return the labels order from the classifier model. */
204  void
205  getLabel (std::vector<int> &labels)
206  {
207  int nr_class = svm_get_nr_class (&model_);
208  int *labels_ = static_cast<int *> (malloc (nr_class * sizeof (int)));
209  svm_get_labels (&model_, labels_);
210 
211  for (int j = 0 ; j < nr_class; j++)
212  labels.push_back (labels_[j]);
213 
214  free (labels_);
215  };
216 
217  /** \brief Save the classifier model in an extern file (in svmlight format). */
218  void saveClassifierModel (const char *filename)
219  {
220  // exit if model has no data
221  if (model_.l == 0)
222  return;
223 
224  if (svm_save_model (filename, &model_))
225  {
226  fprintf (stderr, "can't save model to file %s\n", filename);
227  exit (1);
228  }
229  };
230  };
231 
232  /** \brief SVM (Support Vector Machines) training class for the SVM machine learning.
233  * It creates a model for the classifier from a labelled input dataset.
234  * OPTIONAL: pcl::SVMParam has to be given as input to vary the default training method and parameters.
235  */
236  class SVMTrain : public SVM
237  {
238  protected:
240  using SVM::model_;
241  using SVM::line_;
242  using SVM::max_line_len_;
243  using SVM::training_set_;
244  using SVM::prob_;
245  using SVM::scaling_;
246  using SVM::param_;
247  using SVM::class_name_;
248 
249  bool debug_; // Set to 1 to see the training output
250  int cross_validation_; // Set too 1 for cross validating the classifier
251  int nr_fold_; // Number of folds to be used during cross validation. It indicates in how many parts is split the input training set.
252 
253  /** \brief To cross validate the classifier. It is automatic for probability estimate. */
254  void
256 
257  /** \brief It extracts scaling factors from the input training_set.
258  * The scaling of the training_set is a mandatory for a good training of the classifier. */
259  void
260  scaleFactors (std::vector<SVMData> training_set, svm_scaling &scaling);
261 
262  public:
263  /** \brief Constructor. */
264  SVMTrain() : debug_ (0), cross_validation_ (0), nr_fold_ (0)
265  {
266  class_name_ = "SVMTrain";
267  svm_set_print_string_function (&printNull); // Default to NULL to not print debugging info
268  }
269 
270  /** \brief Destructor. */
272  {
273  if (model_.l > 0)
274  svm_free_model_content (&model_);
275  }
276 
277  /** \brief Change default training parameters (pcl::SVMParam). */
278  void
280  {
281  param_ = param;
282  }
283 
284  /** \brief Return the current training parameters. */
285  SVMParam
287  {
288  return param_;
289  }
290 
291  /** \brief Return the result of the training. */
292  SVMModel
294  {
295  return model_;
296  }
297 
298  /** \brief It adds/store the training set with labelled data. */
299  void
300  setInputTrainingSet (std::vector<SVMData> training_set)
301  {
302  training_set_.insert (training_set_.end(), training_set.begin(), training_set.end());
303  }
304 
305  /** \brief Return the current training set. */
306  std::vector<SVMData>
308  {
309  return training_set_;
310  }
311 
312  /** \brief Reset the training set. */
313  void
315  {
316  training_set_.clear();
317  }
318 
319  /** \brief Start the training of the SVM classifier.
320  \return false if fails. */
321  bool
322  trainClassifier ();
323 
324  /** \brief Read in a problem (in svmlight format).
325  * \return false if fails. */
326  bool
327  loadProblem (const char *filename)
328  {
329  return SVM::loadProblem (filename, prob_);
330  };
331 
332  /** \brief Set to 1 for debugging info. */
333  void
334  setDebugMode (bool in)
335  {
336  debug_ = in;
337 
338  if (in)
339  svm_set_print_string_function (NULL);
340  else
341  svm_set_print_string_function (&printNull);
342  };
343 
344  /** \brief Save the raw training set in a file (in svmlight format).
345  * \return false if fails. */
346  bool
347  saveTrainingSet (const char *filename)
348  {
349  return SVM::saveProblem (filename, 1);
350  };
351 
352  /** \brief Save the normalized training set in a file (in svmlight format).
353  * \return false if fails. */
354  bool
355  saveNormTrainingSet (const char *filename)
356  {
357  return SVM::saveProblemNorm (filename, prob_, 1);
358  };
359  };
360 
361  /** \brief SVM (Support Vector Machines) classification of a dataset.
362  * It can be used both for testing a classifier model and for classify of new data.
363  */
364  class SVMClassify : public SVM
365  {
366  protected:
368  using SVM::model_;
369  using SVM::line_;
370  using SVM::max_line_len_;
371  using SVM::training_set_;
372  using SVM::prob_;
373  using SVM::scaling_;
374  using SVM::param_;
375  using SVM::class_name_;
376 
377  bool model_extern_copied_; // Set to 0 if the model is loaded from an extern file.
378  bool predict_probability_; // Set to 1 to predict probabilities.
379  std::vector< std::vector<double> > prediction_; // It stores the resulting prediction.
380 
381  /** \brief It scales the input dataset using the model information. */
382  void scaleProblem (svm_problem &input, svm_scaling scaling);
383 
384  public:
385  /** \brief Constructor. */
386  SVMClassify () : model_extern_copied_ (0), predict_probability_ (0)
387  {
388  class_name_ = "SvmClassify";
389  }
390 
391  /** \brief Destructor. */
393  {
394  if (!model_extern_copied_ && model_.l > 0)
395  svm_free_model_content (&model_);
396  }
397 
398  /** \brief It adds/store the training set with labelled data. */
399  void
400  setInputTrainingSet (std::vector<SVMData> training_set)
401  {
402  assert (training_set.size() > 0);
403 
404  if (scaling_.max == 0)
405  {
406  // to be sure to have loaded the scaling
407  PCL_ERROR ("[pcl::%s::setInputTrainingSet] Classifier model not loaded!\n", getClassName ().c_str ());
408  return;
409  }
410 
411  training_set_.insert (training_set_.end(), training_set.begin(), training_set.end());
413  }
414 
415  /** \brief Return the current training set. */
416  std::vector<SVMData>
418  {
419  return training_set_;
420  }
421 
422  /** \brief Reset the training set. */
423  void
425  {
426  training_set_.clear();
427  }
428 
429  /** \brief Read in a classifier model (in svmlight format).
430  * \return false if fails. */
431  bool
432  loadClassifierModel (const char *filename);
433 
434  /** \brief Get the result of the classification. */
435  void
436  getClassificationResult (std::vector< std::vector<double> > &out)
437  {
438  out.clear ();
439  out.insert (out.begin(), prediction_.begin(), prediction_.end());
440  }
441 
442  /** \brief Save the classification result in an extern file. */
443  void
444  saveClassificationResult (const char *filename);
445 
446  /** \brief Set the classifier model. */
447  void
449  {
450  // model (inner pointers are references)
451  model_ = model;
452  int i = 0;
453 
454  while (model_.scaling[i].index != -1)
455  i++;
456 
457  scaling_.max = i;
458  scaling_.obj = Malloc (struct svm_node, i + 1);
459  scaling_.obj[i].index = -1;
460 
461  // Performing full scaling copy
462  for (int j = 0; j < i; j++)
463  {
464  scaling_.obj[j] = model_.scaling[j];
465  }
466 
467  model_extern_copied_ = 1;
468  };
469 
470  /** \brief Read in a raw classification problem (in svmlight format).
471  * The values are normalized using the classifier model information.
472  * \return false if fails. */
473  bool
474  loadClassProblem (const char *filename)
475  {
476  assert (model_.l != 0);
477 
478  bool out = SVM::loadProblem (filename, prob_);
481  return out;
482  };
483 
484  /** \brief Read in a normalized classification problem (in svmlight format).
485  * The data are kept whitout normalizing.
486  * \return false if fails. */
487  bool
488  loadNormClassProblem (const char *filename)
489  {
490  bool out = SVM::loadProblem (filename, prob_);
492  return out;
493  };
494 
495  /** \brief Set whether the classification has to be done with the probability estimate.
496  * (the classifier model has to support it). */
497  void
499  {
500  predict_probability_ = set;
501  };
502 
503  /** \brief Start the classification on labelled input dataset. It returns the accuracy percentage.
504  * To get the classification result, use getClassificationResult.
505  * \return false if fails. */
506  bool
508 
509  /** \brief Start the classification on un-labelled input dataset.
510  * To get the classification result, use getClassificationResult.
511  * \return false if fails. */
512  bool
513  classification ();
514 
515  /** \brief Start the classification on a single set. */
516  std::vector<double>
517  classification (SVMData in);
518 
519  /** \brief Save the raw classification problem in a file (in svmlight format).
520  * \return false if fails. */
521  bool
522  saveClassProblem (const char *filename)
523  {
524  return SVM::saveProblem (filename, 0);
525  };
526 
527  /** \brief Save the normalized classification problem in a file (in svmlight format).
528  * \return false if fails. */
529  bool
530  saveNormClassProblem (const char *filename)
531  {
532  return SVM::saveProblemNorm (filename, prob_, 0);
533  };
534  };
535 }
536 
537 #endif // PCL_SVM_WRAPPER_H_
struct svm_node * obj
Definition: svm.h:70
std::vector< SVMData > getInputTrainingSet()
Return the current training set.
Definition: svm_wrapper.h:307
void setInputTrainingSet(std::vector< SVMData > training_set)
It adds/store the training set with labelled data.
Definition: svm_wrapper.h:300
~SVMTrain()
Destructor.
Definition: svm_wrapper.h:271
svm_problem prob_
Definition: svm_wrapper.h:133
bool loadClassifierModel(const char *filename)
Read in a classifier model (in svmlight format).
bool saveNormClassProblem(const char *filename)
Save the normalized classification problem in a file (in svmlight format).
Definition: svm_wrapper.h:530
bool saveProblemNorm(const char *filename, svm_problem prob_, bool labelled)
Save the problem (with normalized values) in an extern file.
bool classificationTest()
Start the classification on labelled input dataset.
bool loadNormClassProblem(const char *filename)
Read in a normalized classification problem (in svmlight format).
Definition: svm_wrapper.h:488
This file defines compatibility wrappers for low level I/O functions.
Definition: convolution.h:45
The structure initialize a single feature value for the classification using SVM (Support Vector Mach...
Definition: svm_wrapper.h:104
std::vector< pcl::SVMDataPoint > SV
Definition: svm_wrapper.h:120
void scaleFactors(std::vector< SVMData > training_set, svm_scaling &scaling)
It extracts scaling factors from the input training_set.
The structure stores the features and the label of a single sample which has to be used for the train...
Definition: svm_wrapper.h:117
void doCrossValidation()
To cross validate the classifier.
SVMClassify()
Constructor.
Definition: svm_wrapper.h:386
Base class for SVM SVM (Support Vector Machines).
Definition: svm_wrapper.h:129
bool model_extern_copied_
Definition: svm_wrapper.h:377
int l
Definition: svm.h:113
void exitInputError(int line_num)
Outputs an error in file reading.
Definition: svm_wrapper.h:151
int nr_weight
Definition: svm.h:95
void setDebugMode(bool in)
Set to 1 for debugging info.
Definition: svm_wrapper.h:334
std::string class_name_
Definition: svm_wrapper.h:137
SVMParam getParameters()
Return the current training parameters.
Definition: svm_wrapper.h:286
double * probB
Definition: svm.h:119
bool loadClassProblem(const char *filename)
Read in a raw classification problem (in svmlight format).
Definition: svm_wrapper.h:474
SVMModel model_
Definition: svm_wrapper.h:134
int * weight_label
Definition: svm.h:96
bool saveTrainingSet(const char *filename)
Save the raw training set in a file (in svmlight format).
Definition: svm_wrapper.h:347
void resetTrainingSet()
Reset the training set.
Definition: svm_wrapper.h:314
~SVM()
Destructor.
Definition: svm_wrapper.h:188
bool saveProblem(const char *filename, bool labelled)
Save the raw problem in an extern file.
double label
Definition: svm_wrapper.h:119
bool predict_probability_
Definition: svm_wrapper.h:378
SVM (Support Vector Machines) classification of a dataset.
Definition: svm_wrapper.h:364
double * probA
Definition: svm.h:118
The structure initialize a model created by the SVM (Support Vector Machines) classifier (pcl::SVMTra...
Definition: svm_wrapper.h:92
SVM()
Constructor.
Definition: svm_wrapper.h:181
Definition: svm.h:108
double p
Definition: svm.h:99
bool saveNormTrainingSet(const char *filename)
Save the normalized training set in a file (in svmlight format).
Definition: svm_wrapper.h:355
bool loadProblem(const char *filename)
Read in a problem (in svmlight format).
Definition: svm_wrapper.h:327
char * line_
Definition: svm_wrapper.h:139
SVM (Support Vector Machines) training class for the SVM machine learning.
Definition: svm_wrapper.h:236
double cache_size
Definition: svm.h:92
void saveClassificationResult(const char *filename)
Save the classification result in an extern file.
bool saveClassProblem(const char *filename)
Save the raw classification problem in a file (in svmlight format).
Definition: svm_wrapper.h:522
int cross_validation_
Definition: svm_wrapper.h:250
void saveClassifierModel(const char *filename)
Save the classifier model in an extern file (in svmlight format).
Definition: svm_wrapper.h:218
void setParameters(SVMParam param)
Change default training parameters (pcl::SVMParam).
Definition: svm_wrapper.h:279
SVMTrain()
Constructor.
Definition: svm_wrapper.h:264
~SVMClassify()
Destructor.
Definition: svm_wrapper.h:392
double eps
Definition: svm.h:93
void adaptInputToLibSVM(std::vector< SVMData > training_set, svm_problem &prob)
Convert the input format (vector of SVMData) into a readable format for libSVM.
bool labelled_training_set_
Definition: svm_wrapper.h:141
int shrinking
Definition: svm.h:100
void resetTrainingSet()
Reset the training set.
Definition: svm_wrapper.h:424
static void printNull(const char *)
Set for output printings during classification.
Definition: svm_wrapper.h:144
struct svm_node ** x
Definition: svm.h:63
struct svm_node * scaling
Definition: svm.h:132
char * readline(FILE *input)
To read a line from the input file.
std::vector< std::vector< double > > prediction_
Definition: svm_wrapper.h:379
bool loadProblem(const char *filename, svm_problem &prob)
Load a problem from an extern file.
bool trainClassifier()
Start the training of the SVM classifier.
void setInputTrainingSet(std::vector< SVMData > training_set)
It adds/store the training set with labelled data.
Definition: svm_wrapper.h:400
int index
Definition: svm.h:54
void setClassifierModel(SVMModel model)
Set the classifier model.
Definition: svm_wrapper.h:448
void adaptLibSVMToInput(std::vector< SVMData > &training_set, svm_problem prob)
Convert the libSVM format (svm_problem) into a easier output format.
void getLabel(std::vector< int > &labels)
Return the labels order from the classifier model.
Definition: svm_wrapper.h:205
std::vector< SVMData > training_set_
Definition: svm_wrapper.h:132
int max
Definition: svm.h:73
svm_scaling scaling_
Definition: svm_wrapper.h:135
void getClassificationResult(std::vector< std::vector< double > > &out)
Get the result of the classification.
Definition: svm_wrapper.h:436
bool classification()
Start the classification on un-labelled input dataset.
const std::string & getClassName() const
Get a string representation of the name of this class.
Definition: svm_wrapper.h:159
int probability
Definition: svm.h:101
int degree
Definition: svm.h:87
int max_line_len_
Definition: svm_wrapper.h:140
The structure stores the parameters for the classificationa nd must be initialized and passed to the ...
Definition: svm_wrapper.h:66
void scaleProblem(svm_problem &input, svm_scaling scaling)
It scales the input dataset using the model information.
Definition: svm.h:52
double * y
Definition: svm.h:61
void setProbabilityEstimates(bool set)
Set whether the classification has to be done with the probability estimate.
Definition: svm_wrapper.h:498
double gamma
Definition: svm.h:88
int l
Definition: svm.h:60
double * weight
Definition: svm.h:97
double C
Definition: svm.h:94
int svm_type
Definition: svm.h:85
double nu
Definition: svm.h:98
double coef0
Definition: svm.h:89
int kernel_type
Definition: svm.h:86
SVMModel getClassifierModel()
Return the result of the training.
Definition: svm_wrapper.h:293
SVMParam param_
Definition: svm_wrapper.h:136
std::vector< SVMData > getInputTrainingSet()
Return the current training set.
Definition: svm_wrapper.h:417