Commit c5eafeb7 authored by Julien Michel's avatar Julien Michel

Backed out changeset 8e7130be7049

parent 5286008e
# - Find LibSVM
# LibSVM is a Library for Support Vector Machines
# available at http://www.csie.ntu.edu.tw/~cjlin/libsvm/
#
# The module defines the following variables:
# LIBSVM_FOUND - the system has LibSVM
# LIBSVM_INCLUDE_DIR - where to find svm.h
# LIBSVM_INCLUDE_DIRS - libsvm includes
# LIBSVM_LIBRARY - where to find the LibSVM library
# LIBSVM_LIBRARIES - aditional libraries
# LIBSVM_MAJOR_VERSION - major version
# LIBSVM_MINOR_VERSION - minor version
# LIBSVM_PATCH_VERSION - patch version
# LIBSVM_VERSION_STRING - version (ex. 2.9.0)
# LIBSVM_ROOT_DIR - root dir (ex. /usr/local)
#=============================================================================
# Copyright 2010-2013, Julien Schueller
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. 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.
#
# 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.
# The views and conclusions contained in the software and documentation are those
# of the authors and should not be interpreted as representing official policies,
# either expressed or implied, of the FreeBSD Project.
#=============================================================================
# set LIBSVM_INCLUDE_DIR
find_path ( LIBSVM_INCLUDE_DIR
NAMES
svm.h
PATHS
${LIBSVM_ROOT_DIR}/include
PATH_SUFFIXES
libsvm
libsvm-2.0/libsvm
)
# set LIBSVM_INCLUDE_DIRS
if ( LIBSVM_INCLUDE_DIR )
set ( LIBSVM_INCLUDE_DIRS ${LIBSVM_INCLUDE_DIR} )
endif ()
# version
set ( _VERSION_FILE ${LIBSVM_INCLUDE_DIR}/svm.h )
if ( EXISTS ${_VERSION_FILE} )
# LIBSVM_VERSION_STRING macro defined in svm.h since version 2.8.9
file ( STRINGS ${_VERSION_FILE} _VERSION_STRING REGEX ".*define[ ]+LIBSVM_VERSION[ ]+[0-9]+.*" )
if ( _VERSION_STRING )
string ( REGEX REPLACE ".*LIBSVM_VERSION[ ]+([0-9]+)" "\\1" _VERSION_NUMBER "${_VERSION_STRING}" )
math ( EXPR LIBSVM_MAJOR_VERSION "${_VERSION_NUMBER} / 100" )
math ( EXPR LIBSVM_MINOR_VERSION "(${_VERSION_NUMBER} % 100 ) / 10" )
math ( EXPR LIBSVM_PATCH_VERSION "${_VERSION_NUMBER} % 10" )
set ( LIBSVM_VERSION_STRING "${LIBSVM_MAJOR_VERSION}.${LIBSVM_MINOR_VERSION}.${LIBSVM_PATCH_VERSION}" )
endif ()
endif ()
# check version
set ( _LIBSVM_VERSION_MATCH TRUE )
if ( LibSVM_FIND_VERSION AND LIBSVM_VERSION_STRING )
if ( LibSVM_FIND_VERSION_EXACT )
if ( NOT LibSVM_FIND_VERSION VERSION_EQUAL LIBSVM_VERSION_STRING )
set ( _LIBSVM_VERSION_MATCH FALSE )
endif ()
else ()
if ( LIBSVM_VERSION_STRING VERSION_LESS LibSVM_FIND_VERSION )
set ( _LIBSVM_VERSION_MATCH FALSE )
endif ()
endif ()
endif ()
# set LIBSVM_LIBRARY
find_library ( LIBSVM_LIBRARY
NAMES
svm
PATHS
${LIBSVM_ROOT_DIR}/lib
DOC
"LibSVM library location"
)
# set LIBSVM_LIBRARIES
set ( LIBSVM_LIBRARIES ${LIBSVM_LIBRARY} )
# link with math library on unix
if ( UNIX )
list ( APPEND LIBSVM_LIBRARIES "-lm" )
endif ()
# try to guess root dir from include dir
if ( LIBSVM_INCLUDE_DIR )
string ( REGEX REPLACE "(.*)/include.*" "\\1" LIBSVM_ROOT_DIR ${LIBSVM_INCLUDE_DIR} )
# try to guess root dir from library dir
elseif ( LIBSVM_LIBRARY )
string ( REGEX REPLACE "(.*)/lib[/|32|64].*" "\\1" LIBSVM_ROOT_DIR ${LIBSVM_LIBRARY} )
endif ()
# handle REQUIRED and QUIET options
include ( FindPackageHandleStandardArgs )
if ( CMAKE_VERSION LESS 2.8.3 )
find_package_handle_standard_args ( LibSVM DEFAULT_MSG LIBSVM_LIBRARY LIBSVM_INCLUDE_DIR _LIBSVM_VERSION_MATCH )
else ()
find_package_handle_standard_args ( LibSVM REQUIRED_VARS LIBSVM_LIBRARY LIBSVM_INCLUDE_DIR _LIBSVM_VERSION_MATCH VERSION_VAR LIBSVM_VERSION_STRING )
endif ()
mark_as_advanced (
LIBSVM_LIBRARY
LIBSVM_LIBRARIES
LIBSVM_INCLUDE_DIR
LIBSVM_INCLUDE_DIRS
LIBSVM_ROOT_DIR
LIBSVM_VERSION_STRING
LIBSVM_MAJOR_VERSION
LIBSVM_MINOR_VERSION
LIBSVM_PATCH_VERSION
)
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.
Copyright (c) GET / ENST Bretagne. All rights reserved.
See GETCopyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef __otbChangeProfileKernelFunctor_h
#define __otbChangeProfileKernelFunctor_h
#include "otb_libsvm.h"
namespace otb
{
/**
* \class ChangeProfileKernelFunctor
* \brief Change Profile Kernel.
*
* Performs a decision point of view dedicated to the multiscale
* change profile delivered by otb::KullbackLeiblerProfileImageFilter.
*
* It is implemented as a polynomial kernel:
* \f$ \exp - \left( \gamma \left( \max_i | x_i - y_i | \right)^\textrm{degree} + \textrm{coef} \right) \f$.
*
* The parameters \f$ \gamma \f$, \f$ \textrm{coef} \f$ and \f$ \textrm{degree} \f$ are
* to be fixed through \code SetValue \endcode with keywords: Gamma (def 1.0),
* Coef (def 1.0) and Degree (def 1.0).
*
* \ingroup OTBSVMLearning
*/
class ChangeProfileKernelFunctor
: public GenericKernelFunctorBase
{
public:
typedef ChangeProfileKernelFunctor Self;
typedef GenericKernelFunctorBase Superclass;
// Deep copy operator
virtual GenericKernelFunctorBase* Clone() const
{
return new Self(*this);
}
double operator ()(const svm_node * x, const svm_node * y,
const svm_parameter& param) const;
ChangeProfileKernelFunctor ();
virtual ~ChangeProfileKernelFunctor () {}
/** Specific implementation of \code Update \endcode to split m_MapParameters
* into specific variables to speed up kernel evaluations */
void Update();
protected:
ChangeProfileKernelFunctor(const Self& copy)
: Superclass(copy)
{
*this = copy;
}
ChangeProfileKernelFunctor&
operator=(const Self& copy)
{
Superclass::operator =(copy);
Update();
return *this;
}
private:
double m_Coef;
double m_Degree;
double m_Gamma;
};
} // end of namespace otb
#endif
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.
Copyright (c) GET / ENST Bretagne. All rights reserved.
See GETCopyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef __otbMixturePolyRBFKernelFunctor_h
#define __otbMixturePolyRBFKernelFunctor_h
#include "otb_libsvm.h"
namespace otb
{
/** \class MixturePolyRBFKernelFunctor
* \brief Mixture of kernels.
*
* Performs the mixture of kind: \f$ \mu k_1(x, y) + (1-\mu) k_2(x, y) \f$
* with \f$ k_1(x, y)=\left( \gamma_1 x\cdot y + c_0 \right) ^d \f$ a
* polynomial kernel and
* \f$ k_2(x, y) = \exp\left( - \gamma_2 \| x-y\-^2 \right) \f$ an RBF one.
*
* Variable to be instanciated (through \code SetValue \endcode) are:
* Mixture (def=0.5), GammaPoly (def=1.0), CoefPoly (def=1.0),
* DegreePoly (def=2), GammaRBF (def=1.0)
*
* \ingroup OTBSVMLearning
*/
class MixturePolyRBFKernelFunctor
: public GenericKernelFunctorBase
{
public:
typedef MixturePolyRBFKernelFunctor Self;
typedef GenericKernelFunctorBase Superclass;
double operator ()(const svm_node * x, const svm_node * y,
const svm_parameter& param) const;
// Deep copy operator
virtual GenericKernelFunctorBase* Clone() const
{
return new Self(*this);
}
MixturePolyRBFKernelFunctor ();
virtual ~MixturePolyRBFKernelFunctor () {}
/** Specific implementation of \code Update \endcode to split m_MapParameters
* into specific variables to speed up kernel evaluations */
void Update();
protected:
MixturePolyRBFKernelFunctor(const Self& copy)
: Superclass(copy)
{
*this = copy;
}
MixturePolyRBFKernelFunctor&
operator=(const Self& copy)
{
Superclass::operator =(copy);
Update();
return *this;
}
double m_Mixture;
double m_GammaPoly;
double m_CoefPoly;
int m_DegreePoly;
double m_GammaRBF;
private:
inline double powi(double base, int times) const;
};
} // end of namespace otb
#endif
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.
Copyright (c) GET / ENST Bretagne. All rights reserved.
See GETCopyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef __otbNonGaussianRBFKernelFunctor_h
#define __otbNonGaussianRBFKernelFunctor_h
#include "otb_libsvm.h"
//FIXME: shouldn't it be in the Functor namespace?
namespace otb
{
/** \class NonGaussianRBFKernelFunctor
* \brief Performs an RBF kernel evaluation that better suit sample distribution with high Kurtosis.
*
* It is of kind
* \f$ \exp\left( - \gamma \sum_i | x_i^\alpha - y_i^\alpha |^\beta \right) \f$
* where \f$ 0 \leqslant \alpha \leqslant 1 \f$ and
* \f$ 0 \leqslant \beta \leqslant 2 \f$.
*
* Variables to be instanciated (through \code SetValue \endcode) are:
* Alpha (def=1), Beta (def=2) and Gamma (def 1.0).
*
*
* \ingroup OTBSVMLearning
*/
class NonGaussianRBFKernelFunctor
: public GenericKernelFunctorBase
{
public:
typedef NonGaussianRBFKernelFunctor Self;
typedef GenericKernelFunctorBase Superclass;
// Deep copy operator
virtual GenericKernelFunctorBase* Clone() const
{
return new Self(*this);
}
double operator ()(const svm_node * x, const svm_node * y,
const svm_parameter& param) const;
NonGaussianRBFKernelFunctor ();
virtual ~NonGaussianRBFKernelFunctor () {}
/** Specific implementation of \code Update \endcode to split m_MapParameters
* into specific variables to speed up kernel evaluations */
void Update();
protected:
NonGaussianRBFKernelFunctor(const Self& copy)
: Superclass(copy)
{
*this = copy;
}
NonGaussianRBFKernelFunctor&
operator=(const Self& copy)
{
Superclass::operator =(copy);
Update();
return *this;
}
protected:
double m_Alpha;
double m_Beta;
double m_Gamma;
};
} // end of namespace otb
#endif
......@@ -157,7 +157,6 @@ public:
/** Make a DataObject of the correct type to be used as the specified
* output. */
itk::DataObject::Pointer MakeOutput(DataObjectPointerArraySizeType idx);
using Superclass::MakeOutput;
void AllocateOutputs();
......
......@@ -89,6 +89,7 @@ public:
/** Returns the classification result */
OutputType* GetOutput();
void SetOutput(OutputType* output);
/** Returns the hyperplanes distances */
HyperplanesDistancesListSampleType * GetHyperplanesDistancesOutput();
......@@ -108,10 +109,6 @@ public:
protected:
SVMClassifier();
virtual ~SVMClassifier() {}
void SetOutput(OutputType* output);
using Superclass::SetOutput;
void PrintSelf(std::ostream& os, itk::Indent indent) const;
/** Starts the classification process */
......
This diff is collapsed.
......@@ -96,11 +96,11 @@ SVMMarginSampler< TSample, TModel >
double minDistance = vcl_abs(hdistances[0]);
// Compute th min distances
for(unsigned int j = 1; j<hdistances.Size(); ++j)
for(unsigned int i = 1; i<hdistances.Size(); ++i)
{
if(vcl_abs(hdistances[j])<minDistance)
if(vcl_abs(hdistances[i])<minDistance)
{
minDistance = vcl_abs(hdistances[j]);
minDistance = vcl_abs(hdistances[i]);
}
}
// Keep index and min distance
......
......@@ -99,6 +99,10 @@ public:
return (unsigned int) (m_Model->nr_class * (m_Model->nr_class - 1) / 2);
}
/** Set a new model. To avoid pointers holding conflicts, this
* method actually makes a copy of aModel */
void SetModel(struct svm_model* aModel);
/** Gets the model */
const struct svm_model* GetModel()
{
......@@ -132,11 +136,13 @@ public:
this->LoadModel(model_file_name.c_str());
}
/** Copy the model */
Pointer GetCopy() const;
/** Set the SVM type to C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR */
void SetSVMType(int svmtype)
{
m_Parameters.svm_type = svmtype;
m_ModelUpToDate = false;
this->Modified();
}
......@@ -154,7 +160,6 @@ public:
void SetKernelType(int kerneltype)
{
m_Parameters.kernel_type = kerneltype;
m_ModelUpToDate = false;
this->Modified();
}
......@@ -168,7 +173,6 @@ public:
void SetPolynomialKernelDegree(int degree)
{
m_Parameters.degree = degree;
m_ModelUpToDate = false;
this->Modified();
}
......@@ -182,7 +186,6 @@ public:
virtual void SetKernelGamma(double gamma)
{
m_Parameters.gamma = gamma;
m_ModelUpToDate = false;
this->Modified();
}
/** Get the gamma parameter for poly/rbf/sigmoid kernels */
......@@ -195,7 +198,6 @@ public:
void SetKernelCoef0(double coef0)
{
m_Parameters.coef0 = coef0;
m_ModelUpToDate = false;
this->Modified();
}
......@@ -210,7 +212,6 @@ public:
void SetNu(double nu)
{
m_Parameters.nu = nu;
m_ModelUpToDate = false;
this->Modified();
}
......@@ -225,7 +226,6 @@ public:
void SetCacheSize(int cSize)
{
m_Parameters.cache_size = static_cast<double>(cSize);
m_ModelUpToDate = false;
this->Modified();
}
......@@ -239,7 +239,6 @@ public:
void SetC(double c)
{
m_Parameters.C = c;
m_ModelUpToDate = false;
this->Modified();
}
......@@ -253,7 +252,6 @@ public:
void SetEpsilon(double eps)
{
m_Parameters.eps = eps;
m_ModelUpToDate = false;
this->Modified();
}
......@@ -267,7 +265,6 @@ public:
void SetP(double p)
{
m_Parameters.p = p;
m_ModelUpToDate = false;
this->Modified();
}
......@@ -281,7 +278,6 @@ public:
void DoShrinking(bool s)
{
m_Parameters.shrinking = static_cast<int>(s);
m_ModelUpToDate = false;
this->Modified();
}
......@@ -295,7 +291,6 @@ public:
void DoProbabilityEstimates(bool prob)
{
m_Parameters.probability = static_cast<int>(prob);
m_ModelUpToDate = false;
this->Modified();
}
......@@ -305,6 +300,19 @@ public:
return static_cast<bool>(m_Parameters.probability);
}
/** Get/Set methods for generic kernel functor */
GenericKernelFunctorBase * GetKernelFunctor(void) const
{
return m_Parameters.kernel_generic;
}
void SetKernelFunctor(GenericKernelFunctorBase* pGenericKernelFunctor)
{
if (pGenericKernelFunctor != NULL)
m_Parameters.kernel_generic = pGenericKernelFunctor->Clone();
this->Modified();
}
/** Return number of support vectors */
int GetNumberOfSupportVectors(void) const
{
......@@ -349,6 +357,13 @@ public:
return m_Problem;
}
/** Reset ModelUpToDate */
virtual void Modified() const
{
Superclass::Modified();
m_ModelUpToDate = false;
}
/** Allocate the problem */
void BuildProblem();
......
......@@ -34,6 +34,7 @@ SVMModel<TValue, TLabel>::SVMModel()
this->SetPolynomialKernelDegree(3);
this->SetKernelGamma(1.); // 1/k
this->SetKernelCoef0(1.);
this->SetKernelFunctor(NULL);
this->SetNu(0.5);
this->SetCacheSize(40);
this->SetC(1);
......@@ -42,6 +43,8 @@ SVMModel<TValue, TLabel>::SVMModel()
this->DoShrinking(true);
this->DoProbabilityEstimates(false);
m_Parameters.kernel_generic = NULL;
m_Parameters.kernel_composed = NULL;
m_Parameters.nr_weight = 0;
m_Parameters.weight_label = NULL;
m_Parameters.weight = NULL;
......@@ -241,7 +244,9 @@ SVMModel<TValue, TLabel>::BuildProblem()
}
// Compute the kernel gamma from maxElementIndex if necessary
if (this->GetKernelGamma() == 0) this->SetKernelGamma(1.0 / static_cast<double>(maxElementIndex));
if (this->GetKernelGamma() == 0
&& this->GetParameters().kernel_type != COMPOSED
&& this->GetParameters().kernel_type != GENERIC) this->SetKernelGamma(1.0 / static_cast<double>(maxElementIndex));
// problem is up-to-date
m_ProblemUpToDate = true;
......@@ -323,8 +328,6 @@ SVMModel<TValue, TLabel>::Train()
// train the model
m_Model = svm_train(&m_Problem, &m_Parameters);
std::cout<<"In train"<<std::endl;
// Set the model as up-to-date
m_ModelUpToDate = true;
}
......@@ -508,6 +511,15 @@ SVMModel<TValue, TLabel>::EvaluateProbabilities(const MeasurementType& measure)
return probabilities;
}
template <class TValue, class TLabel>
void
SVMModel<TValue, TLabel>::SetModel(struct svm_model* aModel)
{
this->DeleteModel();
m_Model = svm_copy_model(aModel);
m_ModelUpToDate = true;
}
template <class TValue, class TLabel>
void
SVMModel<TValue, TLabel>::SaveModel(const char* model_file_name) const
......@@ -524,7 +536,7 @@ void
SVMModel<TValue, TLabel>::LoadModel(const char* model_file_name)
{
this->DeleteModel();
m_Model = svm_load_model(model_file_name);
m_Model = svm_load_model(model_file_name, m_Parameters.kernel_generic);
if (m_Model == 0)
{
itkExceptionMacro(<< "Problem while loading SVM model "
......@@ -534,6 +546,16 @@ SVMModel<TValue, TLabel>::LoadModel(const char* model_file_name)
m_ModelUpToDate = true;
}
template <class TValue, class TLabel>
typename SVMModel<TValue, TLabel>::Pointer
SVMModel<TValue, TLabel>::GetCopy() const
{
Pointer modelCopy = New();
modelCopy->SetModel(m_Model);
// We do not copy the problem to avoid sharing allocated memory
return modelCopy;
}
template <class TValue, class TLabel>
void
SVMModel<TValue, TLabel>::PrintSelf(std::ostream& os, itk::Indent indent) const
......
......@@ -272,6 +272,17 @@ public:
return (this->GetModel()->GetDoProbabilityEstimates());
}
/** Get/Set methods for generic kernel functor */
virtual GenericKernelFunctorBase * GetKernelFunctor(void) const
{
return this->GetModel()->GetKernelFunctor();
}
virtual void SetKernelFunctor(GenericKernelFunctorBase* pGenericKernelFunctor)
{
this->GetModel()->SetKernelFunctor(pGenericKernelFunctor);
this->Modified();
}
/** Save the model */
virtual void SaveModel(const char * fname)
{
......
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
</