Main Page · Modules · All Classes · Class Hierarchy
MAWeakModel.cpp
1 /*
2  * This file is part of the AiBO+ project
3  *
4  * Copyright (C) 2005-2016 Csaba Kertész (csaba.kertesz@gmail.com)
5  *
6  * AiBO+ is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * AiBO+ is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
19  *
20  */
21 
22 #include "MAWeakModel.hpp"
23 
24 #include "core/MACoreTypes.hpp"
25 
26 #include <MCContainers.hpp>
27 #include <MCLog.hpp>
28 
29 MAWeakModel::MAWeakModel(MAModel& classifier)
30 {
31  AddClassifier(classifier);
32 }
33 
34 
36 {
37 }
38 
39 
40 unsigned int MAWeakModel::GetFeatureCount() const
41 {
42  unsigned int Size = 0;
43 
44  for (unsigned int i = 0; i < Classifiers.size(); ++i)
45  {
46  Size += Classifiers[i]->GetFeatureCount();
47  }
48  return Size;
49 }
50 
51 
52 MC::FloatList& MAWeakModel::GetModelLabels()
53 {
54  return Classifiers[0]->GetModelLabels();
55 }
56 
57 
58 void MAWeakModel::AddClassifier(MAModel& classifier)
59 {
60  Classifiers.push_back(MA::ModelSPtr(&classifier));
61 }
62 
63 
64 MC::FloatList MAWeakModel::Predict(const MC::FloatTable& input_vectors, MC::FloatList& confidences)
65 {
66  if (input_vectors.empty())
67  {
68  MC_WARNING("No data in the input table for classifier prediction.");
69  return MC::FloatList();
70  }
71  // Check if the table is appropriate for training
72  int RowSize = input_vectors[0].size();
73 
74  if (RowSize == 0)
75  {
76  MC_WARNING("No data in the input table for classifier prediction.");
77  return MC::FloatList();
78  }
79  for (unsigned int i = 1; i < input_vectors.size(); ++i)
80  {
81  if ((int)input_vectors[i].size() != RowSize)
82  {
83  MC_WARNING("Row counts are inconsistent in the input table for classifier prediction.");
84  return MC::FloatList();
85  }
86  }
87  if (RowSize != (int)GetFeatureCount())
88  {
89  MC_WARNING("Feature count does not match with the expected (%d != %d).", GetFeatureCount(), RowSize);
90  return MC::FloatList();
91  }
92  MC::FloatList Labels;
93 
94  for (unsigned int i = 0; i < input_vectors.size(); ++i)
95  {
96  Labels.push_back(Predict(input_vectors[i], confidences));
97  }
98  return Labels;
99 }
100 
101 
102 float MAWeakModel::Predict(const MC::FloatList& input_vector, MC::FloatList& confidence)
103 {
104  if (input_vector.empty())
105  {
106  MC_WARNING("No data in the input vector for classifier prediction.");
107  return MCFloatInfinity();
108  }
109  if (input_vector.size() != GetFeatureCount())
110  {
111  MC_WARNING("Feature count does not match with the expected test vector (%d != %d).",
112  GetFeatureCount(), input_vector.size());
113  return MCFloatInfinity();
114  }
115  int StartIndex = 0;
116  MA::FloatFloatSortedMap LabelCounts;
117 
118  for (unsigned int i = 0; i < Classifiers.size(); ++i)
119  {
120  int FeatureCount = Classifiers[i]->GetFeatureCount();
121  MC::FloatList VectorPart(input_vector.begin()+StartIndex, input_vector.begin()+StartIndex+FeatureCount);
122  MC::FloatList Confidence;
123  float Label = Classifiers[i]->Predict(VectorPart, Confidence);
124 
125  if (Confidence.empty())
126  {
127  LabelCounts[Label]++;
128  } else {
129  LabelCounts[Label] += Confidence[0];
130  }
131  StartIndex += FeatureCount;
132  }
133  float MaxAmount = 0;
134  float MaxLabel = LabelCounts.begin()->first;
135  float MaxValue = LabelCounts.begin()->second;
136 
137  for (auto& value : LabelCounts)
138  {
139  MaxAmount += value.second;
140  if (MaxValue < value.second)
141  {
142  MaxLabel = value.first;
143  MaxValue = value.second;
144  }
145  }
146  confidence.push_back(MaxValue / MaxAmount);
147  return MaxLabel;
148 }
149 
150 
151 MC::FloatTable MAWeakModel::Predict(const MC::FloatTable& input_vectors)
152 {
153  if (input_vectors.empty())
154  {
155  MC_WARNING("No data in the input table for classifier prediction.");
156  return MC::FloatTable();
157  }
158  // Check if the table is appropriate for training
159  int RowSize = input_vectors[0].size();
160 
161  if (RowSize == 0)
162  {
163  MC_WARNING("No data in the input table for classifier prediction.");
164  return MC::FloatTable();
165  }
166  for (unsigned int i = 1; i < input_vectors.size(); ++i)
167  {
168  if ((int)input_vectors[i].size() != RowSize)
169  {
170  MC_WARNING("Row counts are inconsistent in the input table for classifier prediction.");
171  return MC::FloatTable();
172  }
173  }
174  if (RowSize != (int)GetFeatureCount())
175  {
176  MC_WARNING("Feature count does not match with the expected (%d != %d).", GetFeatureCount(), RowSize);
177  return MC::FloatTable();
178  }
179  MC::FloatTable LabelTable;
180 
181  for (unsigned int i = 0; i < input_vectors.size(); ++i)
182  {
183  LabelTable.push_back(Predict(input_vectors[i]));
184  }
185  return LabelTable;
186 }
187 
188 
189 MC::FloatList MAWeakModel::Predict(const MC::FloatList& input_vector)
190 {
191  if (input_vector.empty())
192  {
193  MC_WARNING("No data in the input vector for classifier prediction.");
194  return MC::FloatList();
195  }
196  if (input_vector.size() != GetFeatureCount())
197  {
198  MC_WARNING("Feature count does not match with the expected test vector (%d != %d).",
199  GetFeatureCount(), input_vector.size());
200  return MC::FloatList();
201  }
202  MC::FloatList Labels;
203  int StartIndex = 0;
204  MC::FloatList Confidence;
205 
206  for (unsigned int i = 0; i < Classifiers.size(); ++i)
207  {
208  int FeatureCount = Classifiers[i]->GetFeatureCount();
209  MC::FloatList VectorPart(input_vector.begin()+StartIndex, input_vector.begin()+StartIndex+FeatureCount);
210 
211  Labels.push_back(Classifiers[i]->Predict(VectorPart, Confidence));
212  StartIndex += FeatureCount;
213  }
214  return Labels;
215 }
216 
217 
218 MCBinaryData* MAWeakModel::Encode() const
219 {
220  MCBinaryData* FileData = nullptr;
221  MA::BinaryDataSPtrList DataList;
222  int FileSize = (int)Classifiers.size()*4;
223 
224  for (unsigned int i = 0; i < Classifiers.size(); ++i)
225  {
226  DataList.push_back(MC::BinaryDataSPtr(Classifiers[i]->Encode()));
227  FileSize += DataList[i]->GetSize();
228  }
229  FileData = new MCBinaryData(FileSize);
230  for (unsigned int i = 0; i < Classifiers.size(); ++i)
231  {
232  FileData->AddInt32(DataList[i]->GetSize());
233  DataList[i]->ResetPosition();
234  DataList[i]->WriteData(*FileData, DataList[i]->GetSize());
235  }
236  return FileData;
237 }
238 
239 
240 MAWeakModel* MAWeakModel::Decode(const MCBinaryData& data)
241 {
242  MCBinaryData& Data = const_cast<MCBinaryData&>(data);
243  MC::BinaryDataSPtr ReadData(new MCBinaryData);
244  int OldPosition = Data.GetPosition();
245  MAWeakModel* WeakModel = nullptr;
246 
247  Data.SetPosition(0);
248  while (!Data.IsPositionAtEnd())
249  {
250  MAModel* Model = nullptr;
251 
252  ReadData->Allocate(Data.GetInt32());
253  Data.WriteData(*ReadData, ReadData->GetSize());
254  Model = MAModel::Decode(*ReadData);
255  if (Model)
256  {
257  if (!WeakModel)
258  {
259  WeakModel = new MAWeakModel(*Model);
260  continue;
261  }
262  WeakModel->AddClassifier(*Model);
263  }
264  }
265  Data.SetPosition(OldPosition);
266  if (WeakModel && WeakModel->Classifiers.empty())
267  {
268  delete WeakModel;
269  WeakModel = nullptr;
270  }
271  return WeakModel;
272 }
Binary data class.
~MAWeakModel()
Class destructor.
Definition: MAWeakModel.cpp:35
Classifier model based on OpenCV classifiers.
Definition: MAModel.hpp:50
#define MC_WARNING(...)
Warning macro.
Definition: MCLog.hpp:43
MA::OpenCVModelPtrList Classifiers
OpenCV classifiers.
void AddInt32(int32_t new_int, bool reverse_order=false)
Add a 32 bit integer at the current position.
Weak model based on OpenCV classifiers.
Definition: MAWeakModel.hpp:50
bool WriteData(MCBinaryData &target, int capacity=-1)
Write data into a target instance.
void SetPosition(unsigned int position)
Set the cursor position.
float MCFloatInfinity()
Get float infinity.
Definition: MCDefs.cpp:110
int32_t GetInt32(bool reverse_order=false)
Get a 32 bit integer from the current position.
int GetPosition() const
Get the current position in the binary data.
bool IsPositionAtEnd() const
Check if the current position is at the end of the binary data.