GEGELATI

Loading...
Searching...
No Matches
classificationLearningAgent.h
1
38#ifndef CLASSIFICATION_LEARNING_AGENT_H
39#define CLASSIFICATION_LEARNING_AGENT_H
40
41#include <numeric>
42#include <stdexcept>
43#include <type_traits>
44#include <vector>
45
46#include "learn/classificationEvaluationResult.h"
47#include "learn/classificationLearningEnvironment.h"
48#include "learn/evaluationResult.h"
49#include "learn/learningAgent.h"
50#include "learn/parallelLearningAgent.h"
51#include <data/hash.h>
52
53 namespace Learn {
74 template <class BaseLearningAgent = ParallelLearningAgent>
75 class ClassificationLearningAgent : public BaseLearningAgent
76 {
77 static_assert(
78 std::is_convertible<BaseLearningAgent*, LearningAgent*>::value);
79
80 public:
91 ClassificationLearningAgent(
92 ClassificationLearningEnvironment& le,
93 const Instructions::Set& iSet, const LearningParameters& p,
94 const TPG::TPGFactory& factory = TPG::TPGFactory())
95 : BaseLearningAgent(le, iSet, p, factory){};
96
105 virtual std::shared_ptr<EvaluationResult> evaluateJob(
106 TPG::TPGExecutionEngine& tee, const Job& root,
107 uint64_t generationNumber, LearningMode mode,
108 LearningEnvironment& le) const override;
109
137 void decimateWorstRoots(
138 std::multimap<std::shared_ptr<EvaluationResult>,
139 const TPG::TPGVertex*>& results) override;
140 };
141
142 template <class BaseLearningAgent>
143 inline std::shared_ptr<EvaluationResult> ClassificationLearningAgent<
144 BaseLearningAgent>::evaluateJob(TPG::TPGExecutionEngine& tee,
145 const Job& job,
146 uint64_t generationNumber,
147 LearningMode mode,
148 LearningEnvironment& le) const
149 {
150 // Only consider the first root of jobs as we are not in adversarial
151 // mode
152 const TPG::TPGVertex* root = job.getRoot();
153
154 // Skip the root evaluation process if enough evaluations were already
155 // performed. In the evaluation mode only.
156 std::shared_ptr<Learn::EvaluationResult> previousEval;
157 if (mode == LearningMode::TRAINING &&
158 this->isRootEvalSkipped(*root, previousEval)) {
159 return previousEval;
160 }
161
162 // Init results
163 std::vector<double> result(this->learningEnvironment.getNbActions(),
164 0.0);
165 std::vector<size_t> nbEvalPerClass(
166 this->learningEnvironment.getNbActions(), 0);
167
168 // Evaluate nbIteration times
169 for (auto i = 0; i < this->params.nbIterationsPerPolicyEvaluation;
170 i++) {
171 // Compute a Hash
172 Data::Hash<uint64_t> hasher;
173 uint64_t hash = hasher(generationNumber) ^ hasher(i);
174
175 // Reset the learning Environment
176 le.reset(hash, mode);
177
178 uint64_t nbActions = 0;
179 while (!le.isTerminal() &&
180 nbActions < this->params.maxNbActionsPerEval) {
181 // Get the actions
182 std::vector<double> actionsID =
183 tee.executeFromRoot(*root, le.getInitActions()).second;
184 // Do it
185 le.doActions(actionsID);
186 // Count actions
187 nbActions++;
188 }
189
190 // Update results
191 const auto& classificationTable =
192 ((ClassificationLearningEnvironment&)le)
193 .getClassificationTable();
194 // for each class
195 for (uint64_t classIdx = 0; classIdx < classificationTable.size();
196 classIdx++) {
197 uint64_t truePositive =
198 classificationTable.at(classIdx).at(classIdx);
199 uint64_t falseNegative =
200 std::accumulate(classificationTable.at(classIdx).begin(),
201 classificationTable.at(classIdx).end(),
202 (uint64_t)0) -
203 truePositive;
204 uint64_t falsePositive = 0;
205 std::for_each(
206 classificationTable.begin(), classificationTable.end(),
207 [&classIdx, &falsePositive](
208 const std::vector<uint64_t>& classifForClass) {
209 falsePositive += classifForClass.at(classIdx);
210 });
211 falsePositive -= truePositive;
212
213 double recall = (double)truePositive /
214 (double)(truePositive + falseNegative);
215 double precision = (double)truePositive /
216 (double)(truePositive + falsePositive);
217 // If true positive is 0, set score to 0.
218 double fScore = (truePositive != 0) ? 2 * (precision * recall) /
219 (precision + recall)
220 : 0.0;
221 result.at(classIdx) += fScore;
222
223 nbEvalPerClass.at(classIdx) += truePositive + falseNegative;
224 }
225 }
226
227 // Before returning the EvaluationResult, divide the result per class by
228 // the number of iteration
229 const LearningParameters& p = this->params;
230 std::for_each(result.begin(), result.end(), [p](double& val) {
231 val /= (double)p.nbIterationsPerPolicyEvaluation;
232 });
233
234 // Create the EvaluationResult
235 auto evaluationResult = std::shared_ptr<EvaluationResult>(
236 new ClassificationEvaluationResult(result, nbEvalPerClass));
237
238 // Combine it with previous one if any
239 if (previousEval != nullptr) {
240 *evaluationResult += *previousEval;
241 }
242 return evaluationResult;
243 }
244
245 template <class BaseLearningAgent>
246 void ClassificationLearningAgent<BaseLearningAgent>::decimateWorstRoots(
247 std::multimap<std::shared_ptr<EvaluationResult>, const TPG::TPGVertex*>&
248 results)
249 {
250 // Check that results are ClassificationEvaluationResults.
251 // (also throws on empty results)
252 const EvaluationResult* result = results.begin()->first.get();
253 if (typeid(ClassificationEvaluationResult) != typeid(*result)) {
254 throw std::runtime_error(
255 "ClassificationLearningAgent can not decimate worst roots for "
256 "results whose type is not ClassificationEvaluationResult.");
257 }
258
259 // Compute the number of root to keep/delete base on each criterion
260 uint64_t totalNbRoot = this->tpg->getNbRootVertices();
261 uint64_t nbRootsToDelete =
262 (uint64_t)floor(this->params.ratioDeletedRoots * totalNbRoot);
263 uint64_t nbRootsToKeep = (totalNbRoot - nbRootsToDelete);
264
265 // Keep ~half+ of the roots based on their general score on
266 // all class.
267 // and ~half- of the roots on a per class score (none if nbRoots to keep
268 // < 2*nb class)
269 uint64_t nbRootsKeptPerClass =
270 (nbRootsToKeep / this->learningEnvironment.getNbActions()) / 2;
271 uint64_t nbRootsKeptGeneralScore =
272 nbRootsToKeep -
273 this->learningEnvironment.getNbActions() * nbRootsKeptPerClass;
274
275 // Build a list of roots to keep
276 std::vector<const TPG::TPGVertex*> rootsToKeep;
277
278 // Insert roots to keep per class
279 for (uint64_t classIdx = 0;
280 classIdx < this->learningEnvironment.getNbActions(); classIdx++) {
281 // Fill a map with the roots and the score of the specific class as
282 // ID.
283 std::multimap<double, const TPG::TPGVertex*> sortedRoot;
284 std::for_each(
285 results.begin(), results.end(),
286 [&sortedRoot,
287 &classIdx](const std::pair<std::shared_ptr<EvaluationResult>,
288 const TPG::TPGVertex*>& res) {
289 sortedRoot.emplace(
290 ((ClassificationEvaluationResult*)res.first.get())
291 ->getScorePerClass()
292 .at(classIdx),
293 res.second);
294 });
295
296 // Keep the best nbRootsKeptPerClass (or less for reasons explained
297 // in the loop)
298 auto iterator = sortedRoot.rbegin();
299 for (auto i = 0; i < nbRootsKeptPerClass; i++) {
300 // If the root is not already marked to be kept
301 if (std::find(rootsToKeep.begin(), rootsToKeep.end(),
302 iterator->second) == rootsToKeep.end()) {
303 rootsToKeep.push_back(iterator->second);
304 }
305 // Advance the iterator no matter what.
306 // This means that if a root scores well for several classes
307 // it is kept only once anyway, but additional roots will not
308 // be kept for any of the concerned class.
309 iterator++;
310 }
311 }
312
313 // Insert remaining roots to keep
314 auto iterator = results.rbegin();
315 while (rootsToKeep.size() < nbRootsToKeep &&
316 iterator != results.rend()) {
317 // If the root is not already marked to be kept
318 if (std::find(rootsToKeep.begin(), rootsToKeep.end(),
319 iterator->second) == rootsToKeep.end()) {
320 rootsToKeep.push_back(iterator->second);
321 }
322 // Advance the iterator no matter what.
323 iterator++;
324 }
325
326 // Do the removal.
327 // Because of potential root actions, the preserved number of roots
328 // may be higher than the given ratio.
329 auto allRoots = this->tpg->getRootVertices();
330 auto& tpgRef = this->tpg;
331 auto& resultsPerRootRef = this->resultsPerRoot;
332 std::for_each(
333 allRoots.begin(), allRoots.end(),
334 [&rootsToKeep, &tpgRef, &resultsPerRootRef,
335 &results](const TPG::TPGVertex* vert) {
336 // Do not remove actions
337 if (dynamic_cast<const TPG::TPGAction*>(vert) == nullptr &&
338 std::find(rootsToKeep.begin(), rootsToKeep.end(), vert) ==
339 rootsToKeep.end()) {
340 tpgRef->removeVertex(*vert);
341
342 // Keep only results of non-decimated roots.
343 resultsPerRootRef.erase(vert);
344
345 // Update results also
346 std::multimap<std::shared_ptr<EvaluationResult>,
347 const TPG::TPGVertex*>::iterator iter =
348 results.begin();
349 while (iter != results.end()) {
350 if (iter->second == vert) {
351 results.erase(iter);
352 break;
353 }
354 iter++;
355 }
356 }
357 });
358 }
359}; // namespace Learn
360
361#endif
Data::PrimitiveTypeArray2D
DataHandler for 2D arrays of primitive types.
Definition primitiveTypeArray2D.h:69
Instructions::Set
Class for storing a set of Instruction.
Definition set.h:55
Learn::ClassificationEvaluationResult
Specialization of the EvaluationResult class for classification LearningEnvironment.
Definition classificationEvaluationResult.h:53
Learn::ClassificationLearningAgent
LearningAgent specialized for LearningEnvironments representing a classification problem.
Definition classificationLearningAgent.h:76
Learn::ClassificationLearningAgent::decimateWorstRoots
void decimateWorstRoots(std::multimap< std::shared_ptr< EvaluationResult >, const TPG::TPGVertex * > &results) override
Specialization of the decimateWorstRoots method for classification purposes.
Definition classificationLearningAgent.h:246
Learn::ClassificationLearningAgent::evaluateJob
virtual std::shared_ptr< EvaluationResult > evaluateJob(TPG::TPGExecutionEngine &tee, const Job &root, uint64_t generationNumber, LearningMode mode, LearningEnvironment &le) const override
Specialization of the evaluateJob method for classification purposes.
Definition classificationLearningAgent.h:144
Learn::ClassificationLearningAgent::ClassificationLearningAgent
ClassificationLearningAgent(ClassificationLearningEnvironment &le, const Instructions::Set &iSet, const LearningParameters &p, const TPG::TPGFactory &factory=TPG::TPGFactory())
Constructor for LearningAgent.
Definition classificationLearningAgent.h:91
Learn::ClassificationLearningEnvironment
Specialization of the LearningEnvironment class for classification purposes.
Definition classificationLearningEnvironment.h:50
Learn::EvaluationResult
Base class for storing all result of a policy evaluation within a LearningEnvironment.
Definition evaluationResult.h:54
Learn::Job
This class embeds roots for the simulations.
Definition job.h:53
Learn::Job::getRoot
virtual const TPG::TPGVertex * getRoot() const
Getter of the root.
Definition job.cpp:49
Learn::LearningEnvironment
Interface for creating a Learning Environment.
Definition learningEnvironment.h:81
Learn::LearningEnvironment::reset
virtual void reset(size_t seed=0, LearningMode mode=LearningMode::TRAINING, uint16_t iterationNumber=0, uint64_t generationNumber=0)=0
Reset the LearningEnvironment.
Learn::LearningEnvironment::isTerminal
virtual bool isTerminal() const =0
Method for checking if the LearningEnvironment has reached a terminal state.
Learn::LearningEnvironment::getInitActions
const std::vector< uint64_t > & getInitActions() const
Get the vector of initial actions available for this LearningEnvironment.
Definition learningEnvironment.h:171
Learn::LearningEnvironment::doActions
virtual void doActions(std::vector< double > vectActionID)
Execute actions on the LearningEnvironment.
Definition learningEnvironment.cpp:71
TPG::TPGExecutionEngine
Definition tpgExecutionEngine.h:57
TPG::TPGExecutionEngine::executeFromRoot
virtual const std::pair< std::vector< const TPG::TPGVertex * >, std::vector< double > > executeFromRoot(const TPGVertex &root, const std::vector< uint64_t > &initActions={0})
Execute the TPGGraph starting from the given TPGVertex.
Definition tpgExecutionEngine.cpp:153
TPG::TPGFactory
Factory for creating all elements constituting a TPG.
Definition tpgFactory.h:71
TPG::TPGVertex
Abstract class representing the vertices of a TPGGraph.
Definition tpgVertex.h:55
Learn
Definition adversarialEvaluationResult.h:45
Learn::LearningMode
LearningMode
Different modes in which the LearningEnvironment can be reset.
Definition learningEnvironment.h:59
Learn::LearningParameters
Structure for simplifying the transmission of LearningParameters to functions.
Definition learningParameters.h:54