Point Cloud Library (PCL) 1.14.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#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{-1};
102 /// The value assigned to the correspondent feature.
103 float value{0.0f};
104
105 SVMDataPoint() = default;
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_{nullptr}; // buffer for line reading
132 int max_line_len_{10000}; // max line length in the input file
134 true}; // it stores whether the input set of samples is labelled
135
136 /** Set for output printings during classification. */
137 static void
138 printNull(const char*){};
139
140 /** To read a line from the input file. Stored in "line_". */
141 char*
142 readline(FILE* input);
143
144 /** Outputs an error in file reading. */
145 void
146 exitInputError(int line_num)
147 {
148 fprintf(stderr, "Wrong input format at line %d\n", line_num);
149 exit(1);
150 }
151
152 /** Get a string representation of the name of this class. */
153 inline const std::string&
155 {
156 return (class_name_);
157 }
158
159 /** Convert the input format (vector of SVMData) into a readable format for libSVM. */
160 void
161 adaptInputToLibSVM(std::vector<SVMData> training_set, svm_problem& prob);
162
163 /** Convert the libSVM format (svm_problem) into a easier output format. */
164 void
165 adaptLibSVMToInput(std::vector<SVMData>& training_set, svm_problem prob) const;
166
167 /** Load a problem from an extern file. */
168 bool
169 loadProblem(const char* filename, svm_problem& prob);
170
171 /** Save the raw problem in an extern file.*/
172 bool
173 saveProblem(const char* filename, bool labelled);
174
175 /** Save the problem (with normalized values) in an extern file.*/
176 bool
177 saveProblemNorm(const char* filename, svm_problem prob_, bool labelled);
178
179public:
180 /** Constructor. */
181 SVM() : prob_() {}
182
183 /** Destructor. */
185 {
186 svm_destroy_param(&param_); // delete parameters
187
188 if (scaling_.max > 0)
189 free(scaling_.obj); // delete scaling factors
190
191 // delete the problem
192 if (prob_.l > 0) {
193 free(prob_.x);
194 free(prob_.y);
195 }
196 }
197
198 /** Return the labels order from the classifier model. */
199 void
200 getLabel(std::vector<int>& labels)
201 {
202 int nr_class = svm_get_nr_class(&model_);
203 int* labels_ = static_cast<int*>(malloc(nr_class * sizeof(int)));
204 svm_get_labels(&model_, labels_);
205
206 for (int j = 0; j < nr_class; j++)
207 labels.push_back(labels_[j]);
208
209 free(labels_);
210 };
211
212 /** Save the classifier model in an extern file (in svmlight format). */
213 void
214 saveClassifierModel(const char* filename)
215 {
216 // exit if model has no data
217 if (model_.l == 0)
218 return;
219
220 if (svm_save_model(filename, &model_)) {
221 fprintf(stderr, "can't save model to file %s\n", filename);
222 exit(1);
223 }
224 };
225};
226
227/** SVM (Support Vector Machines) training class for the SVM machine learning.
228 *
229 * It creates a model for the classifier from a labelled input dataset.
230 *
231 * OPTIONAL: pcl::SVMParam has to be given as input to vary the default training method
232 * and parameters.
233 */
234class SVMTrain : public SVM {
235protected:
236 using SVM::class_name_;
238 using SVM::line_;
239 using SVM::max_line_len_;
240 using SVM::model_;
241 using SVM::param_;
242 using SVM::prob_;
243 using SVM::scaling_;
244 using SVM::training_set_;
245
246 /// Set to 1 to see the training output
247 bool debug_{false};
248 /// Set too 1 for cross validating the classifier
250 /// Number of folds to be used during cross validation. It indicates in how many parts
251 /// is split the input training set.
252 int nr_fold_{0};
253
254 /** To cross validate the classifier. It is automatic for probability estimate. */
255 void
257
258 /** It extracts scaling factors from the input training_set.
259 *
260 * The scaling of the training_set is a mandatory for a good training of the
261 * classifier. */
262 void
263 scaleFactors(std::vector<SVMData> training_set, svm_scaling& scaling);
264
265public:
266 /** Constructor. */
268 {
269 class_name_ = "SVMTrain";
270 svm_set_print_string_function(
271 &printNull); // Default to NULL to not print debugging info
272 }
273
274 /** Destructor. */
276 {
277 if (model_.l > 0)
278 svm_free_model_content(&model_);
279 }
280
281 /** Change default training parameters (pcl::SVMParam). */
282 void
284 {
285 param_ = param;
286 }
287
288 /** Return the current training parameters. */
291 {
292 return param_;
293 }
294
295 /** Return the result of the training. */
298 {
299 return model_;
300 }
301
302 /** It adds/store the training set with labelled data. */
303 void
304 setInputTrainingSet(std::vector<SVMData> training_set)
305 {
306 training_set_.insert(training_set_.end(), training_set.begin(), training_set.end());
307 }
308
309 /** Return the current training set. */
310 std::vector<SVMData>
312 {
313 return training_set_;
314 }
315
316 /** Reset the training set. */
317 void
319 {
320 training_set_.clear();
321 }
322
323 /** Start the training of the SVM classifier.
324 *
325 * \return false if fails
326 */
327 bool
329
330 /** Read in a problem (in svmlight format).
331 *
332 * \return false if fails
333 */
334 bool
335 loadProblem(const char* filename)
336 {
337 return SVM::loadProblem(filename, prob_);
338 };
339
340 /** Set to 1 for debugging info. */
341 void
343 {
344 debug_ = in;
345
346 if (in)
347 svm_set_print_string_function(nullptr);
348 else
349 svm_set_print_string_function(&printNull);
350 };
351
352 /** Save the raw training set in a file (in svmlight format).
353 *
354 * \return false if fails
355 */
356 bool
357 saveTrainingSet(const char* filename)
358 {
359 return SVM::saveProblem(filename, true);
360 };
361
362 /** Save the normalized training set in a file (in svmlight format).
363 *
364 * \return false if fails
365 */
366 bool
367 saveNormTrainingSet(const char* filename)
368 {
369 return SVM::saveProblemNorm(filename, prob_, true);
370 };
371};
372
373/** SVM (Support Vector Machines) classification of a dataset.
374 *
375 * It can be used both for testing a classifier model and for classify of new data.
376 */
377class SVMClassify : public SVM {
378protected:
379 using SVM::class_name_;
381 using SVM::line_;
382 using SVM::max_line_len_;
383 using SVM::model_;
384 using SVM::param_;
385 using SVM::prob_;
386 using SVM::scaling_;
387 using SVM::training_set_;
388
390 false}; // Set to 0 if the model is loaded from an extern file.
391 bool predict_probability_{false}; // Set to 1 to predict probabilities.
392 std::vector<std::vector<double>> prediction_; // It stores the resulting prediction.
393
394 /** It scales the input dataset using the model information. */
395 void
397
398public:
399 /** Constructor. */
400 SVMClassify() { class_name_ = "SvmClassify"; }
401
402 /** Destructor. */
404 {
405 if (!model_extern_copied_ && model_.l > 0)
406 svm_free_model_content(&model_);
407 }
408
409 /** It adds/store the training set with labelled data. */
410 void
411 setInputTrainingSet(std::vector<SVMData> training_set)
412 {
413 assert(training_set.size() > 0);
414
415 if (scaling_.max == 0) {
416 // to be sure to have loaded the scaling
417 PCL_ERROR("[pcl::%s::setInputTrainingSet] Classifier model not loaded!\n",
418 getClassName().c_str());
419 return;
420 }
421
422 training_set_.insert(training_set_.end(), training_set.begin(), training_set.end());
424 }
425
426 /** Return the current training set. */
427 std::vector<SVMData>
429 {
430 return training_set_;
431 }
432
433 /** Reset the training set. */
434 void
436 {
437 training_set_.clear();
438 }
439
440 /** Read in a classifier model (in svmlight format).
441 *
442 * \return false if fails
443 */
444 bool
445 loadClassifierModel(const char* filename);
446
447 /** Get the result of the classification. */
448 void
449 getClassificationResult(std::vector<std::vector<double>>& out)
450 {
451 out.clear();
452 out.insert(out.begin(), prediction_.begin(), prediction_.end());
453 }
454
455 /** Save the classification result in an extern file. */
456 void
457 saveClassificationResult(const char* filename);
458
459 /** Set the classifier model. */
460 void
462 {
463 // model (inner pointers are references)
464 model_ = model;
465 int i = 0;
466
467 while (model_.scaling[i].index != -1)
468 i++;
469
470 scaling_.max = i;
471 scaling_.obj = Malloc(struct svm_node, i + 1);
472 scaling_.obj[i].index = -1;
473
474 // Performing full scaling copy
475 for (int j = 0; j < i; j++) {
476 scaling_.obj[j] = model_.scaling[j];
477 }
478
480 };
481
482 /** Read in a raw classification problem (in svmlight format).
483 *
484 * The values are normalized using the classifier model information.
485 *
486 * \return false if fails
487 */
488 bool
489 loadClassProblem(const char* filename)
490 {
491 assert(model_.l != 0);
492
493 bool out = SVM::loadProblem(filename, prob_);
496 return out;
497 };
498
499 /** Read in a normalized classification problem (in svmlight format).
500 *
501 * The data is kept without normalizing.
502 *
503 * \return false if fails
504 */
505 bool
506 loadNormClassProblem(const char* filename)
507 {
508 bool out = SVM::loadProblem(filename, prob_);
510 return out;
511 };
512
513 /** Set whether the classification has to be done with the probability estimate. (The
514 * classifier model has to support it). */
515 void
517 {
519 };
520
521 /** Start the classification on labelled input dataset.
522 *
523 * It returns the accuracy percentage. To get the classification result, use
524 * getClassificationResult().
525 *
526 * \return false if fails
527 */
528 bool
530
531 /** Start the classification on un-labelled input dataset.
532 *
533 * To get the classification result, use getClassificationResult().
534 *
535 * \return false if fails
536 */
537 bool
539
540 /** Start the classification on a single set. */
541 std::vector<double>
543
544 /** Save the raw classification problem in a file (in svmlight format).
545 *
546 * \return false if fails
547 */
548 bool
549 saveClassProblem(const char* filename)
550 {
551 return SVM::saveProblem(filename, false);
552 };
553
554 /** Save the normalized classification problem in a file (in svmlight format).
555 *
556 * \return false if fails
557 */
558 bool
559 saveNormClassProblem(const char* filename)
560 {
561 return SVM::saveProblemNorm(filename, prob_, false);
562 };
563};
564
565} // 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...
Definition svm_wrapper.h:99
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:87
The structure stores the parameters for the classificationa nd must be initialized and passed to the ...
Definition svm_wrapper.h:61
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