From fb68a33471c821ecade2bb7d909d5f14ba4c64de Mon Sep 17 00:00:00 2001 From: Thomas Feuvrier <thomas.feuvrier@c-s.fr> Date: Thu, 27 Sep 2007 08:07:24 +0000 Subject: [PATCH] Ajout test SVM (accesseur sur la class SVMModel) --- Code/Learning/otbSVMModel.h | 58 ++++-- Code/Learning/otbSVMModel.txx | 57 ++++-- Testing/Code/Learning/CMakeLists.txt | 18 ++ Testing/Code/Learning/otbLearningTests.cxx | 2 + ...otbSVMImageModelEstimatorModelAccessor.cxx | 188 ++++++++++++++++++ Testing/Code/Learning/otbSVMModelAccessor.cxx | 145 ++++++++++++++ 6 files changed, 431 insertions(+), 37 deletions(-) create mode 100644 Testing/Code/Learning/otbSVMImageModelEstimatorModelAccessor.cxx create mode 100644 Testing/Code/Learning/otbSVMModelAccessor.cxx diff --git a/Code/Learning/otbSVMModel.h b/Code/Learning/otbSVMModel.h index 648511d64f..59e74bbdf7 100644 --- a/Code/Learning/otbSVMModel.h +++ b/Code/Learning/otbSVMModel.h @@ -19,13 +19,11 @@ #define _otbSVMModel_h #include "itkDataObject.h" +#include "itkVariableLengthVector.h" -//extern "C" -//{ #include "svm.h" -//} -#define Malloc(type,n) (type *)malloc((n)*sizeof(type)) +//#define Malloc(type,n) (type *)malloc((n)*sizeof(type)) namespace otb { @@ -88,6 +86,8 @@ public: typedef TInputPixel InputPixelType; typedef TLabel LabelType; + typedef itk::VariableLengthVector<double> ValuesType; + /** Type definitions for the training image. */ //typedef typename TTrainingImage::Pointer TrainingImagePointer; @@ -131,21 +131,39 @@ public: // void Update() ; /** Set the number of classes. */ - itkSetMacro(NumberOfClasses, unsigned int); +// itkSetMacro(NumberOfClasses, unsigned int); + void SetNumberOfClasses(const unsigned int nr_class) + { + m_Model->nr_class = (int)nr_class; + } /** Get the number of classes. */ - itkGetConstReferenceMacro(NumberOfClasses, unsigned int); + unsigned int GetNumberOfClasses(void) + { + return (unsigned int)(m_Model->nr_class); + } + + /** Get the number of hyperplane. */ + unsigned int GetNumberOfHyperplane(void) + { + return (unsigned int)(m_Model->nr_class - 1); + } /** Gets the problem */ struct svm_problem GetProblem() { - return m_Problem ; + return m_Problem ; } - /** Gets the problem */ + /** Sets the x space */ + void SetXSpace(struct svm_node* x_space) + { + m_XSpace = x_space; + } + /** Gets the x space */ struct svm_node* GetXSpace() { - return x_space; + return m_XSpace; } /** Allocates the problem */ @@ -168,10 +186,6 @@ public: /** Loads the model from a file */ void LoadModel(const char* model_file_name); - int GetNumberOfClasses() - { - return m_Model->nr_class; - } /** Get/Set methods for generic kernel functor */ virtual GenericKernelFunctorBase * GetKernelFunctor(void)const @@ -198,6 +212,20 @@ public: { return m_Model->SV; } + /** Return the alphas values (SV Coef) */ + double ** GetAlpha (void) + { + return m_Model->sv_coef; + } + + /** Evaluate model */ + double Evaluate(void); + + /** Evaluate hyperplane distance model. + * Return NumberOfClasses*(NumberOfClasses-1)/2 elements + */ + ValuesType EvaluateHyperplaneDistance(void); + protected: SVMModel(); @@ -212,7 +240,7 @@ private: void operator=(const Self&); //purposely not implemented // unsigned int m_NumberOfModels; - unsigned int m_NumberOfClasses; +// unsigned int m_NumberOfClasses; /** Container to hold the SVM model itself */ struct svm_model* m_Model; @@ -221,7 +249,7 @@ private: struct svm_parameter m_Parameters; struct svm_problem m_Problem; - struct svm_node* x_space; + struct svm_node* m_XSpace; /** Pointer to generic kernel functor */ GenericKernelFunctorBase * m_GenericKernelFunctor; diff --git a/Code/Learning/otbSVMModel.txx b/Code/Learning/otbSVMModel.txx index d4ab41b710..9f30c2b900 100644 --- a/Code/Learning/otbSVMModel.txx +++ b/Code/Learning/otbSVMModel.txx @@ -39,7 +39,7 @@ SVMModel< TInputPixel, TLabel >::SVMModel() otbMsgDevMacro( << "SVMModel::SVMModel - m_Problem.l = " << m_Problem.l ); m_Problem.y = new double[1]; m_Problem.x = new struct svm_node*[1]; - x_space = new struct svm_node[1]; + m_XSpace = new struct svm_node[1]; m_GenericKernelFunctor = NULL; } @@ -55,9 +55,9 @@ SVMModel<TInputPixel, TLabel>::~SVMModel() otbMsgDevMacro( << "SVMModel destructor - y done" ); delete [] m_Problem.x; //free(m_Problem.x); otbMsgDevMacro( << "SVMModel destructor - x done" ); - delete [] x_space;// - otbMsgDevMacro( << "SVMModel destructor - x_space done" ); - //free(x_space); + delete [] m_XSpace;// + otbMsgDevMacro( << "SVMModel destructor - m_XSpace done" ); + //free(m_XSpace); */ //svm_destroy_model(m_Model); @@ -82,11 +82,11 @@ SVMModel<TInputPixel, TLabel> delete [] m_Problem.x; m_Problem.x = new struct svm_node*[l];//Malloc(struct svm_node* ,l); otbMsgDevMacro( << "SVMModel::AllocateProblem - x done" ); - delete [] x_space; - x_space = new struct svm_node[elements]; - //free(x_space); - //x_space = Malloc(struct svm_node,elements); - //otbMsgDevMacro( << "SVMModel::AllocateProblem - x_space done" ); + delete [] m_XSpace; + m_XSpace = new struct svm_node[elements]; + //free(m_XSpace); + //m_XSpace = Malloc(struct svm_node,elements); + //otbMsgDevMacro( << "SVMModel::AllocateProblem - m_XSpace done" ); } @@ -116,20 +116,13 @@ SVMModel<TInputPixel, TLabel> // aProblem.y = m_Problem.y; // aProblem.x = m_Problem.x; -// otbMsgDevMacro( << "SVMModel::GetProblem - x_space " << x_space ); -// // aNode = x_space; +// otbMsgDevMacro( << "SVMModel::GetProblem - m_XSpace " << m_XSpace ); +// // aNode = m_XSpace; // otbMsgDevMacro( << "SVMModel::GetProblem - out" ); -// return x_space; +// return m_XSpace; } -template <class TInputPixel, class TLabel > -struct svm_node* -SVMModel<TInputPixel, TLabel> -::GetXSpace() - { - return x_space; - - }*/ +*/ template <class TInputPixel, class TLabel > @@ -162,10 +155,30 @@ void SVMModel<TInputPixel, TLabel> ::PrintSelf(std::ostream& os, itk::Indent indent) const { Superclass::PrintSelf(os,indent); } -// FIXME -}// end namespace otb +template <class TInputPixel, class TLabel > +double +SVMModel<TInputPixel, TLabel> +::Evaluate(void) +{ + return( svm_predict(m_Model,m_XSpace)); +} + +template <class TInputPixel, class TLabel > +typename SVMModel<TInputPixel, TLabel>::ValuesType +SVMModel<TInputPixel, TLabel> +::EvaluateHyperplaneDistance(void) +{ + ValuesType values; + values.SetSize( m_Model->nr_class*(m_Model->nr_class-1)/2); + + svm_predict_values(m_Model, m_XSpace, (double*)(values.GetDataPointer())); + return (values); +} + +// FIXME +}// end namespace otb #endif diff --git a/Testing/Code/Learning/CMakeLists.txt b/Testing/Code/Learning/CMakeLists.txt index e772ef3173..1dc5b7bb7d 100644 --- a/Testing/Code/Learning/CMakeLists.txt +++ b/Testing/Code/Learning/CMakeLists.txt @@ -30,6 +30,14 @@ ADD_TEST(leTuSVMModelLoad ${LEARNING_TESTS} otbSVMModelLoad ${INPUTDATA}/svm_model) +ADD_TEST(leTvSVMModelAccessor ${LEARNING_TESTS} +--compare-ascii ${TOL} ${BASELINE_FILES}/leSVMModelAccessor.txt + ${TEMP}/leSVMModelAccessor.txt + otbSVMModelAccessor + ${INPUTDATA}/svm_model + ${TEMP}/leSVMModelAccessor.txt) + + ADD_TEST(leTvSVMModelLoadSave ${LEARNING_TESTS} --compare-ascii ${TOL} ${INPUTDATA}/svm_model ${TEMP}/svmmodel_test @@ -73,6 +81,14 @@ ADD_TEST(leTuSVMImageModelEstimatorTrain ${LEARNING_TESTS} ${INPUTDATA}/ROI_QB_MUL_4_train.c1.hdr ${TEMP}/leTvsvm_model_image) +ADD_TEST(leTvSVMImageModelEstimatorModelAccessor ${LEARNING_TESTS} +--compare-ascii ${TOL} ${BASELINE_FILES}/leSVMModelEstimatorModelAccessor.txt + ${TEMP}/leSVMModelEstimatorModelAccessor.txt + otbSVMImageModelEstimatorModelAccessor + ${INPUTDATA}/ROI_QB_MUL_4.tif + ${INPUTDATA}/ROI_QB_MUL_4_train.c1.hdr + ${TEMP}/leSVMModelEstimatorModelAccessor.txt) + # ------- otb::SVMPointSetModelEstimator -------------------- ADD_TEST(leTuSVMPointSetModelEstimatorNew ${LEARNING_TESTS} @@ -178,11 +194,13 @@ otbSVMModelNew.cxx otbSVMModelAllocateProblem.cxx otbSVMModelLoad.cxx otbSVMModelLoadSave.cxx +otbSVMModelAccessor.cxx otbSVMModelGenericKernelLoadSave.cxx #otbSVMMembershipFunctionNew.cxx #otbSVMMembershipFunctionLoadModel.cxx otbSVMImageModelEstimatorNew.cxx otbSVMImageModelEstimatorTrain.cxx +otbSVMImageModelEstimatorModelAccessor.cxx otbSVMPointSetModelEstimatorNew.cxx otbSVMPointSetModelEstimatorTrain.cxx otbSVMClassifierNew.cxx diff --git a/Testing/Code/Learning/otbLearningTests.cxx b/Testing/Code/Learning/otbLearningTests.cxx index 7e97ce1434..12951216d3 100644 --- a/Testing/Code/Learning/otbLearningTests.cxx +++ b/Testing/Code/Learning/otbLearningTests.cxx @@ -31,12 +31,14 @@ void RegisterTests() REGISTER_TEST(otbSVMModelNew); REGISTER_TEST(otbSVMModelAllocateProblem); REGISTER_TEST(otbSVMModelLoad); +REGISTER_TEST(otbSVMModelAccessor); REGISTER_TEST(otbSVMModelLoadSave); REGISTER_TEST(otbSVMModelGenericKernelLoadSave); //REGISTER_TEST(otbSVMMembershipFunctionNew); //REGISTER_TEST(otbSVMMembershipFunctionLoadModel); REGISTER_TEST(otbSVMImageModelEstimatorNew); REGISTER_TEST(otbSVMImageModelEstimatorTrain); +REGISTER_TEST(otbSVMImageModelEstimatorModelAccessor); REGISTER_TEST(otbSVMPointSetModelEstimatorNew); REGISTER_TEST(otbSVMPointSetModelEstimatorTrain); REGISTER_TEST(otbSVMClassifierNew); diff --git a/Testing/Code/Learning/otbSVMImageModelEstimatorModelAccessor.cxx b/Testing/Code/Learning/otbSVMImageModelEstimatorModelAccessor.cxx new file mode 100644 index 0000000000..ef8ae75cf4 --- /dev/null +++ b/Testing/Code/Learning/otbSVMImageModelEstimatorModelAccessor.cxx @@ -0,0 +1,188 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.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. + +=========================================================================*/ + +#if defined(_MSC_VER) +#pragma warning ( disable : 4786 ) +#endif + +#include "itkExceptionObject.h" +#include "otbImage.h" +#include "otbVectorImage.h" +#include <iostream> +#include <fstream> + +#include "otbSVMModel.h" +#include "otbSVMImageModelEstimator.h" + +#include "otbImageFileReader.h" + + + +int otbSVMImageModelEstimatorModelAccessor( int argc, char* argv[] ) +{ + try + { + const char* inputImageFileName = argv[1]; + const char* trainingImageFileName = argv[2]; + const char* outputModelFileName = argv[3]; + + typedef double InputPixelType; + const unsigned int Dimension = 2; + + typedef otb::VectorImage< InputPixelType, Dimension > InputImageType; + + typedef otb::Image< InputPixelType, Dimension > TrainingImageType; + + typedef otb::SVMImageModelEstimator< InputImageType, + TrainingImageType > EstimatorType; + + typedef otb::ImageFileReader< InputImageType > InputReaderType; + typedef otb::ImageFileReader< TrainingImageType > TrainingReaderType; + + InputReaderType::Pointer inputReader = InputReaderType::New(); + TrainingReaderType::Pointer trainingReader = TrainingReaderType::New(); + + inputReader->SetFileName( inputImageFileName ); + trainingReader->SetFileName( trainingImageFileName ); + + inputReader->Update(); + trainingReader->Update(); + + EstimatorType::Pointer svmEstimator = EstimatorType::New(); + + svmEstimator->SetInputImage( inputReader->GetOutput() ); + svmEstimator->SetTrainingImage( trainingReader->GetOutput() ); + svmEstimator->SetNumberOfClasses( 2 ); + + svmEstimator->Update(); + + typedef EstimatorType::SVMModelPointer SVMModelPointer; + typedef EstimatorType::SVMModelType SVMModelType; + SVMModelPointer ptrModel = svmEstimator->GetModel(); + + + std::ofstream f; + unsigned int nbClass = ptrModel->GetNumberOfClasses(); + unsigned int nbSupportVector = ptrModel->GetNumberOfSupportVectors(); + + f.open(outputModelFileName); + f << "Test methods of SVMModel class:"<<std::endl; + f << " - GetNumberOfClasses() "<< nbClass<<std::endl; + f << " - GetNumberOfHyperplane() "<< ptrModel->GetNumberOfHyperplane()<<std::endl; + f << " - GetNumberOfSupportVectors() "<< nbSupportVector<<std::endl; + + + f << " - GetSupportVectors() [nb support vector][]"<<std::endl; + svm_node ** SVs = ptrModel->GetSupportVectors(); + if( SVs == NULL ) + { + itkGenericExceptionMacro(<<"SVs NULL"); + } + for(unsigned int i=0;i<nbSupportVector;i++) + { + if( SVs[i] == NULL ) itkGenericExceptionMacro(<<"SVs "<<i<<" NULL"); + f << std::endl; + f << " SV["<<i<<"]:"; + const svm_node *p = SVs[i]; +/* for(unsigned int j=0;j<nbSupportVector;j++) + { + f << " SV["<<i<<"]["<<j<<"]:";*/ + if( svmEstimator->GetKernelType() == PRECOMPUTED) + { + f << " "<<p->value; + + } + else + { + while(p->index != -1) + { + f << " ["<<p->index << ";"<<p->value<<"] "; + p++; + } + } + f << std::endl; +// } + } + + f << " - GetRho() [nr_class*(nr_class-1)/2]"<<std::endl; + unsigned int taille = nbClass*(nbClass-1)/2; + double * rhos = ptrModel->GetRho(); + if( rhos == NULL ) + { + itkGenericExceptionMacro(<<"rhos NULL"); + } + f << " "; + for(unsigned int i=0;i<taille;i++) + { + f << " " << rhos[i]; + } + + + f << std::endl; + f << " - GetAlpha() [nb class-1][nb support vector]"<<std::endl; + double ** alphas = ptrModel->GetAlpha(); + if( alphas == NULL ) + { + itkGenericExceptionMacro(<<"alphas NULL"); + } + for(unsigned int i=0;i<nbClass-1;i++) + { + if( alphas[i] == NULL ) itkGenericExceptionMacro(<<"alphas "<<i<<" NULL"); + f << " "; + for(unsigned int j=0;j<nbSupportVector;j++) + { + f << " " << alphas[i][j]; + } + } + f << std::endl; + f << " - Evaluate() (double) -> "<<ptrModel->Evaluate()<<std::endl; + + typedef SVMModelType::ValuesType ValuesType; + ValuesType _evaluateHyperplaneDistance; + _evaluateHyperplaneDistance = ptrModel->EvaluateHyperplaneDistance(); + + f << " - EvaluateHyperplaneDistance() VariableLenghtVector() nb value(s): "<<_evaluateHyperplaneDistance.Size()<<std::endl; + for(unsigned int i=0;i<_evaluateHyperplaneDistance.Size();i++) + { + f << " "<<_evaluateHyperplaneDistance[i]<<std::endl; + } + f << "end"<<std::endl; + f.close(); + + + } + catch( itk::ExceptionObject & err ) + { + std::cout << "Exception itk::ExceptionObject levee !" << std::endl; + std::cout << err << std::endl; + return EXIT_FAILURE; + } + catch( ... ) + { + std::cout << "Unknown exception !" << std::endl; + return EXIT_FAILURE; + } + // Software Guide : EndCodeSnippet + +//#endif + return EXIT_SUCCESS; +} + + + + diff --git a/Testing/Code/Learning/otbSVMModelAccessor.cxx b/Testing/Code/Learning/otbSVMModelAccessor.cxx new file mode 100644 index 0000000000..f6dc626683 --- /dev/null +++ b/Testing/Code/Learning/otbSVMModelAccessor.cxx @@ -0,0 +1,145 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.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. + +=========================================================================*/ + +#if defined(_MSC_VER) +#pragma warning ( disable : 4786 ) +#endif + +#include "itkExceptionObject.h" +#include "otbImage.h" +#include <iostream> +#include <fstream> + +#include "otbSVMModel.h" + + +int otbSVMModelAccessor( int argc, char* argv[] ) +{ + try + { + typedef unsigned char InputPixelType; + typedef unsigned char LabelPixelType; + const unsigned int Dimension = 2; + + typedef otb::Image< InputPixelType, Dimension > InputImageType; + + typedef otb::SVMModel< InputPixelType, LabelPixelType > ModelType; + + + ModelType::Pointer ptrModel = ModelType::New(); + + ptrModel->LoadModel(argv[1]); + + + // ototo + + std::ofstream f; + unsigned int nbClass = ptrModel->GetNumberOfClasses(); + unsigned int nbSupportVector = ptrModel->GetNumberOfSupportVectors(); + + f.open(argv[2]); + f << "Test methods of SVMModel class:"<<std::endl; + f << " - GetNumberOfClasses() "<< nbClass<<std::endl; + f << " - GetNumberOfHyperplane() "<< ptrModel->GetNumberOfHyperplane()<<std::endl; + f << " - GetNumberOfSupportVectors() "<< nbSupportVector<<std::endl; + + + f << " - GetSupportVectors() [nb support vector][]"<<std::endl; + svm_node ** SVs = ptrModel->GetSupportVectors(); + if( SVs == NULL ) + { + itkGenericExceptionMacro(<<"SVs NULL"); + } + for(unsigned int i=0;i<nbSupportVector;i++) + { + if( SVs[i] == NULL ) itkGenericExceptionMacro(<<"SVs "<<i<<" NULL"); + f << std::endl; + f << " SV["<<i<<"]:"; + const svm_node *p = SVs[i]; + while(p->index != -1) + { + f << " ["<<p->index << ";"<<p->value<<"] "; + p++; + } + f << std::endl; + } + + f << " - GetRho() [nr_class*(nr_class-1)/2]"<<std::endl; + unsigned int taille = nbClass*(nbClass-1)/2; + double * rhos = ptrModel->GetRho(); + if( rhos == NULL ) + { + itkGenericExceptionMacro(<<"rhos NULL"); + } + f << " "; + for(unsigned int i=0;i<taille;i++) + { + f << " " << rhos[i]; + } + + + f << std::endl; + f << " - GetAlpha() [nb class-1][nb support vector]"<<std::endl; + double ** alphas = ptrModel->GetAlpha(); + if( alphas == NULL ) + { + itkGenericExceptionMacro(<<"alphas NULL"); + } + for(unsigned int i=0;i<nbClass-1;i++) + { + if( alphas[i] == NULL ) itkGenericExceptionMacro(<<"alphas "<<i<<" NULL"); + f << " "; + for(unsigned int j=0;j<nbSupportVector;j++) + { + f << " " << alphas[i][j]; + } + } + f << std::endl; + f << " - Evaluate() (double) -> "<<ptrModel->Evaluate()<<std::endl; + + typedef ModelType::ValuesType ValuesType; + ValuesType _evaluateHyperplaneDistance; + _evaluateHyperplaneDistance = ptrModel->EvaluateHyperplaneDistance(); + + f << " - EvaluateHyperplaneDistance() VariableLenghtVector() nb value(s): "<<_evaluateHyperplaneDistance.Size()<<std::endl; + for(unsigned int i=0;i<_evaluateHyperplaneDistance.Size();i++) + { + f << " "<<_evaluateHyperplaneDistance[i]<<std::endl; + } + f << "end"<<std::endl; + f.close(); + + } + catch( itk::ExceptionObject & err ) + { + std::cout << "Exception itk::ExceptionObject levee !" << std::endl; + std::cout << err << std::endl; + return EXIT_FAILURE; + } + catch( ... ) + { + std::cout << "Unknown exception !" << std::endl; + return EXIT_FAILURE; + } + // Software Guide : EndCodeSnippet + +//#endif + return EXIT_SUCCESS; +} + + -- GitLab