From 0bf534f66dd6d686e82c89976876ec10a9e5bf9d Mon Sep 17 00:00:00 2001
From: Julien Michel <julien.michel@cnes.fr>
Date: Mon, 16 Nov 2015 16:53:09 +0100
Subject: [PATCH] PERF: Removing SVM OpenCV implementation from available
 algorithm is TrainImagesClassifier, since it is known to be buggy in linear
 mode. Update class documentation as well

---
 .../include/otbLearningApplicationBase.h      | 24 +++++++++++++------
 .../include/otbLearningApplicationBase.txx    | 22 ++++++++++-------
 .../AppClassification/test/CMakeLists.txt     |  5 ++--
 .../include/otbSVMMachineLearningModel.h      |  8 +++++++
 4 files changed, 41 insertions(+), 18 deletions(-)

diff --git a/Modules/Applications/AppClassification/include/otbLearningApplicationBase.h b/Modules/Applications/AppClassification/include/otbLearningApplicationBase.h
index 9af1259c73..c7edff5f5c 100644
--- a/Modules/Applications/AppClassification/include/otbLearningApplicationBase.h
+++ b/Modules/Applications/AppClassification/include/otbLearningApplicationBase.h
@@ -33,7 +33,9 @@
 #ifdef OTB_USE_OPENCV
 # include "otbKNearestNeighborsMachineLearningModel.h"
 # include "otbRandomForestsMachineLearningModel.h"
-# include "otbSVMMachineLearningModel.h"
+// OpenCV SVM implementation is buggy with linear kernel
+// Users should use the libSVM implementation instead.
+//# include "otbSVMMachineLearningModel.h"
 # include "otbBoostMachineLearningModel.h"
 # include "otbDecisionTreeMachineLearningModel.h"
 # include "otbGradientBoostedTreeMachineLearningModel.h"
@@ -116,7 +118,9 @@ public:
 #ifdef OTB_USE_OPENCV
   typedef otb::RandomForestsMachineLearningModel<InputValueType, OutputValueType> RandomForestType;
   typedef otb::KNearestNeighborsMachineLearningModel<InputValueType, OutputValueType> KNNType;
-  typedef otb::SVMMachineLearningModel<InputValueType, OutputValueType> SVMType;
+  // OpenCV SVM implementation is buggy with linear kernel
+  // Users should use the libSVM implementation instead.
+  // typedef otb::SVMMachineLearningModel<InputValueType, OutputValueType> SVMType;
   typedef otb::BoostMachineLearningModel<InputValueType, OutputValueType> BoostType;
   typedef otb::DecisionTreeMachineLearningModel<InputValueType, OutputValueType> DecisionTreeType;
   typedef otb::GradientBoostedTreeMachineLearningModel<InputValueType, OutputValueType> GradientBoostedTreeType;
@@ -163,7 +167,9 @@ private:
 
 #ifdef OTB_USE_OPENCV
   void InitBoostParams();
-  void InitSVMParams();
+  // OpenCV SVM implementation is buggy with linear kernel
+  // Users should use the libSVM implementation instead.
+  // void InitSVMParams();
   void InitDecisionTreeParams();
   void InitGradientBoostedTreeParams();
   void InitNeuralNetworkParams();
@@ -174,9 +180,11 @@ private:
   void TrainBoost(typename ListSampleType::Pointer trainingListSample,
                   typename TargetListSampleType::Pointer trainingLabeledListSample,
                   std::string modelPath);
-  void TrainSVM(typename ListSampleType::Pointer trainingListSample,
-                typename TargetListSampleType::Pointer trainingLabeledListSample,
-                std::string modelPath);
+  // OpenCV SVM implementation is buggy with linear kernel
+  // Users should use the libSVM implementation instead.
+  // void TrainSVM(typename ListSampleType::Pointer trainingListSample,
+  //              typename TargetListSampleType::Pointer trainingLabeledListSample,
+  //              std::string modelPath);
   void TrainDecisionTree(typename ListSampleType::Pointer trainingListSample,
                          typename TargetListSampleType::Pointer trainingLabeledListSample,
                          std::string modelPath);
@@ -212,7 +220,9 @@ private:
 #include "otbTrainNeuralNetwork.txx"
 #include "otbTrainNormalBayes.txx"
 #include "otbTrainRandomForests.txx"
-#include "otbTrainSVM.txx"
+// OpenCV SVM implementation is buggy with linear kernel
+// Users should use the libSVM implementation instead.
+//#include "otbTrainSVM.txx"
 #endif
 #ifdef OTB_USE_LIBSVM
 #include "otbTrainLibSVM.txx"
diff --git a/Modules/Applications/AppClassification/include/otbLearningApplicationBase.txx b/Modules/Applications/AppClassification/include/otbLearningApplicationBase.txx
index a545538656..c9dec87b73 100644
--- a/Modules/Applications/AppClassification/include/otbLearningApplicationBase.txx
+++ b/Modules/Applications/AppClassification/include/otbLearningApplicationBase.txx
@@ -47,7 +47,9 @@ LearningApplicationBase<TInputValue,TOutputValue>
 #endif
 
 #ifdef OTB_USE_OPENCV
-  InitSVMParams();
+  // OpenCV SVM implementation is buggy with linear kernel
+  // Users should use the libSVM implementation instead.
+  // InitSVMParams();
   if (!m_RegressionFlag)
     {
     InitBoostParams();  // Regression not supported
@@ -105,14 +107,16 @@ LearningApplicationBase<TInputValue,TOutputValue>
     otbAppLogFATAL("Module LIBSVM is not installed. You should consider turning OTB_USE_LIBSVM on during cmake configuration.");
     #endif
     }
-  else if (modelName == "svm")
-    {
-	#ifdef OTB_USE_OPENCV
-    TrainSVM(trainingListSample, trainingLabeledListSample, modelPath);
-    #else
-    otbAppLogFATAL("Module OPENCV is not installed. You should consider turning OTB_USE_OPENCV on during cmake configuration.");
-    #endif
-    }
+  // OpenCV SVM implementation is buggy with linear kernel
+  // Users should use the libSVM implementation instead.
+  // else if (modelName == "svm")
+  //  {
+	//  #ifdef OTB_USE_OPENCV
+  //   TrainSVM(trainingListSample, trainingLabeledListSample, modelPath);
+  //  #else
+  //   otbAppLogFATAL("Module OPENCV is not installed. You should consider turning OTB_USE_OPENCV on during cmake configuration.");
+  //  #endif
+  //  }
   else if (modelName == "boost")
     {
 	#ifdef OTB_USE_OPENCV
diff --git a/Modules/Applications/AppClassification/test/CMakeLists.txt b/Modules/Applications/AppClassification/test/CMakeLists.txt
index c516236cf1..161714af9f 100644
--- a/Modules/Applications/AppClassification/test/CMakeLists.txt
+++ b/Modules/Applications/AppClassification/test/CMakeLists.txt
@@ -78,7 +78,7 @@ set(knn_output_format ".knn")
 
 # Training algorithms parameters
 set(libsvm_parameters "-classifier.libsvm.opt" "true" "-classifier.libsvm.prob" "true")
-set(svm_parameters "-classifier.svm.opt" "true")
+#set(svm_parameters "-classifier.svm.opt" "true")
 set(boost_parameters "")
 set(dt_parameters "")
 set(gbt_parameters "")
@@ -101,7 +101,8 @@ if(OTB_USE_LIBSVM)
   list(APPEND classifierList "LIBSVM")
 endif()
 if(OTB_USE_OPENCV)
-  list(APPEND classifierList "SVM" "BOOST" "DT" "GBT" "ANN" "BAYES" "RF" "KNN")
+  #list(APPEND classifierList "SVM" "BOOST" "DT" "GBT" "ANN" "BAYES" "RF" "KNN")
+  list(APPEND classifierList "BOOST" "DT" "GBT" "ANN" "BAYES" "RF" "KNN")
 endif()
 set(classifier_with_confmap "LIBSVM" "BOOST" "KNN" "ANN" "RF")
 
diff --git a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h
index 569ab32142..c976d666b1 100644
--- a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h
@@ -28,6 +28,14 @@ class CvSVM;
 
 namespace otb
 {
+/** 
+* \brief OpenCV implementation of SVM algorithm.
+* 
+* This machine learning model uses the OpenCV implementation of the
+* SVM algorithm. Since this implementation is buggy in the linear
+* case, we recommend users to use the LibSVM implementation instead,
+* through the otb::LibSVMMachineLearningModel.
+*/ 
 template <class TInputValue, class TTargetValue>
 class ITK_EXPORT SVMMachineLearningModel
   : public MachineLearningModel <TInputValue, TTargetValue>
-- 
GitLab