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,®ularizer); + + 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