OTB  9.0.0
Orfeo Toolbox
otbNeuralNetworkMachineLearningModel.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2022 Centre National d'Etudes Spatiales (CNES)
3  *
4  * This file is part of Orfeo Toolbox
5  *
6  * https://www.orfeo-toolbox.org/
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef otbNeuralNetworkMachineLearningModel_hxx
22 #define otbNeuralNetworkMachineLearningModel_hxx
23 
24 #include <fstream>
26 #include "itkMacro.h" // itkExceptionMacro
27 
28 namespace otb
29 {
30 
31 template <class TInputValue, class TOutputValue>
33  :
34  m_ANNModel(cv::ml::ANN_MLP::create()),
35  m_TrainMethod(CvANN_MLP_TrainParams::RPROP),
36  m_ActivateFunction(CvANN_MLP::SIGMOID_SYM),
37  m_Alpha(1.),
38  m_Beta(1.),
39  m_BackPropDWScale(0.1),
40  m_BackPropMomentScale(0.1),
41  m_RegPropDW0(0.1),
42  m_RegPropDWMin(FLT_EPSILON),
43  m_TermCriteriaType(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS),
44  m_MaxIter(1000),
45  m_Epsilon(0.01)
46 {
47  this->m_ConfidenceIndex = true;
48  this->m_IsRegressionSupported = true;
49 }
50 
52 template <class TInputValue, class TOutputValue>
54 {
55  const unsigned int nbLayers = layers.size();
56  if (nbLayers < 3)
57  itkExceptionMacro(<< "Number of layers in the Neural Network must be >= 3")
58 
59  m_LayerSizes = layers;
60 }
61 
67 template <class TInputValue, class TOutputValue>
69 {
70  unsigned int nbSamples = 0;
71  if (labels != nullptr)
72  {
73  nbSamples = labels->Size();
74  }
76 
77  // Check for valid listSample
78  if (nbSamples > 0)
79  {
80  // Build an iterator
81  typename TargetListSampleType::ConstIterator labelSampleIt = labels->Begin();
82 
83  TargetValueType classLabel;
84  for (; labelSampleIt != labels->End(); ++labelSampleIt)
85  {
86  // Retrieve labelSample
87  typename TargetListSampleType::MeasurementVectorType labelSample = labelSampleIt.GetMeasurementVector();
88  classLabel = labelSample[0];
89  if (m_MapOfLabels.count(classLabel) == 0)
90  {
91  m_MapOfLabels[classLabel] = -1;
92  }
93  }
94 
95  unsigned int nbClasses = m_MapOfLabels.size();
96 
97  m_MatrixOfLabels = cv::Mat(1,nbClasses, CV_32FC1);
98  unsigned int itLabel = 0;
99  for (auto& kv : m_MapOfLabels)
100  {
101  classLabel = kv.first;
102  kv.second = itLabel;
103  m_MatrixOfLabels.at<float>(0,itLabel) = classLabel;
104  ++itLabel;
105  }
106 
107  // Sample index
108  unsigned int sampleIdx = 0;
109  labelSampleIt = labels->Begin();
110  output.create(nbSamples, nbClasses, CV_32FC1);
111  output.setTo(-m_Beta);
112  // Fill the cv matrix
113  for (; labelSampleIt != labels->End(); ++labelSampleIt, ++sampleIdx)
114  {
115  // Retrieve labelSample
116  typename TargetListSampleType::MeasurementVectorType labelSample = labelSampleIt.GetMeasurementVector();
117  classLabel = labelSample[0];
118  unsigned int indexLabel = m_MapOfLabels[classLabel];
119  output.at<float>(sampleIdx, indexLabel) = m_Beta;
120  }
121  }
122 }
123 
124 template <class TInputValue, class TOutputValue>
126 {
127  // Create the neural network
128  const unsigned int nbLayers = m_LayerSizes.size();
129 
130  if (nbLayers == 0)
131  itkExceptionMacro(<< "Number of layers in the Neural Network must be >= 3")
132 
133  cv::Mat layers = cv::Mat(nbLayers, 1, CV_32SC1);
134  for (unsigned int i = 0; i < nbLayers; i++)
135  {
136  layers.row(i) = m_LayerSizes[i];
137  }
138 
139  m_ANNModel->setLayerSizes(layers);
140  m_ANNModel->setActivationFunction(m_ActivateFunction, m_Alpha, m_Beta);
141 }
142 
143 
144 template <class TInputValue, class TOutputValue>
146 {
147  // convert listsample to opencv matrix
148  cv::Mat samples;
149  otb::ListSampleToMat<InputListSampleType>(this->GetInputListSample(), samples);
150  this->CreateNetwork();
151  int flags = (this->m_RegressionMode ? 0 : cv::ml::ANN_MLP::NO_OUTPUT_SCALE);
152  m_ANNModel->setTrainMethod(m_TrainMethod);
153  m_ANNModel->setBackpropMomentumScale(m_BackPropMomentScale);
154  m_ANNModel->setBackpropWeightScale(m_BackPropDWScale);
155  m_ANNModel->setRpropDW0(m_RegPropDW0);
156  // m_ANNModel->setRpropDWMax( );
157  m_ANNModel->setRpropDWMin(m_RegPropDWMin);
158  // m_ANNModel->setRpropDWMinus( );
159  // m_ANNModel->setRpropDWPlus( );
160  m_ANNModel->setTermCriteria(cv::TermCriteria(m_TermCriteriaType, m_MaxIter, m_Epsilon));
161  m_ANNModel->train(cv::ml::TrainData::create(samples, cv::ml::ROW_SAMPLE, labels), flags);
162 }
163 
165 template <class TInputValue, class TOutputValue>
167 {
168  // Transform the targets into a matrix of labels
169  cv::Mat matOutputANN;
170  if (this->m_RegressionMode)
171  {
172  // MODE REGRESSION
173  otb::ListSampleToMat<TargetListSampleType>(this->GetTargetListSample(), matOutputANN);
174  }
175  else
176  {
177  // MODE CLASSIFICATION : store the map between internal labels and output labels
178  LabelsToMat(this->GetTargetListSample(), matOutputANN);
179  }
180  this->SetupNetworkAndTrain(matOutputANN);
181 }
183 
184 template <class TInputValue, class TOutputValue>
187  ProbaSampleType* proba) const
188 {
189  TargetSampleType target;
190  // convert listsample to Mat
191  cv::Mat sample;
192 
193  otb::SampleToMat<InputSampleType>(input, sample);
194 
195  cv::Mat response; //(1, 1, CV_32FC1);
196  m_ANNModel->predict(sample, response);
197 
198  float currentResponse = 0;
199  float maxResponse = response.at<float>(0, 0);
200 
201  if (this->m_RegressionMode)
202  {
203  // MODE REGRESSION : only output first response
204  target[0] = maxResponse;
205  return target;
206  }
207 
208  // MODE CLASSIFICATION : find the highest response
209  float secondResponse = -1e10;
210 
211  target[0] = m_MatrixOfLabels.at<TOutputValue>(0);
212  unsigned int nbClasses = m_MatrixOfLabels.size[1];
213 
214  for (unsigned itLabel = 1; itLabel < nbClasses; ++itLabel)
215  {
216  currentResponse = response.at<float>(0, itLabel);
217  if (currentResponse > maxResponse)
218  {
219  secondResponse = maxResponse;
220 
221  maxResponse = currentResponse;
222  target[0] = m_MatrixOfLabels.at<TOutputValue>(itLabel);
223  }
224  else
225  {
226  if (currentResponse > secondResponse)
227  {
228  secondResponse = currentResponse;
229  }
230  }
231  }
232 
233  if (quality != nullptr)
234  {
235  (*quality) = static_cast<ConfidenceValueType>(maxResponse) - static_cast<ConfidenceValueType>(secondResponse);
236  }
237  if (proba != nullptr && !this->m_ProbaIndex)
238  itkExceptionMacro("Probability per class not available for this classifier !");
239 
240  return target;
241 }
242 
243 template <class TInputValue, class TOutputValue>
244 void NeuralNetworkMachineLearningModel<TInputValue, TOutputValue>::Save(const std::string& filename, const std::string& name)
245 {
246  cv::FileStorage fs(filename, cv::FileStorage::WRITE);
247  fs << (name.empty() ? m_ANNModel->getDefaultName() : cv::String(name)) << "{";
248  m_ANNModel->write(fs);
249 
250  if (!m_MatrixOfLabels.empty())
251  {
252  fs << "class_labels" << m_MatrixOfLabels;
253  }
254  fs << "}";
255  fs.release();
256 }
257 
258 template <class TInputValue, class TOutputValue>
259 void NeuralNetworkMachineLearningModel<TInputValue, TOutputValue>::Load(const std::string& filename, const std::string& name)
260 {
261  cv::FileStorage fs(filename, cv::FileStorage::READ);
262  cv::FileNode model_node(name.empty() ? fs.getFirstTopLevelNode() : fs[name]);
263  m_ANNModel->read(model_node);
264  model_node["class_labels"] >> m_MatrixOfLabels;
265  fs.release();
266 }
267 
268 template <class TInputValue, class TOutputValue>
270 {
271  std::ifstream ifs;
272  ifs.open(file);
273 
274  if (!ifs)
275  {
276  std::cerr << "Could not read file " << file << std::endl;
277  return false;
278  }
279 
280  while (!ifs.eof())
281  {
282  std::string line;
283  std::getline(ifs, line);
284 
285  if (line.find(CV_TYPE_NAME_ML_ANN_MLP) != std::string::npos || line.find(m_ANNModel->getDefaultName()) != std::string::npos)
286  {
287  return true;
288  }
289  }
290  ifs.close();
291  return false;
292 }
293 
294 template <class TInputValue, class TOutputValue>
296 {
297  return false;
298 }
299 
300 template <class TInputValue, class TOutputValue>
301 void NeuralNetworkMachineLearningModel<TInputValue, TOutputValue>::PrintSelf(std::ostream& os, itk::Indent indent) const
302 {
303  // Call superclass implementation
304  Superclass::PrintSelf(os, indent);
305 }
306 
307 } // end namespace otb
308 
309 #endif
otb::NeuralNetworkMachineLearningModel::DoPredict
TargetSampleType DoPredict(const InputSampleType &input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override
Definition: otbNeuralNetworkMachineLearningModel.hxx:186
otb::NeuralNetworkMachineLearningModel::LabelsToMat
void LabelsToMat(const TargetListSampleType *listSample, cv::Mat &output)
Definition: otbNeuralNetworkMachineLearningModel.hxx:68
otb::NeuralNetworkMachineLearningModel::SetupNetworkAndTrain
void SetupNetworkAndTrain(cv::Mat &labels)
Definition: otbNeuralNetworkMachineLearningModel.hxx:145
otb::NeuralNetworkMachineLearningModel::SetLayerSizes
void SetLayerSizes(const std::vector< unsigned int > layers)
Definition: otbNeuralNetworkMachineLearningModel.hxx:53
CV_TYPE_NAME_ML_ANN_MLP
#define CV_TYPE_NAME_ML_ANN_MLP
Definition: otbOpenCVUtils.h:53
CvANN_MLP_TrainParams
#define CvANN_MLP_TrainParams
Definition: otbOpenCVUtils.h:58
otb::NeuralNetworkMachineLearningModel::ProbaSampleType
Superclass::ProbaSampleType ProbaSampleType
Definition: otbNeuralNetworkMachineLearningModel.h:50
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::NeuralNetworkMachineLearningModel::ConfidenceValueType
Superclass::ConfidenceValueType ConfidenceValueType
Definition: otbNeuralNetworkMachineLearningModel.h:49
otb::NeuralNetworkMachineLearningModel::TargetValueType
Superclass::TargetValueType TargetValueType
Definition: otbNeuralNetworkMachineLearningModel.h:46
otb::MachineLearningModel< TInputValue, TTargetValue >::m_IsRegressionSupported
bool m_IsRegressionSupported
Definition: otbMachineLearningModel.h:225
otbNeuralNetworkMachineLearningModel.h
otb::NeuralNetworkMachineLearningModel::InputSampleType
Superclass::InputSampleType InputSampleType
Definition: otbNeuralNetworkMachineLearningModel.h:44
otb::NeuralNetworkMachineLearningModel::CanReadFile
bool CanReadFile(const std::string &) override
Definition: otbNeuralNetworkMachineLearningModel.hxx:269
otb::NeuralNetworkMachineLearningModel::PrintSelf
void PrintSelf(std::ostream &os, itk::Indent indent) const override
Definition: otbNeuralNetworkMachineLearningModel.hxx:301
CvANN_MLP
#define CvANN_MLP
Definition: otbOpenCVUtils.h:59
otb::NeuralNetworkMachineLearningModel::CreateNetwork
void CreateNetwork()
Definition: otbNeuralNetworkMachineLearningModel.hxx:125
otb::NeuralNetworkMachineLearningModel::TargetListSampleType
Superclass::TargetListSampleType TargetListSampleType
Definition: otbNeuralNetworkMachineLearningModel.h:48
otb::NeuralNetworkMachineLearningModel::TargetSampleType
Superclass::TargetSampleType TargetSampleType
Definition: otbNeuralNetworkMachineLearningModel.h:47
otb::NeuralNetworkMachineLearningModel::Train
void Train() override
Definition: otbNeuralNetworkMachineLearningModel.hxx:166
otb::NeuralNetworkMachineLearningModel::NeuralNetworkMachineLearningModel
NeuralNetworkMachineLearningModel()
Definition: otbNeuralNetworkMachineLearningModel.hxx:32
otb::NeuralNetworkMachineLearningModel::CanWriteFile
bool CanWriteFile(const std::string &) override
Definition: otbNeuralNetworkMachineLearningModel.hxx:295
otb::NeuralNetworkMachineLearningModel::Save
void Save(const std::string &filename, const std::string &name="") override
Definition: otbNeuralNetworkMachineLearningModel.hxx:244
otb::MachineLearningModel< TInputValue, TTargetValue >::m_ConfidenceIndex
bool m_ConfidenceIndex
Definition: otbMachineLearningModel.h:228
otb::NeuralNetworkMachineLearningModel::Load
void Load(const std::string &filename, const std::string &name="") override
Definition: otbNeuralNetworkMachineLearningModel.hxx:259