Commit 2f6c48cd authored by Cédric Traizet's avatar Cédric Traizet

app training working for autoencoder and tied autoencoder using the autoencodermodel class

parent dfc3280c
......@@ -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
}
......
......@@ -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"));
}
};
......
#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
#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
#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
/*=========================================================================
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
#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
/*=========================================================================
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
#ifndef cbTrainAutoencoder_txx
#define cbTrainAutoencoder_txx
#include "cbLearningApplicationBaseDR.h"
namespace otb
{
namespace Wrapper