Point Cloud Library (PCL) 1.15.0
Loading...
Searching...
No Matches
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
53namespace 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 */
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 */
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 */
112struct 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). */
122class SVM {
123protected:
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&
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
180public:
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 */
235class SVMTrain : public SVM {
236protected:
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
266public:
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. */
292 {
293 return param_;
294 }
295
296 /** Return the result of the training. */
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
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 */
378class SVMClassify : public SVM {
379protected:
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
399public:
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
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 {
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.
bool saveClassProblem(const char *filename)
Save the raw classification problem in a file (in svmlight format).
bool saveNormClassProblem(const char *filename)
Save the normalized classification problem in a file (in svmlight format).
std::vector< std::vector< double > > prediction_
bool loadClassProblem(const char *filename)
Read in a raw classification problem (in svmlight format).
void resetTrainingSet()
Reset the training set.
~SVMClassify()
Destructor.
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.
std::vector< SVMData > getInputTrainingSet()
Return the current training set.
SVMClassify()
Constructor.
std::vector< double > classification(SVMData in)
Start the classification on a single set.
bool classificationTest()
Start the classification on labelled input dataset.
void setClassifierModel(SVMModel model)
Set the classifier model.
void setInputTrainingSet(std::vector< SVMData > training_set)
It adds/store the training set with labelled data.
bool loadClassifierModel(const char *filename)
Read in a classifier model (in svmlight format).
std::string class_name_
svm_scaling scaling_
svm_problem prob_
void scaleProblem(svm_problem &input, svm_scaling scaling)
It scales the input dataset using the model information.
std::vector< SVMData > training_set_
bool loadNormClassProblem(const char *filename)
Read in a normalized classification problem (in svmlight format).
void getClassificationResult(std::vector< std::vector< double > > &out)
Get the result of the classification.
Base class for SVM SVM (Support Vector Machines).
SVMModel model_
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).
int max_line_len_
char * line_
char * readline(FILE *input)
To read a line from the input file.
bool labelled_training_set_
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.
~SVM()
Destructor.
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_
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.
SVM()
Constructor.
svm_scaling scaling_
SVMParam param_
svm_problem prob_
void exitInputError(int line_num)
Outputs an error in file reading.
std::vector< SVMData > training_set_
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.
SVM (Support Vector Machines) training class for the SVM machine learning.
SVMModel model_
void doCrossValidation()
To cross validate the classifier.
void resetTrainingSet()
Reset the training set.
~SVMTrain()
Destructor.
int cross_validation_
Set too 1 for cross validating the classifier.
SVMModel getClassifierModel()
Return the result of the training.
bool debug_
Set to 1 to see the training output.
void setInputTrainingSet(std::vector< SVMData > training_set)
It adds/store the training set with labelled data.
bool loadProblem(const char *filename)
Read in a problem (in svmlight format).
bool saveNormTrainingSet(const char *filename)
Save the normalized training set in a file (in svmlight format).
bool saveTrainingSet(const char *filename)
Save the raw training set in a file (in svmlight format).
bool trainClassifier()
Start the training of the SVM classifier.
void setDebugMode(bool in)
Set to 1 for debugging info.
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).
std::string class_name_
SVMParam param_
svm_problem prob_
std::vector< SVMData > training_set_
int nr_fold_
Number of folds to be used during cross validation.
std::vector< SVMData > getInputTrainingSet()
Return the current training set.
SVMParam getParameters()
Return the current training parameters.
SVMTrain()
Constructor.
The structure stores the features and the label of a single sample which has to be used for the train...
std::vector< pcl::SVMDataPoint > SV
Vector of features for the specific sample.
double label
Pointer to the label value. It is a mandatory to train the classifier.
The structure initialize a single feature value for the classification using SVM (Support Vector Mach...
int idx
It's the feature index. It has to be an integer number greater or equal to zero.
float value
The value assigned to the correspondent feature.
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
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