diff --git a/include/DimensionalityReductionModelFactory.txx b/include/DimensionalityReductionModelFactory.txx index 240d68ad7136e85d004c200134ab4d823f24f7f6..5195605a894a19da3ddfebe8724e6e004ad2a2e5 100644 --- a/include/DimensionalityReductionModelFactory.txx +++ b/include/DimensionalityReductionModelFactory.txx @@ -48,6 +48,12 @@ using SOM2DModelFactory = SOMModelFactory<TInputValue, TTargetValue, 2> ; template <class TInputValue, class TTargetValue> using SOM3DModelFactory = SOMModelFactory<TInputValue, TTargetValue, 3> ; +template <class TInputValue, class TTargetValue> +using SOM4DModelFactory = SOMModelFactory<TInputValue, TTargetValue, 4> ; + +template <class TInputValue, class TTargetValue> +using SOM5DModelFactory = SOMModelFactory<TInputValue, TTargetValue, 5> ; + template <class TInputValue, class TOutputValue> typename DimensionalityReductionModel<TInputValue,TOutputValue>::Pointer DimensionalityReductionModelFactory<TInputValue,TOutputValue> @@ -104,9 +110,10 @@ DimensionalityReductionModelFactory<TInputValue,TOutputValue> - - RegisterFactory(SOM3DModelFactory<TInputValue,TOutputValue>::New()); RegisterFactory(SOM2DModelFactory<TInputValue,TOutputValue>::New()); + RegisterFactory(SOM3DModelFactory<TInputValue,TOutputValue>::New()); + RegisterFactory(SOM4DModelFactory<TInputValue,TOutputValue>::New()); + RegisterFactory(SOM5DModelFactory<TInputValue,TOutputValue>::New()); #ifdef OTB_USE_SHARK RegisterFactory(PCAModelFactory<TInputValue,TOutputValue>::New()); @@ -142,6 +149,23 @@ DimensionalityReductionModelFactory<TInputValue,TOutputValue> { // SOM + + SOM5DModelFactory<TInputValue,TOutputValue> *som5dFactory = + dynamic_cast<SOM5DModelFactory<TInputValue,TOutputValue> *>(*itFac); + if (som5dFactory) + { + itk::ObjectFactoryBase::UnRegisterFactory(som5dFactory); + continue; + } + + SOM4DModelFactory<TInputValue,TOutputValue> *som4dFactory = + dynamic_cast<SOM4DModelFactory<TInputValue,TOutputValue> *>(*itFac); + if (som4dFactory) + { + itk::ObjectFactoryBase::UnRegisterFactory(som4dFactory); + continue; + } + SOM3DModelFactory<TInputValue,TOutputValue> *som3dFactory = dynamic_cast<SOM3DModelFactory<TInputValue,TOutputValue> *>(*itFac); if (som3dFactory) diff --git a/include/SOMModel.txx b/include/SOMModel.txx index 983e5f62a6a92d2e4894e9eb2fad29927a2320e2..d6c9f02c45cdcdd6a3f3d22b43ea5ef62bce3062 100644 --- a/include/SOMModel.txx +++ b/include/SOMModel.txx @@ -54,6 +54,7 @@ void SOMModel<TInputValue, MapDimension>::Train() } + template <class TInputValue, unsigned int MapDimension> bool SOMModel<TInputValue, MapDimension>::CanReadFile(const std::string & filename) { @@ -75,11 +76,27 @@ bool SOMModel<TInputValue, MapDimension>::CanWriteFile(const std::string & filen return true; } +template<typename T> +std::ostream& binary_write(std::ostream& stream, const T& value){ + return stream.write(reinterpret_cast<const char*>(&value), sizeof(T)); +} + + +std::ostream& binary_write_string(std::ofstream& stream, const std::string& value){ + return stream.write(value.c_str(), value.length()); +} + +template<typename T> +std::istream & binary_read(std::istream& stream, T& value){ + return stream.read(reinterpret_cast<char*>(&value), sizeof(T)); +} + + + template <class TInputValue, unsigned int MapDimension> void SOMModel<TInputValue, MapDimension>::Save(const std::string & filename, const std::string & name) { - std::cout << m_SOMMap->GetNumberOfComponentsPerPixel() << std::endl; - + //Ecriture auto kwl = m_SOMMap->GetImageKeywordlist(); kwl.AddKey("MachineLearningModelType", "SOM"+std::to_string(MapDimension)); @@ -92,22 +109,21 @@ void SOMModel<TInputValue, MapDimension>::Save(const std::string & filename, con // test text itk::ImageRegionConstIterator<MapType> inputIterator(m_SOMMap,m_SOMMap->GetLargestPossibleRegion()); - std::ofstream ofs(filename+"2"); - ofs << "SOM" << std::endl; - ofs << MapDimension << std::endl; + inputIterator.GoToBegin(); + std::ofstream ofs(filename+"2", std::ios::binary); + binary_write_string(ofs,"som"); + binary_write(ofs,static_cast<int>(MapDimension)); SizeType size = m_SOMMap->GetLargestPossibleRegion().GetSize() ; - //ofs << m_SOMMap->GetLargestPossibleRegion().GetSize() << std::endl; for (size_t i=0;i<MapDimension;i++){ - ofs << size[i] << " " ; + binary_write(ofs,size[i]); } - ofs << std::endl; - ofs << inputIterator.Get().GetNumberOfElements() << std::endl;; + + binary_write(ofs,inputIterator.Get().GetNumberOfElements()); while(!inputIterator.IsAtEnd()){ InputSampleType vect = inputIterator.Get(); for (size_t i=0;i<vect.GetNumberOfElements();i++){ - ofs << vect[i] << " " ; + binary_write(ofs,vect[i]); } - ++inputIterator; } ofs.close(); @@ -117,113 +133,58 @@ void SOMModel<TInputValue, MapDimension>::Save(const std::string & filename, con template <class TInputValue, unsigned int MapDimension> void SOMModel<TInputValue, MapDimension>::Load(const std::string & filename, const std::string & name) { - /* - auto reader = otb::ImageFileReader<MapType>::New(); - reader->SetFileName(filename); - reader->Update(); - if (reader->GetOutput()->GetImageKeywordlist().GetMetadataByKey("MachineLearningModelType") != "SOM"+std::to_string(MapDimension)){ - itkExceptionMacro(<< "Error opening " << filename.c_str() ); - } - m_SOMMap = reader->GetOutput(); - */ - // test text - - + std::ifstream ifs(filename+"2", std::ios::binary); + /** Read the model key (should be som) */ + char s[]=" "; + for (int i=0; i<3; i++){ + binary_read(ifs,s[i]); + } + std::string modelType(s); + /** Read the dimension of the map (should be equal to MapDimension) */ - std::ifstream ifs(filename+"2"); - std::string model_type_str; - std::string dimension_str; - std::string size_str; - std::string number_of_elements_str; + int dimension; + binary_read(ifs,dimension); - std::getline(ifs,model_type_str); - std::getline(ifs,dimension_str); - if (model_type_str+dimension_str != "SOM"+std::to_string(MapDimension)){ + if (modelType != "som" || dimension != MapDimension){ itkExceptionMacro(<< "Error opening " << filename.c_str() ); } - std::cout << "bug-1?" << std::endl; SizeType size; - itk::Point<double, MapDimension> origin; - SpacingType spacing; itk::Index< MapDimension > index; for (int i=0 ; i<MapDimension; i++) { - std::getline(ifs,size_str , ' '); - size[i] = stof(size_str); - origin[i] = 0; - spacing[i]=0; + binary_read(ifs,size[i]); index[i]=0; } + unsigned int numberOfElements; + binary_read(ifs,numberOfElements); - std::getline(ifs,number_of_elements_str); - std::getline(ifs,number_of_elements_str); - std::cout << "bug0?" << number_of_elements_str << std::endl; - auto number_of_elements = stof(number_of_elements_str); - - //typedef itk::Image< unsigned char, 3 > ImageType; - //typename MapType::Pointer image = MapType::New(); m_SOMMap = MapType::New(); typename MapType::RegionType region; region.SetSize( size ); - m_SOMMap->SetNumberOfComponentsPerPixel(number_of_elements); + m_SOMMap->SetNumberOfComponentsPerPixel(numberOfElements); region.SetIndex( index ); m_SOMMap->SetRegions( region ); m_SOMMap->Allocate(); - std::cout << m_SOMMap << std::endl; -/* - - std::cout << "bug1?" << number_of_elements << std::endl; - itk::ImageRegion<MapDimension> outputRegion; - - - std::cout << "bugoriggin?" << origin << std::endl; - m_SOMMap->SetNumberOfComponentsPerPixel(number_of_elements); - outputRegion.SetIndex(index); - std::cout << "setindex?" << index << std::endl; - outputRegion.SetSize(size); - std::cout << origin << size << std::endl; - m_SOMMap->SetLargestPossibleRegion(outputRegion); - std::cout << "setRegion" << origin << std::endl; - - m_SOMMap->Allocate(); - std::cout << "bug2?" << std::endl; - - */ itk::ImageRegionIterator<MapType> outputIterator(m_SOMMap,region); - + outputIterator.GoToBegin(); std::string value; - size_t j=0; while(!outputIterator.IsAtEnd()){ - std::cout << j << std::endl; - std::getline(ifs,value, ' '); - itk::VariableLengthVector<float> vect(number_of_elements); - for (int i=0 ; i<number_of_elements; i++) + InputSampleType vect(numberOfElements); + for (int i=0 ; i<numberOfElements; i++) { - std::getline(ifs,value , ' '); - //std::cout << value << " "; - std::cout << stof(value) << " "; - vect[i]=std::stof(value); + binary_read(ifs,vect[i]); } - std::cout << vect << std::endl; outputIterator.Set(vect); ++outputIterator; - j++; - std::cout << j << "end" << std::endl; - //std::cout << value << std::endl; - //std::string line; - //std::getline(ifs, line); } - std::cout << j << std::endl; + ifs.close(); - std::cout << "model type " << model_type_str << std::endl; - std::cout << "dimension " << dimension_str << std::endl; - std::cout << "size " << size_str << std::endl; } @@ -236,8 +197,6 @@ SOMModel<TInputValue, MapDimension>::DoPredict(const InputSampleType & value) co target.SetSize(dimension); auto winner =m_SOMMap->GetWinner(value); - // std::cout << winner << std::endl; - for (int i=0; i< dimension ;i++) { target[i] = winner.GetElement(i); } diff --git a/include/cbLearningApplicationBaseDR.h b/include/cbLearningApplicationBaseDR.h index f78dc01e272b4a136e964e42767f39a6e3a48f7c..328373b24f9b1ae99bb002d787298dc779160786 100644 --- a/include/cbLearningApplicationBaseDR.h +++ b/include/cbLearningApplicationBaseDR.h @@ -86,12 +86,19 @@ public: typedef typename ModelType::InputListSampleType ListSampleType; // Dimensionality reduction models + + typedef SOMMap<itk::VariableLengthVector<TInputValue>,itk::Statistics::EuclideanDistanceMetric<itk::VariableLengthVector<TInputValue>>, 2> Map2DType; + typedef otb::SOMModel<InputValueType, 2> SOM2DModelType; typedef SOMMap<itk::VariableLengthVector<TInputValue>,itk::Statistics::EuclideanDistanceMetric<itk::VariableLengthVector<TInputValue>>, 3> Map3DType; typedef otb::SOMModel<InputValueType, 3> SOM3DModelType; - typedef SOMMap<itk::VariableLengthVector<TInputValue>,itk::Statistics::EuclideanDistanceMetric<itk::VariableLengthVector<TInputValue>>, 2> Map2DType; - typedef otb::SOMModel<InputValueType, 2> SOM2DModelType; + typedef SOMMap<itk::VariableLengthVector<TInputValue>,itk::Statistics::EuclideanDistanceMetric<itk::VariableLengthVector<TInputValue>>, 4> Map4DType; + typedef otb::SOMModel<InputValueType, 4> SOM4DModelType; + + typedef SOMMap<itk::VariableLengthVector<TInputValue>,itk::Statistics::EuclideanDistanceMetric<itk::VariableLengthVector<TInputValue>>, 5> Map5DType; + typedef otb::SOMModel<InputValueType, 5> SOM5DModelType; + #ifdef OTB_USE_SHARK typedef shark::Autoencoder< shark::TanhNeuron, shark::LinearNeuron> AutoencoderType; @@ -134,6 +141,7 @@ private: void TrainPCA(typename ListSampleType::Pointer trainingListSample, std::string modelPath); template <class somchoice> void TrainSOM(typename ListSampleType::Pointer trainingListSample, std::string modelPath); + void BeforeTrainSOM(typename ListSampleType::Pointer trainingListSample, std::string modelPath); #endif //@} }; diff --git a/include/cbLearningApplicationBaseDR.txx b/include/cbLearningApplicationBaseDR.txx index 12f8d69d9cf5acdb0e93c1348c51bc1f73cf96a9..916d7d6f8247b85300593999687ce9a219173d90 100644 --- a/include/cbLearningApplicationBaseDR.txx +++ b/include/cbLearningApplicationBaseDR.txx @@ -44,9 +44,10 @@ cbLearningApplicationBaseDR<TInputValue,TOutputValue> { AddDocTag(Tags::Learning); - // main choice parameter that will contain all machine learning options + // main choice parameter that will contain all dimensionality reduction options AddParameter(ParameterType_Choice, "model", "moddel to use for the training"); SetParameterDescription("model", "Choice of the dimensionality reduction model to use for the training."); + InitSOMParams(); #ifdef OTB_USE_SHARK @@ -60,32 +61,7 @@ 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> @@ -95,20 +71,15 @@ cbLearningApplicationBaseDR<TInputValue,TOutputValue> std::string modelPath) { - // get the name of the chosen machine learning model - const std::string modelName = GetParameterString("model"); - // call specific train function + // get the name of the chosen machine learning model + const std::string modelName = GetParameterString("model"); + // call specific train function if(modelName == "som") - { - TrainSOM<SOM2DModelType >(trainingListSample,modelPath); - } - - if(modelName == "som3d") - { - TrainSOM<SOM3DModelType >(trainingListSample,modelPath); - } - + { + BeforeTrainSOM(trainingListSample,modelPath); + } + if(modelName == "autoencoder") { #ifdef OTB_USE_SHARK diff --git a/include/cbTrainSOM.txx b/include/cbTrainSOM.txx index 10d62fb80b30e009ec9aab478de162da485c3e5f..539504b92b71490cc25f10732e2f7d6a1eeba488 100644 --- a/include/cbTrainSOM.txx +++ b/include/cbTrainSOM.txx @@ -24,6 +24,20 @@ cbLearningApplicationBaseDR<TInputValue,TOutputValue> "This group of parameters allows setting SOM parameters. " ); + AddChoice("model.som4d", "OTB SOM"); + SetParameterDescription("model.som4d", + "This group of parameters allows setting SOM parameters. " + ); + + AddChoice("model.som5d", "OTB SOM"); + SetParameterDescription("model.som5d", + "This group of parameters allows setting SOM parameters. " + ); + + + AddParameter(ParameterType_Int, "model.som.dim","Dimension of the map"); + SetParameterDescription("model.som.dim","Dimension of the SOM map."); + AddParameter(ParameterType_StringList , "model.som.s", "Size"); SetParameterDescription("model.som.s", "Size of the SOM map"); MandatoryOff("model.som.s"); @@ -63,7 +77,7 @@ cbLearningApplicationBaseDR<TInputValue,TOutputValue> AddParameter(ParameterType_Float, "model.som.iv", "InitialValue"); SetParameterDescription("model.som.iv", "Maximum initial neuron weight"); MandatoryOff("model.som.iv"); - ; + SetDefaultParameterInt("model.som.sx", 32); SetDefaultParameterInt("model.som.sy", 32); SetDefaultParameterInt("model.som.nx", 10); @@ -76,6 +90,41 @@ cbLearningApplicationBaseDR<TInputValue,TOutputValue> } +template <class TInputValue, class TOutputValue> +void +cbLearningApplicationBaseDR<TInputValue,TOutputValue> +::BeforeTrainSOM(typename ListSampleType::Pointer trainingListSample, + std::string modelPath) +{ + int SomDim = GetParameterInt("model.som.dim"); + std::cout << SomDim << std::endl; + + if(SomDim == 2) + { + TrainSOM<SOM2DModelType >(trainingListSample,modelPath); + } + + if(SomDim == 3) + { + TrainSOM<SOM3DModelType >(trainingListSample,modelPath); + } + + if(SomDim == 4) + { + TrainSOM<SOM4DModelType >(trainingListSample,modelPath); + } + + if(SomDim == 5) + { + TrainSOM<SOM5DModelType >(trainingListSample,modelPath); + } + if(SomDim > 5 || SomDim < 2) + { + std::cerr << "invalid dimension" << std::endl; + } +} + + template <class TInputValue, class TOutputValue> template <typename somchoice> void cbLearningApplicationBaseDR<TInputValue,TOutputValue>