567 lines
15 KiB
C
567 lines
15 KiB
C
|
|
/*
|
||
|
|
* Software License Agreement (BSD License)
|
||
|
|
*
|
||
|
|
* Point Cloud Library (PCL) - www.pointclouds.org
|
||
|
|
* Copyright (c) 2010-2012, Willow Garage, Inc.
|
||
|
|
* Copyright (c) 2000-2012 Chih-Chung Chang and Chih-Jen Lin
|
||
|
|
*
|
||
|
|
* All rights reserved.
|
||
|
|
*
|
||
|
|
* Redistribution and use in source and binary forms, with or without
|
||
|
|
* modification, are permitted provided that the following conditions
|
||
|
|
* are met:
|
||
|
|
*
|
||
|
|
* * Redistributions of source code must retain the above copyright
|
||
|
|
* notice, this list of conditions and the following disclaimer.
|
||
|
|
* * Redistributions in binary form must reproduce the above
|
||
|
|
* copyright notice, this list of conditions and the following
|
||
|
|
* disclaimer in the documentation and/or other materials provided
|
||
|
|
* with the distribution.
|
||
|
|
* * Neither the name of copyright holders nor the names of its
|
||
|
|
* contributors may be used to endorse or promote products derived
|
||
|
|
* from this software without specific prior written permission.
|
||
|
|
*
|
||
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
*
|
||
|
|
*/
|
||
|
|
|
||
|
|
#pragma once
|
||
|
|
|
||
|
|
#include <pcl/console/print.h> // for PCL_ERROR
|
||
|
|
#include <pcl/ml/svm.h>
|
||
|
|
|
||
|
|
#include <cassert> // for assert
|
||
|
|
#include <cstdio>
|
||
|
|
#include <cstdlib>
|
||
|
|
#include <limits> // for numeric_limits
|
||
|
|
#include <string> // for string
|
||
|
|
#include <vector>
|
||
|
|
#define Malloc(type, n) static_cast<type*>(malloc((n) * sizeof(type)))
|
||
|
|
|
||
|
|
namespace pcl {
|
||
|
|
|
||
|
|
/** The structure stores the parameters for the classificationa nd must be initialized
|
||
|
|
* and passed to the training method pcl::SVMTrain.
|
||
|
|
*
|
||
|
|
* \param svm_type {C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR}
|
||
|
|
* \param kernel_type {LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED}
|
||
|
|
* \param probability sets the probability estimates
|
||
|
|
*/
|
||
|
|
struct SVMParam : svm_parameter {
|
||
|
|
SVMParam()
|
||
|
|
{
|
||
|
|
svm_type = C_SVC; // C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR
|
||
|
|
kernel_type = RBF; // LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED
|
||
|
|
degree = 3; // for poly
|
||
|
|
gamma = 0; // 1/num_features {for poly/rbf/sigmoid}
|
||
|
|
coef0 = 0; // for poly/sigmoid
|
||
|
|
|
||
|
|
nu = 0.5; // for NU_SVC, ONE_CLASS, and NU_SVR
|
||
|
|
cache_size = 100; // in MB
|
||
|
|
C = 1; // for C_SVC, EPSILON_SVR and NU_SVR
|
||
|
|
eps = 1e-3; // stopping criteria
|
||
|
|
p = 0.1; // for EPSILON_SVR
|
||
|
|
shrinking = 0; // use the shrinking heuristics
|
||
|
|
probability = 0; // do probability estimates
|
||
|
|
|
||
|
|
nr_weight = 0; // for C_SVC
|
||
|
|
weight_label = nullptr; // for C_SVC
|
||
|
|
weight = nullptr; // for C_SVC
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
/** The structure initialize a model created by the SVM (Support Vector Machines)
|
||
|
|
* classifier (pcl::SVMTrain).
|
||
|
|
*/
|
||
|
|
struct SVMModel : svm_model {
|
||
|
|
SVMModel()
|
||
|
|
{
|
||
|
|
l = 0;
|
||
|
|
probA = nullptr;
|
||
|
|
probB = nullptr;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
/** The structure initialize a single feature value for the classification using
|
||
|
|
* SVM (Support Vector Machines).
|
||
|
|
*/
|
||
|
|
struct SVMDataPoint {
|
||
|
|
/// It's the feature index. It has to be an integer number greater or equal to zero
|
||
|
|
int idx;
|
||
|
|
/// The value assigned to the correspondent feature.
|
||
|
|
float value;
|
||
|
|
|
||
|
|
SVMDataPoint() : idx(-1), value(0) {}
|
||
|
|
};
|
||
|
|
|
||
|
|
/** The structure stores the features and the label of a single sample which has to be
|
||
|
|
* used for the training or the classification of the SVM (Support Vector Machines).
|
||
|
|
*/
|
||
|
|
struct SVMData {
|
||
|
|
/// Pointer to the label value. It is a mandatory to train the classifier
|
||
|
|
double label;
|
||
|
|
/// Vector of features for the specific sample.
|
||
|
|
std::vector<pcl::SVMDataPoint> SV;
|
||
|
|
|
||
|
|
SVMData() : label(std::numeric_limits<double>::signaling_NaN()) {}
|
||
|
|
};
|
||
|
|
|
||
|
|
/** Base class for SVM SVM (Support Vector Machines). */
|
||
|
|
class SVM {
|
||
|
|
protected:
|
||
|
|
std::vector<SVMData> training_set_; // Basic training set
|
||
|
|
svm_problem prob_; // contains the problem (vector of samples with their features)
|
||
|
|
SVMModel model_; // model of the classifier
|
||
|
|
svm_scaling scaling_; // for the best model training, the input dataset is scaled and
|
||
|
|
// the scaling factors are stored here
|
||
|
|
SVMParam param_; // it stores the training parameters
|
||
|
|
std::string class_name_; // The SVM class name.
|
||
|
|
|
||
|
|
char* line_; // buffer for line reading
|
||
|
|
int max_line_len_; // max line length in the input file
|
||
|
|
bool labelled_training_set_; // it stores whether the input set of samples is labelled
|
||
|
|
|
||
|
|
/** Set for output printings during classification. */
|
||
|
|
static void
|
||
|
|
printNull(const char*){};
|
||
|
|
|
||
|
|
/** To read a line from the input file. Stored in "line_". */
|
||
|
|
char*
|
||
|
|
readline(FILE* input);
|
||
|
|
|
||
|
|
/** Outputs an error in file reading. */
|
||
|
|
void
|
||
|
|
exitInputError(int line_num)
|
||
|
|
{
|
||
|
|
fprintf(stderr, "Wrong input format at line %d\n", line_num);
|
||
|
|
exit(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Get a string representation of the name of this class. */
|
||
|
|
inline const std::string&
|
||
|
|
getClassName() const
|
||
|
|
{
|
||
|
|
return (class_name_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Convert the input format (vector of SVMData) into a readable format for libSVM. */
|
||
|
|
void
|
||
|
|
adaptInputToLibSVM(std::vector<SVMData> training_set, svm_problem& prob);
|
||
|
|
|
||
|
|
/** Convert the libSVM format (svm_problem) into a easier output format. */
|
||
|
|
void
|
||
|
|
adaptLibSVMToInput(std::vector<SVMData>& training_set, svm_problem prob) const;
|
||
|
|
|
||
|
|
/** Load a problem from an extern file. */
|
||
|
|
bool
|
||
|
|
loadProblem(const char* filename, svm_problem& prob);
|
||
|
|
|
||
|
|
/** Save the raw problem in an extern file.*/
|
||
|
|
bool
|
||
|
|
saveProblem(const char* filename, bool labelled);
|
||
|
|
|
||
|
|
/** Save the problem (with normalized values) in an extern file.*/
|
||
|
|
bool
|
||
|
|
saveProblemNorm(const char* filename, svm_problem prob_, bool labelled);
|
||
|
|
|
||
|
|
public:
|
||
|
|
/** Constructor. */
|
||
|
|
SVM() : prob_(), line_(nullptr), max_line_len_(10000), labelled_training_set_(true) {}
|
||
|
|
|
||
|
|
/** Destructor. */
|
||
|
|
~SVM()
|
||
|
|
{
|
||
|
|
svm_destroy_param(¶m_); // delete parameters
|
||
|
|
|
||
|
|
if (scaling_.max > 0)
|
||
|
|
free(scaling_.obj); // delete scaling factors
|
||
|
|
|
||
|
|
// delete the problem
|
||
|
|
if (prob_.l > 0) {
|
||
|
|
free(prob_.x);
|
||
|
|
free(prob_.y);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Return the labels order from the classifier model. */
|
||
|
|
void
|
||
|
|
getLabel(std::vector<int>& labels)
|
||
|
|
{
|
||
|
|
int nr_class = svm_get_nr_class(&model_);
|
||
|
|
int* labels_ = static_cast<int*>(malloc(nr_class * sizeof(int)));
|
||
|
|
svm_get_labels(&model_, labels_);
|
||
|
|
|
||
|
|
for (int j = 0; j < nr_class; j++)
|
||
|
|
labels.push_back(labels_[j]);
|
||
|
|
|
||
|
|
free(labels_);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** Save the classifier model in an extern file (in svmlight format). */
|
||
|
|
void
|
||
|
|
saveClassifierModel(const char* filename)
|
||
|
|
{
|
||
|
|
// exit if model has no data
|
||
|
|
if (model_.l == 0)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (svm_save_model(filename, &model_)) {
|
||
|
|
fprintf(stderr, "can't save model to file %s\n", filename);
|
||
|
|
exit(1);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
/** SVM (Support Vector Machines) training class for the SVM machine learning.
|
||
|
|
*
|
||
|
|
* It creates a model for the classifier from a labelled input dataset.
|
||
|
|
*
|
||
|
|
* OPTIONAL: pcl::SVMParam has to be given as input to vary the default training method
|
||
|
|
* and parameters.
|
||
|
|
*/
|
||
|
|
class SVMTrain : public SVM {
|
||
|
|
protected:
|
||
|
|
using SVM::class_name_;
|
||
|
|
using SVM::labelled_training_set_;
|
||
|
|
using SVM::line_;
|
||
|
|
using SVM::max_line_len_;
|
||
|
|
using SVM::model_;
|
||
|
|
using SVM::param_;
|
||
|
|
using SVM::prob_;
|
||
|
|
using SVM::scaling_;
|
||
|
|
using SVM::training_set_;
|
||
|
|
|
||
|
|
/// Set to 1 to see the training output
|
||
|
|
bool debug_;
|
||
|
|
/// Set too 1 for cross validating the classifier
|
||
|
|
int cross_validation_;
|
||
|
|
/// Number of folds to be used during cross validation. It indicates in how many parts
|
||
|
|
/// is split the input training set.
|
||
|
|
int nr_fold_;
|
||
|
|
|
||
|
|
/** To cross validate the classifier. It is automatic for probability estimate. */
|
||
|
|
void
|
||
|
|
doCrossValidation();
|
||
|
|
|
||
|
|
/** It extracts scaling factors from the input training_set.
|
||
|
|
*
|
||
|
|
* The scaling of the training_set is a mandatory for a good training of the
|
||
|
|
* classifier. */
|
||
|
|
void
|
||
|
|
scaleFactors(std::vector<SVMData> training_set, svm_scaling& scaling);
|
||
|
|
|
||
|
|
public:
|
||
|
|
/** Constructor. */
|
||
|
|
SVMTrain() : debug_(false), cross_validation_(0), nr_fold_(0)
|
||
|
|
{
|
||
|
|
class_name_ = "SVMTrain";
|
||
|
|
svm_set_print_string_function(
|
||
|
|
&printNull); // Default to NULL to not print debugging info
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Destructor. */
|
||
|
|
~SVMTrain()
|
||
|
|
{
|
||
|
|
if (model_.l > 0)
|
||
|
|
svm_free_model_content(&model_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Change default training parameters (pcl::SVMParam). */
|
||
|
|
void
|
||
|
|
setParameters(SVMParam param)
|
||
|
|
{
|
||
|
|
param_ = param;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Return the current training parameters. */
|
||
|
|
SVMParam
|
||
|
|
getParameters()
|
||
|
|
{
|
||
|
|
return param_;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Return the result of the training. */
|
||
|
|
SVMModel
|
||
|
|
getClassifierModel()
|
||
|
|
{
|
||
|
|
return model_;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** It adds/store the training set with labelled data. */
|
||
|
|
void
|
||
|
|
setInputTrainingSet(std::vector<SVMData> training_set)
|
||
|
|
{
|
||
|
|
training_set_.insert(training_set_.end(), training_set.begin(), training_set.end());
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Return the current training set. */
|
||
|
|
std::vector<SVMData>
|
||
|
|
getInputTrainingSet()
|
||
|
|
{
|
||
|
|
return training_set_;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Reset the training set. */
|
||
|
|
void
|
||
|
|
resetTrainingSet()
|
||
|
|
{
|
||
|
|
training_set_.clear();
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Start the training of the SVM classifier.
|
||
|
|
*
|
||
|
|
* \return false if fails
|
||
|
|
*/
|
||
|
|
bool
|
||
|
|
trainClassifier();
|
||
|
|
|
||
|
|
/** Read in a problem (in svmlight format).
|
||
|
|
*
|
||
|
|
* \return false if fails
|
||
|
|
*/
|
||
|
|
bool
|
||
|
|
loadProblem(const char* filename)
|
||
|
|
{
|
||
|
|
return SVM::loadProblem(filename, prob_);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** Set to 1 for debugging info. */
|
||
|
|
void
|
||
|
|
setDebugMode(bool in)
|
||
|
|
{
|
||
|
|
debug_ = in;
|
||
|
|
|
||
|
|
if (in)
|
||
|
|
svm_set_print_string_function(nullptr);
|
||
|
|
else
|
||
|
|
svm_set_print_string_function(&printNull);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** Save the raw training set in a file (in svmlight format).
|
||
|
|
*
|
||
|
|
* \return false if fails
|
||
|
|
*/
|
||
|
|
bool
|
||
|
|
saveTrainingSet(const char* filename)
|
||
|
|
{
|
||
|
|
return SVM::saveProblem(filename, true);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** Save the normalized training set in a file (in svmlight format).
|
||
|
|
*
|
||
|
|
* \return false if fails
|
||
|
|
*/
|
||
|
|
bool
|
||
|
|
saveNormTrainingSet(const char* filename)
|
||
|
|
{
|
||
|
|
return SVM::saveProblemNorm(filename, prob_, true);
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
/** SVM (Support Vector Machines) classification of a dataset.
|
||
|
|
*
|
||
|
|
* It can be used both for testing a classifier model and for classify of new data.
|
||
|
|
*/
|
||
|
|
class SVMClassify : public SVM {
|
||
|
|
protected:
|
||
|
|
using SVM::class_name_;
|
||
|
|
using SVM::labelled_training_set_;
|
||
|
|
using SVM::line_;
|
||
|
|
using SVM::max_line_len_;
|
||
|
|
using SVM::model_;
|
||
|
|
using SVM::param_;
|
||
|
|
using SVM::prob_;
|
||
|
|
using SVM::scaling_;
|
||
|
|
using SVM::training_set_;
|
||
|
|
|
||
|
|
bool model_extern_copied_; // Set to 0 if the model is loaded from an extern file.
|
||
|
|
bool predict_probability_; // Set to 1 to predict probabilities.
|
||
|
|
std::vector<std::vector<double>> prediction_; // It stores the resulting prediction.
|
||
|
|
|
||
|
|
/** It scales the input dataset using the model information. */
|
||
|
|
void
|
||
|
|
scaleProblem(svm_problem& input, svm_scaling scaling);
|
||
|
|
|
||
|
|
public:
|
||
|
|
/** Constructor. */
|
||
|
|
SVMClassify() : model_extern_copied_(false), predict_probability_(false)
|
||
|
|
{
|
||
|
|
class_name_ = "SvmClassify";
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Destructor. */
|
||
|
|
~SVMClassify()
|
||
|
|
{
|
||
|
|
if (!model_extern_copied_ && model_.l > 0)
|
||
|
|
svm_free_model_content(&model_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** It adds/store the training set with labelled data. */
|
||
|
|
void
|
||
|
|
setInputTrainingSet(std::vector<SVMData> training_set)
|
||
|
|
{
|
||
|
|
assert(training_set.size() > 0);
|
||
|
|
|
||
|
|
if (scaling_.max == 0) {
|
||
|
|
// to be sure to have loaded the scaling
|
||
|
|
PCL_ERROR("[pcl::%s::setInputTrainingSet] Classifier model not loaded!\n",
|
||
|
|
getClassName().c_str());
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
training_set_.insert(training_set_.end(), training_set.begin(), training_set.end());
|
||
|
|
SVM::adaptInputToLibSVM(training_set_, prob_);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Return the current training set. */
|
||
|
|
std::vector<SVMData>
|
||
|
|
getInputTrainingSet()
|
||
|
|
{
|
||
|
|
return training_set_;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Reset the training set. */
|
||
|
|
void
|
||
|
|
resetTrainingSet()
|
||
|
|
{
|
||
|
|
training_set_.clear();
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Read in a classifier model (in svmlight format).
|
||
|
|
*
|
||
|
|
* \return false if fails
|
||
|
|
*/
|
||
|
|
bool
|
||
|
|
loadClassifierModel(const char* filename);
|
||
|
|
|
||
|
|
/** Get the result of the classification. */
|
||
|
|
void
|
||
|
|
getClassificationResult(std::vector<std::vector<double>>& out)
|
||
|
|
{
|
||
|
|
out.clear();
|
||
|
|
out.insert(out.begin(), prediction_.begin(), prediction_.end());
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Save the classification result in an extern file. */
|
||
|
|
void
|
||
|
|
saveClassificationResult(const char* filename);
|
||
|
|
|
||
|
|
/** Set the classifier model. */
|
||
|
|
void
|
||
|
|
setClassifierModel(SVMModel model)
|
||
|
|
{
|
||
|
|
// model (inner pointers are references)
|
||
|
|
model_ = model;
|
||
|
|
int i = 0;
|
||
|
|
|
||
|
|
while (model_.scaling[i].index != -1)
|
||
|
|
i++;
|
||
|
|
|
||
|
|
scaling_.max = i;
|
||
|
|
scaling_.obj = Malloc(struct svm_node, i + 1);
|
||
|
|
scaling_.obj[i].index = -1;
|
||
|
|
|
||
|
|
// Performing full scaling copy
|
||
|
|
for (int j = 0; j < i; j++) {
|
||
|
|
scaling_.obj[j] = model_.scaling[j];
|
||
|
|
}
|
||
|
|
|
||
|
|
model_extern_copied_ = true;
|
||
|
|
};
|
||
|
|
|
||
|
|
/** Read in a raw classification problem (in svmlight format).
|
||
|
|
*
|
||
|
|
* The values are normalized using the classifier model information.
|
||
|
|
*
|
||
|
|
* \return false if fails
|
||
|
|
*/
|
||
|
|
bool
|
||
|
|
loadClassProblem(const char* filename)
|
||
|
|
{
|
||
|
|
assert(model_.l != 0);
|
||
|
|
|
||
|
|
bool out = SVM::loadProblem(filename, prob_);
|
||
|
|
SVM::adaptLibSVMToInput(training_set_, prob_);
|
||
|
|
scaleProblem(prob_, scaling_);
|
||
|
|
return out;
|
||
|
|
};
|
||
|
|
|
||
|
|
/** Read in a normalized classification problem (in svmlight format).
|
||
|
|
*
|
||
|
|
* The data are kept whitout normalizing.
|
||
|
|
*
|
||
|
|
* \return false if fails
|
||
|
|
*/
|
||
|
|
bool
|
||
|
|
loadNormClassProblem(const char* filename)
|
||
|
|
{
|
||
|
|
bool out = SVM::loadProblem(filename, prob_);
|
||
|
|
SVM::adaptLibSVMToInput(training_set_, prob_);
|
||
|
|
return out;
|
||
|
|
};
|
||
|
|
|
||
|
|
/** Set whether the classification has to be done with the probability estimate. (The
|
||
|
|
* classifier model has to support it). */
|
||
|
|
void
|
||
|
|
setProbabilityEstimates(bool set)
|
||
|
|
{
|
||
|
|
predict_probability_ = set;
|
||
|
|
};
|
||
|
|
|
||
|
|
/** Start the classification on labelled input dataset.
|
||
|
|
*
|
||
|
|
* It returns the accuracy percentage. To get the classification result, use
|
||
|
|
* getClassificationResult().
|
||
|
|
*
|
||
|
|
* \return false if fails
|
||
|
|
*/
|
||
|
|
bool
|
||
|
|
classificationTest();
|
||
|
|
|
||
|
|
/** Start the classification on un-labelled input dataset.
|
||
|
|
*
|
||
|
|
* To get the classification result, use getClassificationResult().
|
||
|
|
*
|
||
|
|
* \return false if fails
|
||
|
|
*/
|
||
|
|
bool
|
||
|
|
classification();
|
||
|
|
|
||
|
|
/** Start the classification on a single set. */
|
||
|
|
std::vector<double>
|
||
|
|
classification(SVMData in);
|
||
|
|
|
||
|
|
/** Save the raw classification problem in a file (in svmlight format).
|
||
|
|
*
|
||
|
|
* \return false if fails
|
||
|
|
*/
|
||
|
|
bool
|
||
|
|
saveClassProblem(const char* filename)
|
||
|
|
{
|
||
|
|
return SVM::saveProblem(filename, false);
|
||
|
|
};
|
||
|
|
|
||
|
|
/** Save the normalized classification problem in a file (in svmlight format).
|
||
|
|
*
|
||
|
|
* \return false if fails
|
||
|
|
*/
|
||
|
|
bool
|
||
|
|
saveNormClassProblem(const char* filename)
|
||
|
|
{
|
||
|
|
return SVM::saveProblemNorm(filename, prob_, false);
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
} // namespace pcl
|