From 2f6c48cdf8d36fcff9295c51910d176d737c356d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Traizet?= <traizetc@cesbio.cnes.fr>
Date: Tue, 9 May 2017 17:09:45 +0200
Subject: [PATCH] app training working for autoencoder and tied autoencoder
 using the autoencodermodel class

---
 app/cbDimensionalityReduction.cxx        |   7 +-
 app/cbDimensionalityReductionTrainer.cxx |  66 +++++++++--
 include/AutoencoderModel.h               |  52 ++++++--
 include/AutoencoderModel.h.gch           | Bin 0 -> 8399 bytes
 include/AutoencoderModel.txx             |  83 ++++++++++++-
 include/AutoencoderModelFactory.h        |  50 ++++++++
 include/AutoencoderModelFactory.txx      |  64 ++++++++++
 include/cbLearningApplicationBaseDR.h    | 144 +++++++++++++++++++++++
 include/cbLearningApplicationBaseDR.txx  | 122 +++++++++++++++++++
 include/cbTrainAutoencoder.txx           |  65 ++++++++++
 include/encode_filter.h                  |   2 +-
 include/encode_filter.txx                |   9 +-
 otb-module.cmake                         |   1 +
 13 files changed, 635 insertions(+), 30 deletions(-)
 create mode 100644 include/AutoencoderModel.h.gch
 create mode 100644 include/AutoencoderModelFactory.h
 create mode 100644 include/AutoencoderModelFactory.txx
 create mode 100644 include/cbLearningApplicationBaseDR.h
 create mode 100644 include/cbLearningApplicationBaseDR.txx
 create mode 100644 include/cbTrainAutoencoder.txx

diff --git a/app/cbDimensionalityReduction.cxx b/app/cbDimensionalityReduction.cxx
index a539b66c13..b195d053ba 100644
--- a/app/cbDimensionalityReduction.cxx
+++ b/app/cbDimensionalityReduction.cxx
@@ -11,7 +11,6 @@
 #include <shark/Models/Normalizer.h>
 #include "encode_filter.h"
 
-#include "dummy_filter.h"
 #include "otbMultiChannelExtractROI.h"
 
 namespace otb
@@ -77,8 +76,8 @@ private:
 		filter_dim_reduc->SetNormalizerModel(normalizerPath);
 		filter_dim_reduc->SetInput(inImage);
 		
-		//SetParameterOutputImage("out", filter_dim_reduc->GetOutput());
-
+		SetParameterOutputImage("out", filter_dim_reduc->GetOutput());
+/*
 		m_ExtractROIFilter = ExtractROIFilterType::New();
 		m_ExtractROIFilter->SetInput(filter_dim_reduc->GetOutput());
 		for (unsigned int idx = 1; idx <= filter_dim_reduc->GetDimension(); ++idx)
@@ -87,7 +86,7 @@ private:
 		}
 
 		SetParameterOutputImage("out", m_ExtractROIFilter->GetOutput());
-
+*/
 		//SetParameterOutputImage("out", inImage); // copy input image
 
 	}
diff --git a/app/cbDimensionalityReductionTrainer.cxx b/app/cbDimensionalityReductionTrainer.cxx
index 2ceb73d902..9c7cc45142 100644
--- a/app/cbDimensionalityReductionTrainer.cxx
+++ b/app/cbDimensionalityReductionTrainer.cxx
@@ -6,10 +6,10 @@
 
 #include "itkVariableLengthVector.h"
 
-#include "AutoencoderModel.h"
+//#include "AutoencoderModel.h"
 
 #include "otbSharkUtils.h"
-
+#include "otbMachineLearningModel.h"
 //include train function
 #include <shark/ObjectiveFunctions/ErrorFunction.h>
 #include <shark/Algorithms/GradientDescent/Rprop.h>// the RProp optimization algorithm
@@ -25,6 +25,9 @@
 
 #include <shark/Algorithms/Trainers/NormalizeComponentsUnitVariance.h>
 
+#include "otbMachineLearningModelFactory.h"
+
+#include "cbLearningApplicationBaseDR.h"
 
 template<class AutoencoderModel>
 AutoencoderModel trainAutoencoderModel(
@@ -73,27 +76,36 @@ namespace otb
 {
 namespace Wrapper
 {
-class CbDimensionalityReductionTrainer : public otb::Wrapper::Application
+class CbDimensionalityReductionTrainer : public cbLearningApplicationBaseDR<float,float>
 {
 public:
 	typedef CbDimensionalityReductionTrainer Self;
+	typedef cbLearningApplicationBaseDR<float, float> Superclass;
 	typedef itk::SmartPointer<Self> Pointer;
+	typedef itk::SmartPointer<const Self> ConstPointer;
+	
 	itkNewMacro(Self);
 	itkTypeMacro(CbDimensionalityReductionTrainer, otb::Application);
 
 
-	typedef double ValueType;
+	typedef float ValueType;
 	typedef itk::VariableLengthVector<ValueType> InputSampleType;
 	typedef itk::Statistics::ListSample<InputSampleType> ListSampleType;
 	
 	typedef itk::VariableLengthVector<ValueType> MeasurementType;
-
+	  
+	typedef otb::MachineLearningModelFactory<ValueType, ValueType>  ModelFactoryType;
+		
+	typedef shark::Autoencoder< shark::TanhNeuron, shark::LinearNeuron> AutoencoderType;
+	typedef AutoencoderModel<ValueType,AutoencoderType> AutoencoderModelType;
+typedef RandomForestsMachineLearningModel<ValueType,int> rfModelType;
 
 private:
 	void DoInit()
 	{
 		SetName("CbDimensionalityReductionTrainer");
 		SetDescription("Trainer for the dimensionality reduction algorithms used in the cbDimensionalityReduction application.");
+		/*
 		AddParameter(ParameterType_InputVectorData, "train", "Name of the input training vector data");
 		SetParameterDescription("train","The vector data used for training.");
 	
@@ -102,6 +114,22 @@ private:
 		
 		AddParameter(ParameterType_Int, "k","target dimension");
 		SetParameterDescription("k", "Dimension of the output feature vectors");
+*/
+		AddParameter(ParameterType_Group, "io", "Input and output data");
+		SetParameterDescription("io", "This group of parameters allows setting input and output data.");
+
+		AddParameter(ParameterType_InputVectorData, "io.vd", "Input Vector Data");
+		SetParameterDescription("io.vd", "Input geometries used for training (note : all geometries from the layer will be used)");
+
+		AddParameter(ParameterType_OutputFilename, "io.out", "Output model");
+		SetParameterDescription("io.out", "Output file containing the model estimated (.txt format).");
+
+
+		AddParameter(ParameterType_StringList, "feat", "Field names to be calculated."); //
+		SetParameterDescription("feat","List of field names in the input vector data used as features for training."); //
+		
+		Superclass::DoInit();
+
 
 		/*
 		AddParameter(ParameterType_InputFilename, "model", "Dimensionality Reduction model file");
@@ -127,7 +155,7 @@ private:
 
 		std::cout << "Appli !" << std::endl;
 
-		std::string shapefile = GetParameterString("train");
+		std::string shapefile = GetParameterString("io.vd");
 
 		otb::ogr::DataSource::Pointer source = otb::ogr::DataSource::New(shapefile, otb::ogr::DataSource::Modes::Read);
 		otb::ogr::Layer layer = source->GetLayer(0);
@@ -147,6 +175,7 @@ private:
 			}
 			input->PushBack(mv);
 		}
+		/*
 		std::cout << input << std::endl;
 		std::vector<shark::RealVector> features;
 		otb::Shark::ListSampleToSharkVector<ListSampleType>( input, features);
@@ -162,13 +191,12 @@ private:
 	
 		std::cout << "normalizer trained and training set normalized" << std::endl;
 
-		typedef shark::Autoencoder< shark::TanhNeuron, shark::LinearNeuron> AutoencoderType;
 		AutoencoderType net = trainAutoencoderModel<AutoencoderType>(inputSamples,numHidden,iterations,regularisation);
-		std::cout << "autoencoder trained !!" << std::endl;
+		std::cout << "autoencoder trained !!!!" << std::endl;
 
 		// save the model to the file "net.model"
 		std::ofstream ofs("net.model");
-		boost::archive::polymorphic_text_oarchive oa(ofs);
+		shark::TextOutArchive oa(ofs);
 		net.write(oa);
 		ofs.close();
 	
@@ -177,9 +205,27 @@ private:
 		boost::archive::polymorphic_text_oarchive onorm(norm_ofs);
 		normalizer.write(onorm);
 		norm_ofs.close();
-	
+	*/
+
+		std::cout << "Using a Machine learning model" << std::endl;
+		/*
+		AutoencoderModelType::Pointer dimredTrainer = AutoencoderModelType::New();
+		dimredTrainer->SetNumberOfHiddenNeurons(5);
+		dimredTrainer->SetNumberOfIterations(50);
+		dimredTrainer->SetRegularization(0.1);
+		dimredTrainer->SetInputListSample(input);
+		dimredTrainer->Train();
+		dimredTrainer->Save("net.model");
+		std::cout << "ok" << std::endl;
+		*/
+		this->Train(input,GetParameterString("io.out"));
+		
 	}
 
+
+	
+
+
 };
 
 
diff --git a/include/AutoencoderModel.h b/include/AutoencoderModel.h
index f545a72284..603f0dc4d2 100644
--- a/include/AutoencoderModel.h
+++ b/include/AutoencoderModel.h
@@ -1,37 +1,64 @@
 #ifndef AutoencoderModel_h
 #define AutoencoderModel_h
 
-#include "DimensionalityReductionModel.h"
+#include "otbMachineLearningModel.h"
 
 
 namespace otb
 {
 template <class TInputValue, class AutoencoderType>
-class AutoencoderModel: public DimensionalityReductionModel<TInputValue>
+class ITK_EXPORT AutoencoderModel: public  MachineLearningModel<TInputValue,TInputValue>   
 {
 
 public:
 	
 	typedef AutoencoderModel Self;
-	typedef DimensionalityReductionModel<TInputValue> Superclass;
+	typedef MachineLearningModel<TInputValue,TInputValue> Superclass;
 	typedef itk::SmartPointer<Self> Pointer;
 	typedef itk::SmartPointer<const Self> ConstPointer;
 
-	typedef TInputValue InputValueType;
-	typedef itk::VariableLengthVector<InputValueType> InputSampleType;
-	typedef itk::Statistics::ListSample<InputSampleType> InputListSampleType;
+	typedef typename Superclass::InputValueType InputValueType;
+	typedef typename Superclass::InputSampleType InputSampleType;
+	typedef typename Superclass::InputListSampleType InputListSampleType;
+	typedef typename Superclass::TargetValueType TargetValueType;
+	typedef typename Superclass::TargetSampleType TargetSampleType;
+	typedef typename Superclass::TargetListSampleType TargetListSampleType;
+	typedef typename Superclass::ConfidenceValueType ConfidenceValueType;
+	typedef typename Superclass::ConfidenceSampleType ConfidenceSampleType;
+	typedef typename Superclass::ConfidenceListSampleType ConfidenceListSampleType;
 
+	itkNewMacro(Self);
+	itkTypeMacro(AutoencoderModel, MachineLearningModel);
 
-	
-	void Save(const std::string & filename, const std::string & name="")  {};
-	void Load(const std::string & filename, const std::string & name="") {};
 
-	void Train();
-	void Dimensionality_reduction()  {};
+	itkGetMacro(NumberOfHiddenNeurons,unsigned int);
+	itkSetMacro(NumberOfHiddenNeurons,unsigned int);
+
+	itkGetMacro(NumberOfIterations,unsigned int);
+	itkSetMacro(NumberOfIterations,unsigned int);
+
+	itkGetMacro(Regularization,double);
+	itkSetMacro(Regularization,double);
+
+	bool CanReadFile(const std::string & filename);
+	bool CanWriteFile(const std::string & filename);
+
+	void Save(const std::string & filename, const std::string & name="")  ITK_OVERRIDE;
+	void Load(const std::string & filename, const std::string & name="")  ITK_OVERRIDE;
+
+	void Train() ITK_OVERRIDE;
+	//void Dimensionality_reduction()  {}; // Dimensionality reduction is done by DoPredict
+	 
 
 protected:
 	AutoencoderModel(){};	
-	
+private:
+	virtual TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE;
+
+	AutoencoderType m_net;
+	unsigned int m_NumberOfHiddenNeurons;
+	unsigned int m_NumberOfIterations;
+	double m_Regularization;
 };
 } // end namespace otb
 
@@ -42,3 +69,4 @@ protected:
 
 
 #endif
+
diff --git a/include/AutoencoderModel.h.gch b/include/AutoencoderModel.h.gch
new file mode 100644
index 0000000000000000000000000000000000000000..298f5cae3a31fa80eb0653035130a574619c25e6
GIT binary patch
literal 8399
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
V3j+Hd4CvAkZD^qOM*6$Z=>J&7Iwb%A

literal 0
HcmV?d00001

diff --git a/include/AutoencoderModel.txx b/include/AutoencoderModel.txx
index 9a51269360..50fc9940f9 100644
--- a/include/AutoencoderModel.txx
+++ b/include/AutoencoderModel.txx
@@ -1,20 +1,101 @@
+
 #ifndef AutoencoderModel_txx
 #define AutoencoderModel_txx
 
+#include <fstream>
+#include <shark/Data/Dataset.h>
+#include "otbSharkUtils.h"
+//include train function
+#include <shark/ObjectiveFunctions/ErrorFunction.h>
+#include <shark/Algorithms/GradientDescent/Rprop.h>// the RProp optimization algorithm
+#include <shark/ObjectiveFunctions/Loss/SquaredLoss.h> // squared loss used for regression
+#include <shark/ObjectiveFunctions/Regularizer.h> //L2 regulariziation
 
-#include "AutoencoderModel.h"
 namespace otb
 {
 
 template <class TInputValue, class AutoencoderType>
 void AutoencoderModel<TInputValue,AutoencoderType>::Train()
 {
+	
+	std::vector<shark::RealVector> features;
+	
+	Shark::ListSampleToSharkVector(this->GetInputListSample(), features);
+	
+	shark::Data<shark::RealVector> inputSamples = shark::createDataFromRange( features );
+		
+	std::size_t inputs = dataDimension(inputSamples);
+	m_net.setStructure(inputs, m_NumberOfHiddenNeurons);
+	initRandomUniform(m_net,-0.1*std::sqrt(1.0/inputs),0.1*std::sqrt(1.0/inputs));
+	
+	shark::LabeledData<shark::RealVector,shark::RealVector> trainSet(inputSamples,inputSamples);//labels identical to inputs
+	shark::SquaredLoss<shark::RealVector> loss;
+	shark::ErrorFunction error(trainSet, &m_net, &loss);
+	shark::TwoNormRegularizer regularizer(error.numberOfVariables());
+	error.setRegularizer(m_Regularization,&regularizer);
+
+	shark::IRpropPlusFull optimizer;
+	error.init();
+	optimizer.init(error);
+	std::cout<<"Optimizing model: "+m_net.name()<<std::endl;
+	for(std::size_t i = 0; i != m_NumberOfIterations; ++i){
+		optimizer.step(error);
+		std::cout<<i<<" "<<optimizer.solution().value<<std::endl;
+	}
+	//std::cout<<optimizer.solution().value<<std::endl;
+	m_net.setParameterVector(optimizer.solution().point);
+}
+
+
+template <class TInputValue, class AutoencoderType>
+bool AutoencoderModel<TInputValue,AutoencoderType>::CanReadFile(const std::string & filename)
+{
+	try
+	{
+		this->Load(filename);
+		m_net.name();
+	}
+	catch(...)
+	{
+	return false;
+	}
+	return true;
+}
 
+
+template <class TInputValue, class AutoencoderType>
+bool AutoencoderModel<TInputValue,AutoencoderType>::CanWriteFile(const std::string & filename)
+{
+	return true;
 }
 
+template <class TInputValue, class AutoencoderType>
+void AutoencoderModel<TInputValue,AutoencoderType>::Save(const std::string & filename, const std::string & name)
+{
+	std::ofstream ofs(filename);
+	boost::archive::polymorphic_text_oarchive oa(ofs);
+	m_net.write(oa);
+	ofs.close();
+}
 
+template <class TInputValue, class AutoencoderType>
+void AutoencoderModel<TInputValue,AutoencoderType>::Load(const std::string & filename, const std::string & name)
+{
+	std::ifstream ifs(filename);
+	boost::archive::polymorphic_text_iarchive ia(ifs);
+	m_net.read(ia);
+	ifs.close();
+	m_NumberOfHiddenNeurons = m_net.numberOfHiddenNeurons();
+}
 
 
+template <class TInputValue, class AutoencoderType>
+typename AutoencoderModel<TInputValue,AutoencoderType>::TargetSampleType
+AutoencoderModel<TInputValue,AutoencoderType>::DoPredict(const InputSampleType & value, ConfidenceValueType *quality) const
+{
+	TargetSampleType target;
+	return target;
+}
 
 } // namespace otb
 #endif
diff --git a/include/AutoencoderModelFactory.h b/include/AutoencoderModelFactory.h
new file mode 100644
index 0000000000..5bead33b9b
--- /dev/null
+++ b/include/AutoencoderModelFactory.h
@@ -0,0 +1,50 @@
+#ifndef AutoencoderModelFactory_h
+#define AutoencoderModelFactory_h
+
+
+#include "itkObjectFactoryBase.h"
+
+namespace otb
+{
+	
+template <class TInputValue, class TTargetValue>
+class ITK_EXPORT AutoencoderModelFactory : public itk::ObjectFactoryBase
+{
+public:
+  /** Standard class typedefs. */
+  typedef AutoencoderModelFactory             Self;
+  typedef itk::ObjectFactoryBase        Superclass;
+  typedef itk::SmartPointer<Self>       Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+
+  /** Class methods used to interface with the registered factories. */
+  const char* GetITKSourceVersion(void) const ITK_OVERRIDE;
+  const char* GetDescription(void) const ITK_OVERRIDE;
+
+  /** Method for class instantiation. */
+  itkFactorylessNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(AutoencoderModelFactory, itk::ObjectFactoryBase);
+
+  /** Register one factory of this type  */
+  static void RegisterOneFactory(void)
+  {
+    Pointer RFFactory = AutoencoderModelFactory::New();
+    itk::ObjectFactoryBase::RegisterFactory(RFFactory);
+  }
+
+protected:
+  AutoencoderModelFactory();
+  ~AutoencoderModelFactory() ITK_OVERRIDE;
+
+private:
+  AutoencoderModelFactory(const Self &); //purposely not implemented
+  void operator =(const Self&); //purposely not implemented
+
+};
+} //namespace otb
+
+#endif
+
+
diff --git a/include/AutoencoderModelFactory.txx b/include/AutoencoderModelFactory.txx
new file mode 100644
index 0000000000..272e29bc10
--- /dev/null
+++ b/include/AutoencoderModelFactory.txx
@@ -0,0 +1,64 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+#ifndef AutoencoderModelFactory_txx
+#define AutoencoderModelFactory_txx
+
+
+#include "AutoencoderModelFactory.h"
+
+#include "itkCreateObjectFunction.h"
+#include "AutoencoderModel.h"
+#include "itkVersion.h"
+
+namespace otb
+{
+template <class TInputValue, class TOutputValue>
+AutoencoderModelFactory<TInputValue,TOutputValue>::AutoencoderModelFactory()
+{
+
+  std::string classOverride = std::string("otbMachineLearningModel");
+  std::string subclass = std::string("AutoencoderModel");
+
+  this->RegisterOverride(classOverride.c_str(),
+                         subclass.c_str(),
+                         "Shark RF ML Model",
+                         1,
+                      //   itk::CreateObjectFunction<AutoencoderModel<TInputValue,TOutputValue> >::New());
+						itk::CreateObjectFunction<AutoencoderModel<TInputValue,shark::Autoencoder< shark::TanhNeuron, shark::LinearNeuron> > >::New());
+}
+
+template <class TInputValue, class TOutputValue>
+AutoencoderModelFactory<TInputValue,TOutputValue>::~AutoencoderModelFactory()
+{
+}
+
+template <class TInputValue, class TOutputValue>
+const char* AutoencoderModelFactory<TInputValue,TOutputValue>::GetITKSourceVersion(void) const
+{
+  return ITK_SOURCE_VERSION;
+}
+
+template <class TInputValue, class TOutputValue>
+const char* AutoencoderModelFactory<TInputValue,TOutputValue>::GetDescription() const
+{
+  return "Autoencoder model factory";
+}
+
+} // end namespace otb
+
+#endif
diff --git a/include/cbLearningApplicationBaseDR.h b/include/cbLearningApplicationBaseDR.h
new file mode 100644
index 0000000000..fe42e2d875
--- /dev/null
+++ b/include/cbLearningApplicationBaseDR.h
@@ -0,0 +1,144 @@
+#ifndef cbLearningApplicationBaseDR_h
+#define cbLearningApplicationBaseDR_h
+
+#include "otbConfigure.h"
+
+#include "otbWrapperApplication.h"
+
+#include <iostream>
+
+// ListSample
+#include "itkListSample.h"
+#include "itkVariableLengthVector.h"
+
+//Estimator
+#include "otbMachineLearningModelFactory.h"
+
+#ifdef OTB_USE_SHARK
+#include "AutoencoderModel.h"
+#endif
+
+namespace otb
+{
+namespace Wrapper
+{
+
+/** \class LearningApplicationBase
+ *  \brief LearningApplicationBase is the base class for application that
+ *         use machine learning model.
+ *
+ * This base class offers a DoInit() method to initialize all the parameters
+ * related to machine learning models. They will all be in the choice parameter
+ * named "classifier". The class also offers generic Train() and Classify()
+ * methods. The classes derived from LearningApplicationBase only need these
+ * 3 methods to handle the machine learning model.
+ *
+ * There are multiple machine learning models in OTB, some imported
+ * from OpenCV and one imported from LibSVM. They all have
+ * different parameters. The purpose of this class is to handle the
+ * creation of all parameters related to machine learning models (in
+ * DoInit() ), and to dispatch the calls to specific train functions
+ * in function Train().
+ *
+ * This class is templated over scalar types for input and output values.
+ * Typically, the input value type will be either float of double. The choice
+ * of an output value type depends on the learning mode. This base class
+ * supports both classification and regression modes. For classification
+ * (enabled by default), the output value type corresponds to a class
+ * identifier so integer types suit well. For regression, the output value
+ * should not be an integer type, but rather a floating point type. In addition,
+ * an application deriving this base class for regression should initialize
+ * the m_RegressionFlag to true in their constructor.
+ *
+ * \sa TrainImagesClassifier
+ * \sa TrainRegression
+ *
+ * \ingroup OTBAppClassification
+ */
+template <class TInputValue, class TOutputValue>
+class cbLearningApplicationBaseDR: public Application
+{
+public:
+	/** Standard class typedefs. */
+	typedef cbLearningApplicationBaseDR Self;
+	typedef Application             Superclass;
+	typedef itk::SmartPointer<Self> Pointer;
+	typedef itk::SmartPointer<const Self> ConstPointer;
+
+	/** Standard macro */
+	itkTypeMacro(cbLearningApplicationBaseDR, otb::Application)
+
+	typedef TInputValue                             InputValueType;
+	typedef TOutputValue                            OutputValueType;
+
+	typedef otb::VectorImage<InputValueType>        SampleImageType;
+	typedef typename SampleImageType::PixelType     PixelType;
+
+	  // Machine Learning models
+	typedef otb::MachineLearningModelFactory<
+				InputValueType, OutputValueType>             ModelFactoryType;
+	typedef typename ModelFactoryType::MachineLearningModelTypePointer ModelPointerType;
+	typedef typename ModelFactoryType::MachineLearningModelType        ModelType;
+	  
+	typedef typename ModelType::InputSampleType     SampleType;
+	typedef typename ModelType::InputListSampleType ListSampleType;
+	  
+
+#ifdef OTB_USE_SHARK
+	typedef shark::Autoencoder< shark::TanhNeuron, shark::LinearNeuron> AutoencoderType;
+	typedef otb::AutoencoderModel<InputValueType, AutoencoderType> AutoencoderModelType;
+	
+	typedef shark::TiedAutoencoder< shark::TanhNeuron, shark::LinearNeuron> TiedAutoencoderType;
+	typedef otb::AutoencoderModel<InputValueType, TiedAutoencoderType> TiedAutoencoderModelType;
+#endif
+  
+protected:
+  cbLearningApplicationBaseDR();
+
+  ~cbLearningApplicationBaseDR() ITK_OVERRIDE;
+
+  /** Generic method to train and save the machine learning model. This method
+   * uses specific train methods depending on the chosen model.*/
+  void Train(typename ListSampleType::Pointer trainingListSample,
+             std::string modelPath);
+
+  /** Generic method to load a model file and use it to classify a sample list*/
+  void Reduce(typename ListSampleType::Pointer validationListSample,
+                std::string modelPath);
+
+  /** Init method that creates all the parameters for machine learning models */
+  void DoInit();
+
+private:
+
+  /** Specific Init and Train methods for each machine learning model */
+  //@{
+
+#ifdef OTB_USE_SHARK
+  void InitAutoencoderParams();
+  template <class autoencoderchoice>
+  void TrainAutoencoder(typename ListSampleType::Pointer trainingListSample, std::string modelPath){
+ // typename AutoencoderModelType::Pointer dimredTrainer = AutoencoderModelType::New();
+  typename autoencoderchoice::Pointer dimredTrainer = autoencoderchoice::New();
+		dimredTrainer->SetNumberOfHiddenNeurons(GetParameterInt("model.autoencoder.nbneuron"));
+		dimredTrainer->SetNumberOfIterations(GetParameterInt("model.autoencoder.nbiter"));
+		dimredTrainer->SetRegularization(GetParameterFloat("model.autoencoder.normalizer"));
+		dimredTrainer->SetInputListSample(trainingListSample);
+		dimredTrainer->Train();
+		dimredTrainer->Save(modelPath);
+}; // !!!!!!!!!!!!!!!!! How to declare this method body in the .txx ? (double template...) 
+#endif
+  //@}
+};
+
+}
+}
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "cbLearningApplicationBaseDR.txx"
+#ifdef OTB_USE_SHARK
+#include "cbTrainAutoencoder.txx"
+#endif
+#endif
+
+#endif
diff --git a/include/cbLearningApplicationBaseDR.txx b/include/cbLearningApplicationBaseDR.txx
new file mode 100644
index 0000000000..344b6eccfc
--- /dev/null
+++ b/include/cbLearningApplicationBaseDR.txx
@@ -0,0 +1,122 @@
+/*=========================================================================
+ 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.
+
+ =========================================================================*/
+#ifndef cbLearningApplicationBaseDR_txx
+#define cbLearningApplicationBaseDR_txx
+
+#include "cbLearningApplicationBaseDR.h"
+
+namespace otb
+{
+namespace Wrapper
+{
+
+template <class TInputValue, class TOutputValue>
+cbLearningApplicationBaseDR<TInputValue,TOutputValue>
+::cbLearningApplicationBaseDR() 
+{
+}
+
+template <class TInputValue, class TOutputValue>
+cbLearningApplicationBaseDR<TInputValue,TOutputValue>
+::~cbLearningApplicationBaseDR()
+{
+  ModelFactoryType::CleanFactories();
+}
+
+template <class TInputValue, class TOutputValue>
+void
+cbLearningApplicationBaseDR<TInputValue,TOutputValue>
+::DoInit()
+{
+  AddDocTag(Tags::Learning);
+
+  // main choice parameter that will contain all machine learning options
+  AddParameter(ParameterType_Choice, "model", "moddel to use for the training");
+  SetParameterDescription("model", "Choice of the dimensionality reduction model to use for the training.");
+
+
+#ifdef OTB_USE_SHARK
+  InitAutoencoderParams();
+#endif
+  
+}
+
+template <class TInputValue, class TOutputValue>
+void
+cbLearningApplicationBaseDR<TInputValue,TOutputValue>
+::Reduce(typename ListSampleType::Pointer validationListSample,std::string modelPath)
+{/*
+  // Setup fake reporter
+  RGBAPixelConverter<int,int>::Pointer dummyFilter =
+    RGBAPixelConverter<int,int>::New();
+  dummyFilter->SetProgress(0.0f);
+  this->AddProcess(dummyFilter,"Classify...");
+  dummyFilter->InvokeEvent(itk::StartEvent());
+
+  // load a machine learning model from file and predict the input sample list
+  ModelPointerType model = ModelFactoryType::CreateMachineLearningModel(modelPath,
+                                                                        ModelFactoryType::ReadMode);
+
+  if (model.IsNull())
+    {
+    otbAppLogFATAL(<< "Error when loading model " << modelPath);
+    }
+
+  model->Load(modelPath);
+  model->SetRegressionMode(this->m_RegressionFlag);
+  model->SetInputListSample(validationListSample);
+  model->SetTargetListSample(predictedList);
+  model->PredictAll();
+
+  // update reporter
+  dummyFilter->UpdateProgress(1.0f);
+  dummyFilter->InvokeEvent(itk::EndEvent());*/
+}
+
+template <class TInputValue, class TOutputValue>
+void
+cbLearningApplicationBaseDR<TInputValue,TOutputValue>
+::Train(typename ListSampleType::Pointer trainingListSample,
+        std::string modelPath)
+{
+ 
+  // get the name of the chosen machine learning model
+  const std::string modelName = GetParameterString("model");
+  // call specific train function
+
+  if(modelName == "autoencoder")
+    {
+    #ifdef OTB_USE_SHARK
+    TrainAutoencoder<AutoencoderModelType>(trainingListSample,modelPath);
+    #else
+    otbAppLogFATAL("Module SharkLearning is not installed. You should consider turning OTB_USE_SHARK on during cmake configuration.");
+    #endif
+    }
+  if(modelName == "tiedautoencoder")
+    {
+    #ifdef OTB_USE_SHARK
+    TrainAutoencoder<TiedAutoencoderModelType>(trainingListSample,modelPath);
+    #else
+    otbAppLogFATAL("Module SharkLearning is not installed. You should consider turning OTB_USE_SHARK on during cmake configuration.");
+    #endif
+    }
+}
+
+}
+}
+
+#endif
diff --git a/include/cbTrainAutoencoder.txx b/include/cbTrainAutoencoder.txx
new file mode 100644
index 0000000000..f28bad3297
--- /dev/null
+++ b/include/cbTrainAutoencoder.txx
@@ -0,0 +1,65 @@
+
+#ifndef cbTrainAutoencoder_txx
+#define cbTrainAutoencoder_txx
+
+#include "cbLearningApplicationBaseDR.h"
+
+namespace otb
+{
+namespace Wrapper
+{
+
+template <class TInputValue, class TOutputValue>
+void
+cbLearningApplicationBaseDR<TInputValue,TOutputValue>
+::InitAutoencoderParams()
+{
+
+
+  AddChoice("model.tiedautoencoder", "Shark Tied Autoencoder");
+  AddChoice("model.autoencoder", "Shark Autoencoder");
+  SetParameterDescription("model.autoencoder",
+                          "This group of parameters allows setting Shark autoencoder parameters. "
+                          );
+  //Number Of Iterations
+  AddParameter(ParameterType_Int, "model.autoencoder.nbiter",
+               "Maximum number of iterations during training");
+  SetParameterInt("model.autoencoder.nbiter",100, false);
+  SetParameterDescription(
+    "model.autoencoder.nbiter",
+    "The maximum number of iterations used during training.");
+  
+  
+   //Number Of Hidden Neurons
+  AddParameter(ParameterType_Int, "model.autoencoder.nbneuron",
+               "Number of neurons in the hidden layer");
+  SetParameterInt("model.autoencoder.nbneuron",10, false);
+  SetParameterDescription(
+    "model.autoencoder.nbneuron",
+    "The number of neurons in the hidden layer.");
+  
+  //normalization
+  AddParameter(ParameterType_Float, "model.autoencoder.normalizer", "Strength of the normalization");
+  SetParameterFloat("model.autoencoder.normalizer",0, false);
+  SetParameterDescription("model.autoencoder.normalizer", 
+                         "Strength of the L2 normalization used during training");
+}
+/*
+template <class TInputValue, class TOutputValue>
+void cbLearningApplicationBaseDR<TInputValue,TOutputValue>
+::template < autoencoderchoice> TrainAutoencoder(typename ListSampleType::Pointer trainingListSample,std::string modelPath)
+{
+ // typename AutoencoderModelType::Pointer dimredTrainer = AutoencoderModelType::New();
+  autoencoderchoice::Pointer dimredTrainer = autoencoderchoice::New();
+		dimredTrainer->SetNumberOfHiddenNeurons(GetParameterInt("model.autoencoder.nbneuron"));
+		dimredTrainer->SetNumberOfIterations(GetParameterInt("model.autoencoder.nbiter"));
+		dimredTrainer->SetRegularization(GetParameterFloat("model.autoencoder.normalizer"));
+		dimredTrainer->SetInputListSample(trainingListSample);
+		dimredTrainer->Train();
+		dimredTrainer->Save(modelPath);
+}
+*/
+} //end namespace wrapper
+} //end namespace otb
+
+#endif
diff --git a/include/encode_filter.h b/include/encode_filter.h
index 6b5e361fb3..cd8f523505 100644
--- a/include/encode_filter.h
+++ b/include/encode_filter.h
@@ -34,7 +34,7 @@ class ITK_EXPORT EncodeFilter:public itk::ImageToImageFilter< TImage, TImage >
 		NormalizerModel GetNormalizerModel();
  		
 	/** Does the real work. */
-
+		virtual void GenerateOutputInformation();
 		virtual void BeforeThreadedGenerateData();
 	  	void ThreadedGenerateData(const typename TImage::RegionType &outputRegionForThread, unsigned int threadId) ITK_OVERRIDE;
 	 
diff --git a/include/encode_filter.txx b/include/encode_filter.txx
index 8e7b334a9a..a96b048f33 100644
--- a/include/encode_filter.txx
+++ b/include/encode_filter.txx
@@ -101,7 +101,12 @@ this->SetNumberOfThreads(1);
 #endif
 }
 
-
+template< class TImage, class AutoencoderModel, class NormalizerModel>
+void EncodeFilter<TImage, AutoencoderModel, NormalizerModel>::GenerateOutputInformation()
+{
+  Superclass::GenerateOutputInformation();
+    this->GetOutput()->SetNumberOfComponentsPerPixel( m_hidden_neuron );
+}
 
 template< class TImage, class AutoencoderModel, class NormalizerModel>
 void EncodeFilter<TImage, AutoencoderModel, NormalizerModel>::ThreadedGenerateData(const typename TImage::RegionType &outputRegionForThread, unsigned int threadId)
@@ -153,7 +158,7 @@ void EncodeFilter<TImage, AutoencoderModel, NormalizerModel>::ThreadedGenerateDa
 		++imageIteratorOut;
 		++vect_it;
 	}
-	
+		
 }
 	 
 
diff --git a/otb-module.cmake b/otb-module.cmake
index d1bd695426..8b1eb2c05c 100644
--- a/otb-module.cmake
+++ b/otb-module.cmake
@@ -7,6 +7,7 @@ otb_module(CbDimensionalityReduction
 		OTBShark	
 		OTBBoost
 		OTBSupervised
+		OTBAppClassification
 	DESCRIPTION 
 		"${DOCUMENTATION}"
 )
-- 
GitLab