Point Cloud Library (PCL) 1.13.0
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#define Malloc(type, n) static_cast<type*>(malloc((n) * sizeof(type)))
51
52namespace pcl {
53
54/** The structure stores the parameters for the classificationa nd must be initialized
55 * and passed to the training method pcl::SVMTrain.
56 *
57 * \param svm_type {C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR}
58 * \param kernel_type {LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED}
59 * \param probability sets the probability estimates
60 */
63 {
64 svm_type = C_SVC; // C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR
65 kernel_type = RBF; // LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED
66 degree = 3; // for poly
67 gamma = 0; // 1/num_features {for poly/rbf/sigmoid}
68 coef0 = 0; // for poly/sigmoid
69
70 nu = 0.5; // for NU_SVC, ONE_CLASS, and NU_SVR
71 cache_size = 100; // in MB
72 C = 1; // for C_SVC, EPSILON_SVR and NU_SVR
73 eps = 1e-3; // stopping criteria
74 p = 0.1; // for EPSILON_SVR
75 shrinking = 0; // use the shrinking heuristics
76 probability = 0; // do probability estimates
77
78 nr_weight = 0; // for C_SVC
79 weight_label = nullptr; // for C_SVC
80 weight = nullptr; // for C_SVC
81 }
82};
83
84/** The structure initialize a model created by the SVM (Support Vector Machines)
85 * classifier (pcl::SVMTrain).
86 */
89 {
90 l = 0;
91 probA = nullptr;
92 probB = nullptr;
93 }
94};
95
96/** The structure initialize a single feature value for the classification using
97 * SVM (Support Vector Machines).
98 */
100 /// It's the feature index. It has to be an integer number greater or equal to zero
101 int idx;
102 /// The value assigned to the correspondent feature.
103 float value;
104
105 SVMDataPoint() : idx(-1), value(0) {}
106};
107
108/** The structure stores the features and the label of a single sample which has to be
109 * used for the training or the classification of the SVM (Support Vector Machines).
110 */
111struct SVMData {
112 /// Pointer to the label value. It is a mandatory to train the classifier
113 double label;
114 /// Vector of features for the specific sample.
115 std::vector<pcl::SVMDataPoint> SV;
116
117 SVMData() : label(std::numeric_limits<double>::signaling_NaN()) {}
118};
119
120/** Base class for SVM SVM (Support Vector Machines). */
121class SVM {
122protected:
123 std::vector<SVMData> training_set_; // Basic training set
124 svm_problem prob_; // contains the problem (vector of samples with their features)
125 SVMModel model_; // model of the classifier
126 svm_scaling scaling_; // for the best model training, the input dataset is scaled and
127 // the scaling factors are stored here
128 SVMParam param_; // it stores the training parameters
129 std::string class_name_; // The SVM class name.
130
131 char* line_; // buffer for line reading
132 int max_line_len_; // max line length in the input file
133 bool labelled_training_set_; // it stores whether the input set of samples is labelled
134
135 /** Set for output printings during classification. */
136 static void
137 printNull(const char*){};
138
139 /** To read a line from the input file. Stored in "line_". */
140 char*
141 readline(FILE* input);
142
143 /** Outputs an error in file reading. */
144 void
145 exitInputError(int line_num)
146 {
147 fprintf(stderr, "Wrong input format at line %d\n", line_num);
148 exit(1);
149 }
150
151 /** Get a string representation of the name of this class. */
152 inline const std::string&
154 {
155 return (class_name_);
156 }
157
158 /** Convert the input format (vector of SVMData) into a readable format for libSVM. */
159 void
160 adaptInputToLibSVM(std::vector<SVMData> training_set, svm_problem& prob);
161
162 /** Convert the libSVM format (svm_problem) into a easier output format. */
163 void
164 adaptLibSVMToInput(std::vector<SVMData>& training_set, svm_problem prob) const;
165
166 /** Load a problem from an extern file. */
167 bool
168 loadProblem(const char* filename, svm_problem& prob);
169
170 /** Save the raw problem in an extern file.*/
171 bool
172 saveProblem(const char* filename, bool labelled);
173
174 /** Save the problem (with normalized values) in an extern file.*/
175 bool
176 saveProblemNorm(const char* filename, svm_problem prob_, bool labelled);
177
178public:
179 /** Constructor. */
180 SVM() : prob_(), line_(nullptr), max_line_len_(10000), labelled_training_set_(true) {}
181
182 /** Destructor. */
184 {
185 svm_destroy_param(&param_); // delete parameters
186
187 if (scaling_.max > 0)
188 free(scaling_.obj); // delete scaling factors
189
190 // delete the problem
191 if (prob_.l > 0) {
192 free(prob_.x);
193 free(prob_.y);
194 }
195 }
196
197 /** Return the labels order from the classifier model. */
198 void
199 getLabel(std::vector<int>& labels)
200 {
201 int nr_class = svm_get_nr_class(&model_);
202 int* labels_ = static_cast<int*>(malloc(nr_class * sizeof(int)));
203 svm_get_labels(&model_, labels_);
204
205 for (int j = 0; j < nr_class; j++)
206 labels.push_back(labels_[j]);
207
208 free(labels_);
209 };
210
211 /** Save the classifier model in an extern file (in svmlight format). */
212 void
213 saveClassifierModel(const char* filename)
214 {
215 // exit if model has no data
216 if (model_.l == 0)
217 return;
218
219 if (svm_save_model(filename, &model_)) {
220 fprintf(stderr, "can't save model to file %s\n", filename);
221 exit(1);
222 }
223 };
224};
225
226/** SVM (Support Vector Machines) training class for the SVM machine learning.
227 *
228 * It creates a model for the classifier from a labelled input dataset.
229 *
230 * OPTIONAL: pcl::SVMParam has to be given as input to vary the default training method
231 * and parameters.
232 */
233class SVMTrain : public SVM {
234protected:
235 using SVM::class_name_;
237 using SVM::line_;
238 using SVM::max_line_len_;
239 using SVM::model_;
240 using SVM::param_;
241 using SVM::prob_;
242 using SVM::scaling_;
243 using SVM::training_set_;
244
245 /// Set to 1 to see the training output
246 bool debug_;
247 /// Set too 1 for cross validating the classifier
249 /// Number of folds to be used during cross validation. It indicates in how many parts
250 /// is split the input training set.
252
253 /** To cross validate the classifier. It is automatic for probability estimate. */
254 void
256
257 /** It extracts scaling factors from the input training_set.
258 *
259 * The scaling of the training_set is a mandatory for a good training of the
260 * classifier. */
261 void
262 scaleFactors(std::vector<SVMData> training_set, svm_scaling& scaling);
263
264public:
265 /** Constructor. */
267 {
268 class_name_ = "SVMTrain";
269 svm_set_print_string_function(
270 &printNull); // Default to NULL to not print debugging info
271 }
272
273 /** Destructor. */
275 {
276 if (model_.l > 0)
277 svm_free_model_content(&model_);
278 }
279
280 /** Change default training parameters (pcl::SVMParam). */
281 void
283 {
284 param_ = param;
285 }
286
287 /** Return the current training parameters. */
290 {
291 return param_;
292 }
293
294 /** Return the result of the training. */
297 {
298 return model_;
299 }
300
301 /** It adds/store the training set with labelled data. */
302 void
303 setInputTrainingSet(std::vector<SVMData> training_set)
304 {
305 training_set_.insert(training_set_.end(), training_set.begin(), training_set.end());
306 }
307
308 /** Return the current training set. */
309 std::vector<SVMData>
311 {
312 return training_set_;
313 }
314
315 /** Reset the training set. */
316 void
318 {
319 training_set_.clear();
320 }
321
322 /** Start the training of the SVM classifier.
323 *
324 * \return false if fails
325 */
326 bool
328
329 /** Read in a problem (in svmlight format).
330 *
331 * \return false if fails
332 */
333 bool
334 loadProblem(const char* filename)
335 {
336 return SVM::loadProblem(filename, prob_);
337 };
338
339 /** Set to 1 for debugging info. */
340 void
342 {
343 debug_ = in;
344
345 if (in)
346 svm_set_print_string_function(nullptr);
347 else
348 svm_set_print_string_function(&printNull);
349 };
350
351 /** Save the raw training set in a file (in svmlight format).
352 *
353 * \return false if fails
354 */
355 bool
356 saveTrainingSet(const char* filename)
357 {
358 return SVM::saveProblem(filename, true);
359 };
360
361 /** Save the normalized training set in a file (in svmlight format).
362 *
363 * \return false if fails
364 */
365 bool
366 saveNormTrainingSet(const char* filename)
367 {
368 return SVM::saveProblemNorm(filename, prob_, true);
369 };
370};
371
372/** SVM (Support Vector Machines) classification of a dataset.
373 *
374 * It can be used both for testing a classifier model and for classify of new data.
375 */
376class SVMClassify : public SVM {
377protected:
378 using SVM::class_name_;
380 using SVM::line_;
381 using SVM::max_line_len_;
382 using SVM::model_;
383 using SVM::param_;
384 using SVM::prob_;
385 using SVM::scaling_;
386 using SVM::training_set_;
387
388 bool model_extern_copied_; // Set to 0 if the model is loaded from an extern file.
389 bool predict_probability_; // Set to 1 to predict probabilities.
390 std::vector<std::vector<double>> prediction_; // It stores the resulting prediction.
391
392 /** It scales the input dataset using the model information. */
393 void
395
396public:
397 /** Constructor. */
399 {
400 class_name_ = "SvmClassify";
401 }
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
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 are kept whitout 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 {
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:376
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:390
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:389
~SVMClassify()
Destructor.
Definition: svm_wrapper.h:404
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
std::vector< SVMData > getInputTrainingSet()
Return the current training set.
Definition: svm_wrapper.h:429
SVMClassify()
Constructor.
Definition: svm_wrapper.h:398
std::vector< double > classification(SVMData in)
Start the classification on a single set.
bool model_extern_copied_
Definition: svm_wrapper.h:388
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:129
svm_scaling scaling_
Definition: svm_wrapper.h:126
svm_problem prob_
Definition: svm_wrapper.h:124
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:123
bool loadNormClassProblem(const char *filename)
Read in a normalized classification problem (in svmlight format).
Definition: svm_wrapper.h:507
void getClassificationResult(std::vector< std::vector< double > > &out)
Get the result of the classification.
Definition: svm_wrapper.h:450
Base class for SVM SVM (Support Vector Machines).
Definition: svm_wrapper.h:121
SVMModel model_
Definition: svm_wrapper.h:125
bool loadProblem(const char *filename, svm_problem &prob)
Load a problem from an extern file.
void saveClassifierModel(const char *filename)
Save the classifier model in an extern file (in svmlight format).
Definition: svm_wrapper.h:213
int max_line_len_
Definition: svm_wrapper.h:132
char * line_
Definition: svm_wrapper.h:131
char * readline(FILE *input)
To read a line from the input file.
bool labelled_training_set_
Definition: svm_wrapper.h:133
void adaptLibSVMToInput(std::vector< SVMData > &training_set, svm_problem prob) const
Convert the libSVM format (svm_problem) into a easier output format.
const std::string & getClassName() const
Get a string representation of the name of this class.
Definition: svm_wrapper.h:153
~SVM()
Destructor.
Definition: svm_wrapper.h:183
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:129
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:199
SVM()
Constructor.
Definition: svm_wrapper.h:180
svm_scaling scaling_
Definition: svm_wrapper.h:126
SVMParam param_
Definition: svm_wrapper.h:128
svm_problem prob_
Definition: svm_wrapper.h:124
void exitInputError(int line_num)
Outputs an error in file reading.
Definition: svm_wrapper.h:145
std::vector< SVMData > training_set_
Definition: svm_wrapper.h:123
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:137
SVM (Support Vector Machines) training class for the SVM machine learning.
Definition: svm_wrapper.h:233
SVMModel model_
Definition: svm_wrapper.h:125
void doCrossValidation()
To cross validate the classifier.
void resetTrainingSet()
Reset the training set.
Definition: svm_wrapper.h:317
~SVMTrain()
Destructor.
Definition: svm_wrapper.h:274
int cross_validation_
Set too 1 for cross validating the classifier.
Definition: svm_wrapper.h:248
SVMModel getClassifierModel()
Return the result of the training.
Definition: svm_wrapper.h:296
bool debug_
Set to 1 to see the training output.
Definition: svm_wrapper.h:246
void setInputTrainingSet(std::vector< SVMData > training_set)
It adds/store the training set with labelled data.
Definition: svm_wrapper.h:303
bool loadProblem(const char *filename)
Read in a problem (in svmlight format).
Definition: svm_wrapper.h:334
bool saveNormTrainingSet(const char *filename)
Save the normalized training set in a file (in svmlight format).
Definition: svm_wrapper.h:366
bool saveTrainingSet(const char *filename)
Save the raw training set in a file (in svmlight format).
Definition: svm_wrapper.h:356
bool trainClassifier()
Start the training of the SVM classifier.
void setDebugMode(bool in)
Set to 1 for debugging info.
Definition: svm_wrapper.h:341
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:282
std::string class_name_
Definition: svm_wrapper.h:129
SVMParam param_
Definition: svm_wrapper.h:128
svm_problem prob_
Definition: svm_wrapper.h:124
std::vector< SVMData > training_set_
Definition: svm_wrapper.h:123
int nr_fold_
Number of folds to be used during cross validation.
Definition: svm_wrapper.h:251
std::vector< SVMData > getInputTrainingSet()
Return the current training set.
Definition: svm_wrapper.h:310
SVMParam getParameters()
Return the current training parameters.
Definition: svm_wrapper.h:289
SVMTrain()
Constructor.
Definition: svm_wrapper.h:266
The structure stores the features and the label of a single sample which has to be used for the train...
Definition: svm_wrapper.h:111
std::vector< pcl::SVMDataPoint > SV
Vector of features for the specific sample.
Definition: svm_wrapper.h:115
double label
Pointer to the label value. It is a mandatory to train the classifier.
Definition: svm_wrapper.h:113
The structure initialize a single feature value for the classification using SVM (Support Vector Mach...
Definition: svm_wrapper.h:99
int idx
It's the feature index. It has to be an integer number greater or equal to zero.
Definition: svm_wrapper.h:101
float value
The value assigned to the correspondent feature.
Definition: svm_wrapper.h:103
The structure initialize a model created by the SVM (Support Vector Machines) classifier (pcl::SVMTra...
Definition: svm_wrapper.h:87
The structure stores the parameters for the classificationa nd must be initialized and passed to the ...
Definition: svm_wrapper.h:61
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