KSquare Utilities
ModelDual.cpp
Go to the documentation of this file.
1 #include "FirstIncludes.h"
2 
3 #include <stdio.h>
4 #include <string>
5 #include <iostream>
6 #include <fstream>
7 #include <math.h>
8 #include <vector>
9 #include <sstream>
10 #include <iomanip>
11 #include <set>
12 #include <vector>
13 #include "MemoryDebug.h"
14 using namespace std;
15 
16 
17 #include "GlobalGoalKeeper.h"
18 #include "KKBaseTypes.h"
19 #include "KKException.h"
20 #include "OSservices.h"
21 #include "RunLog.h"
22 #include "KKStr.h"
23 using namespace KKB;
24 
25 
26 #include "ModelDual.h"
27 #include "Classifier2.h"
28 #include "ClassProb.h"
29 #include "FeatureNumList.h"
30 #include "FeatureVector.h"
31 #include "ModelParamDual.h"
33 #include "TrainingProcess2.h"
34 using namespace KKMLL;
35 
36 
37 
38 
40  Model (),
41  param (NULL),
42  config1 (NULL),
43  config2 (NULL),
44  trainer1 (NULL),
45  trainer2 (NULL),
46  classifier1 (NULL),
47  classifier2 (NULL)
48 {
49 }
50 
51 
52 
53 
55  Model (_factoryFVProducer),
56  param (NULL),
57  config1 (NULL),
58  config2 (NULL),
59  trainer1 (NULL),
60  trainer2 (NULL),
61  classifier1 (NULL),
62  classifier2 (NULL)
63 {
64 }
65 
66 
67 ModelDual::ModelDual (const KKStr& _name,
68  const ModelParamDual& _param, // Create new model from
69  FactoryFVProducerPtr _factoryFVProducer
70  ):
71  Model (_name, _param, _factoryFVProducer),
72  param (NULL),
73  config1 (NULL),
74  config2 (NULL),
75  trainer1 (NULL),
76  trainer2 (NULL),
77  classifier1 (NULL),
78  classifier2 (NULL)
79 {
80  param = dynamic_cast<ModelParamDualPtr> (Model::param);
81 }
82 
83 
84 
85 
86 ModelDual::ModelDual (const ModelDual& _model):
87  Model (_model),
88  param (NULL),
89  config1 (NULL),
90  config2 (NULL),
91  trainer1 (NULL),
92  trainer2 (NULL),
93  classifier1 (NULL),
94  classifier2 (NULL)
95 {
96  param = dynamic_cast<ModelParamDualPtr> (Model::param);
97 }
98 
99 
100 
101 
102 
103 /**
104  * @brief Frees any memory allocated by, and owned by the ModelDual
105  */
107 {
108  // The base class owns param, so we do not delete it.
110  delete config1; config1 = NULL;
111  delete config2; config2 = NULL;
112  delete trainer1; trainer1 = NULL;
113  delete trainer2; trainer2 = NULL;
114  delete classifier1; classifier1 = NULL;
115  delete classifier2; classifier2 = NULL;
116 
117 }
118 
119 
121 {
122  kkint32 memoryConsumedEstimated = Model::MemoryConsumedEstimated ();
123  if (trainer1) memoryConsumedEstimated += trainer1->MemoryConsumedEstimated ();
124  if (trainer2) memoryConsumedEstimated += trainer2->MemoryConsumedEstimated ();
125  if (classifier1) memoryConsumedEstimated += classifier1->MemoryConsumedEstimated ();
126  if (classifier2) memoryConsumedEstimated += classifier2->MemoryConsumedEstimated ();
127  return memoryConsumedEstimated;
128 }
129 
130 
131 
132 
134 {
135  KKStr result = "Dual(" + Name () + ")";
136  if (trainer1)
138  else if (config1)
139  result << " " << config1->ModelTypeStr () + "(" + osGetRootName (config1->FileName ()) + ")";
140 
141  if (trainer2)
143  else if (config1)
144  result << " " << config2->ModelTypeStr () + "(" + osGetRootName (config2->FileName ()) + ")";
145 
146  return result;
147 }
148 
149 
150 
151 ModelDualPtr ModelDual::Duplicate () const
152 {
153  return new ModelDual (*this);
154 }
155 
156 
157 
159 {
160  return param;
161 }
162 
163 
165 {
166  delete config1; config1 = NULL;
167  delete config2; config2 = NULL;
168  delete trainer1; trainer1 = NULL;
169  delete trainer2; trainer2 = NULL;
170  delete classifier1; classifier1 = NULL;
171  delete classifier2; classifier2 = NULL;
172 } /* DeleteExistingClassifiers */
173 
174 
175 
176 
178  bool _alreadyNormalized,
179  bool _takeOwnership, /**< Model will take ownership of these examples */
180  VolConstBool& _cancelFlag,
181  RunLog& _log
182  )
183 {
184  _log.Level (10) << "ModelDual::TrainModel Model[" << param->FileName () << "] _trainExamples->size()[" << _trainExamples->size() << "]" << endl;
185 
186  if (param == NULL)
187  {
188  validModel = false;
189  KKStr errMsg = "ModelDual::TrainModel (param == NULL)";
190  _log.Level (-1) << endl << errMsg << endl << endl;
191  throw KKException (errMsg);
192  }
193 
195 
196  try
197  {
198  Model::TrainModel (_trainExamples, _alreadyNormalized, _takeOwnership, _cancelFlag, _log);
199  }
200  catch (const KKException& e)
201  {
202  validModel = false;
203  KKStr errMsg = "ModelDual::TrainModel ***ERROR*** Exception occurred calling 'Model::TrainModel'.";
204  _log.Level (-1) << endl << errMsg << endl << e.ToString () << endl << endl;
205  throw KKException (errMsg, e);
206  }
207  catch (const exception& e2)
208  {
209  validModel = false;
210  KKStr errMsg = "ModelDual::TrainModel ***ERROR*** Exception occurred calling 'Model::TrainModel'.";
211  _log.Level (-1) << endl << errMsg << endl << e2.what () << endl << endl;
212  throw KKException (errMsg, e2);
213  }
214  catch (...)
215  {
216  validModel = false;
217  KKStr errMsg = "ModelDual::TrainModel ***ERROR*** Exception occurred calling 'Model::TrainModel'.";
218  _log.Level (-1) << endl << errMsg << endl << endl;
219  throw KKException (errMsg);
220  }
221 
222  // 'Model::TrainModel' Will have performed any BitReduction and Feature Encoding
223  // that needed to be done.
224  // Also the data structures 'classes', 'encoder', and 'fileDesc' will have been built.
225  // 'classes' will already be sorted in name order.
226  // The Prediction variables 'probabilities', 'votes', and 'crossClassProbTable' will
227  // have been built.
228 
229  {
230  // Make sure that the configuration files actually exist.
232  {
233  validModel = false;
234  KKStr errMsg = "ModelDual::TrainModel ***ERROR*** Could not find Configuration[" + param->ConfigFileName1 () + "].";
235  _log.Level (-1) << endl << errMsg << endl << endl;
236  throw KKException (errMsg);
237  }
238 
240  {
241  validModel = false;
242  KKStr errMsg = "ModelDual::TrainModel ***ERROR*** Could not find Configuration[" + param->ConfigFileName2 () + "].";
243  _log.Level (-1) << endl << errMsg << endl << endl;
244  throw KKException (errMsg);
245  }
246  }
247 
250  false, // false = Do NOT validate directories.
251  _log
252  );
253  if (!config1->FormatGood ())
254  {
255  validModel = false;
256  KKStr errMsg = "ModelDual::TrainModel ***ERROR*** Configuration[" + param->ConfigFileName1 () + "] is not valid.";
257  _log.Level (-1) << endl << errMsg << endl << endl;
258  throw KKException (errMsg);
259  }
260 
263  false, // false = Do NOT validate directories.
264  _log
265  );
266  if (!config2->FormatGood ())
267  {
268  validModel = false;
269  KKStr errMsg = "ModelDual::TrainModel ***ERROR*** Configuration[" + param->ConfigFileName2 () + "] is not valid.";
270  _log.Level (-1) << endl << errMsg << endl << endl;
271  throw KKException (errMsg);
272  }
273 
274  KKStr statusMsg;
275 
278  (config1,
280  false, /**< false = DON'T take ownership of 'trainExamples'. */
281  true, /**< true = Features are already normalized. */
282  _cancelFlag,
283  _log
284  );
286 
287  if ((!trainer1) || trainer1->Abort ())
288  {
289  validModel = false;
290  KKStr errMsg = "ModelDual::TrainModel ***ERROR*** Error building TrainingProcess for [" + param->ConfigFileName1 () + "].";
291  _log.Level (-1) << endl << errMsg << endl << endl;
292  throw KKException (errMsg);
293  }
294 
297  (config2,
299  false, /**< false = DON'T take ownership of 'trainExamples'. */
300  true, /**< true = Features are already normalized. */
301  _cancelFlag,
302  _log
303  );
305 
306  if ((!trainer2) || trainer2->Abort ())
307  {
308  validModel = false;
309  KKStr errMsg = "ModelDual::TrainModel ***ERROR*** Error building TrainingProcess for [" + param->ConfigFileName1 () + "].";
310  _log.Level (-1) << endl << errMsg << endl << endl;
311  throw KKException (errMsg);
312  }
313 
316 } /* TrainModel */
317 
318 
319 
320 MLClassPtr ModelDual::ReconcilePredictions (MLClassPtr pred1,
321  MLClassPtr pred2,
322  RunLog& log
323  )
324 {
325  if (pred1 == pred2)
326  return pred1;
327 
329  {
330  if (param->OtherClass ())
331  return param->OtherClass ();
332  else
333  return MLClass::CreateNewMLClass ("NoAgreement");
334  }
335 
336  if (!pred1)
337  {
338  if (!pred2)
339  {
340  log.Level (-1) << "ModelDual::ReconcilePredictions ***WARNING*** Classifier[" << param->ConfigFileName1 () << "] nor Classifier[" << param->ConfigFileName2 () << "] return predictions." << endl;
341  return NULL;
342  }
343  else
344  {
345  log.Level (-1) << "ModelDual::ReconcilePredictions ***WARNING*** Classifier[" << param->ConfigFileName1 () << "] did not return a prediction." << endl;
346  return pred2;
347  }
348  }
349  else
350  {
351  if (!pred2)
352  {
353  log.Level (-1) << "ModelDual::ReconcilePredictions ***WARNING*** Classifier[" << param->ConfigFileName2 () << "] did not return a prediction." << endl;
354  return pred1;
355  }
356  }
357 
358  // We need to find the common part of the predictions.
359  KKStr name1 = pred1->Name ();
360  KKStr name2 = pred2->Name ();
361  kkint32 maxLen = Min (name1.Len (), name2.Len ());
362  KKStr commonPart (maxLen + 1);
363 
364  while ((!name1.Empty ()) && (!name2.Empty ()))
365  {
366  KKStr name1Token = name1.ExtractToken2 ("_");
367  KKStr name2Token = name2.ExtractToken2 ("_");
368  if (name1Token == name2Token)
369  {
370  if (!commonPart.Empty ())
371  commonPart.Append ('_');
372  commonPart += name1Token;
373  }
374  else
375  {
376  break;
377  }
378  }
379 
380  if (commonPart.Len () < 1)
381  {
382  if (param->OtherClass ())
383  return param->OtherClass ();
384  else
385  return MLClass::CreateNewMLClass ("NoAgreement");
386  }
387  else
388  {
389  return MLClass::CreateNewMLClass (commonPart);
390  }
391 } /* ReconcilePredictions */
392 
393 
394 
395 
396 void ModelDual::ReconcileProbAndVotes (Classifier2Ptr classifier,
397  MLClassPtr predClass,
398  FeatureVectorPtr encodedExample,
399  double& predClassProb,
400  kkint32& predClassVotes
401  )
402 {
403  const KKStr& name = predClass->Name ();
404 
405  predClassProb = 0.0;
406  predClassVotes = 0;
407 
408  ClassProbListPtr predictions = classifier->ProbabilitiesByClass (encodedExample);
409  ClassProbList::iterator idx;
410  for (idx = predictions->begin (); idx != predictions->end (); ++idx)
411  {
412  ClassProbPtr p = *idx;
414  {
415  predClassProb += p->probability;
416  predClassVotes += (kkint32)(p->votes);
417  }
418  }
419 
420  delete predictions;
421  predictions = NULL;
422 
423  return;
424 } /* ReconcileProbAndVotes */
425 
426 
427 
428 
429 
430 MLClassPtr ModelDual::Predict (FeatureVectorPtr example,
431  RunLog& log
432  )
433 {
434  if ((!classifier1) || (!classifier2))
435  {
436  log.Level (-1) << endl << endl << "ModelDual::Predict ***ERROR*** Both Classifiers are not defined." << endl << endl;
437  return NULL;
438  }
439 
440  bool newExampleCreated = false;
441 
442  MLClassPtr pred1 = NULL;
443  MLClassPtr pred2 = NULL;
444 
445  /**@todo ModelDual::Predict Make sure that the call to the first classifier does not modify the encodedExample. */
446  FeatureVectorPtr encodedExample = PrepExampleForPrediction (example, newExampleCreated);
447  pred1 = classifier1->ClassifyAExample (*encodedExample);
448  pred2 = classifier2->ClassifyAExample (*encodedExample);
449 
450  if (newExampleCreated)
451  {
452  delete encodedExample;
453  encodedExample = NULL;
454  }
455 
456  return ReconcilePredictions (pred1, pred2, log);
457 } /* Predict */
458 
459 
460 
461 
463  MLClassPtr knownClass,
464  MLClassPtr& predClass1,
465  MLClassPtr& predClass2,
466  kkint32& predClass1Votes,
467  kkint32& predClass2Votes,
468  double& probOfKnownClass,
469  double& predClass1Prob,
470  double& predClass2Prob,
471  kkint32& numOfWinners,
472  bool& knownClassOneOfTheWinners,
473  double& breakTie,
474  RunLog& log
475  )
476 {
477  if ((!classifier1) || (!classifier2))
478  {
479  predClass1 = predClass2 = NULL;
480  log.Level (-1) << endl << endl << "ModelDual::Predict ***ERROR*** Both Classifiers are not defined." << endl << endl;
481  return;
482  }
483 
484  MLClassPtr predClass1C1 = NULL;
485  MLClassPtr predClass2C1 = NULL;
486  kkint32 predClass1VotesC1 = 0;
487  kkint32 predClass2VotesC1 = 0;
488  double probOfKnownClassC1 = 0.0;
489  double predClass1ProbC1 = 0.0;
490  double predClass2ProbC1 = 0.0;
491  kkint32 numOfWinnersC1 = 0;
492  bool knownClassOneOfTheWinnersC1 = false;
493  double breakTieC1 = 0.0;
494 
495  MLClassPtr predClass1C2 = NULL;
496  MLClassPtr predClass2C2 = NULL;
497  kkint32 predClass1VotesC2 = 0;
498  kkint32 predClass2VotesC2 = 0;
499  double probOfKnownClassC2 = 0.0;
500  double predClass1ProbC2 = 0.0;
501  double predClass2ProbC2 = 0.0;
502  kkint32 numOfWinnersC2 = 0;
503  bool knownClassOneOfTheWinnersC2 = false;
504  double breakTieC2 = 0.0;
505 
506  bool newExampleCreated = false;
507  FeatureVectorPtr encodedExample = PrepExampleForPrediction (example, newExampleCreated);
508 
509  /**@todo Make sure that 'classifier1->ClassifyAExample' does not modify the feature data. */
510 
511  classifier1->ClassifyAExample (*encodedExample,
512  predClass1C1, predClass2C1,
513  predClass1VotesC1, predClass2VotesC1,
514  probOfKnownClassC1,
515  predClass1ProbC1, predClass2ProbC1,
516  numOfWinnersC1,
517  breakTieC1
518  );
519 
520  classifier2->ClassifyAExample (*encodedExample,
521  predClass1C2, predClass2C2,
522  predClass1VotesC2, predClass2VotesC2,
523  probOfKnownClassC2,
524  predClass1ProbC2, predClass2ProbC2,
525  numOfWinnersC2,
526  breakTieC2
527  );
528 
529  predClass1 = ReconcilePredictions (predClass1C1, predClass1C2, log);
530  predClass2 = ReconcilePredictions (predClass2C1, predClass2C2, log);
531 
532  if (predClass1C1 != predClass1C2)
533  {
535  predClass1,
536  encodedExample,
537  predClass1ProbC1,
538  predClass1VotesC1
539  );
540 
542  predClass1,
543  encodedExample,
544  predClass1ProbC2,
545  predClass1VotesC2
546  );
547  }
548 
549 
550  if (predClass2C1 != predClass2C2)
551  {
553  predClass2,
554  encodedExample,
555  predClass2ProbC1,
556  predClass2VotesC1
557  );
558 
560  predClass2,
561  encodedExample,
562  predClass2ProbC2,
563  predClass2VotesC2
564  );
565  }
566 
567  predClass1Prob = (predClass1ProbC1 + predClass1ProbC2) / 2.0;
568  predClass2Prob = (predClass2ProbC1 + predClass2ProbC2) / 2.0;
569  predClass1Votes = (kkint32)((0.5f + predClass1VotesC1 + predClass1VotesC2) / 2.0f);
570  predClass2Votes = (kkint32)((0.5f + predClass2VotesC1 + predClass2VotesC2) / 2.0f);
571 
572 
573  probOfKnownClass = (probOfKnownClassC1 + probOfKnownClassC2) / 2.0;
574  breakTie = (breakTieC1 + breakTieC2) / 2.0;
575  numOfWinners = (numOfWinnersC1 + numOfWinnersC2) / 2;
576  knownClassOneOfTheWinners = (knownClass == predClass1C1) || (knownClass == predClass1C2);
577 
578  if (newExampleCreated)
579  {
580  delete encodedExample;
581  encodedExample = NULL;
582  }
583 
584  return;
585 } /* Predict */
586 
587 
588 
589 
590 
592  RunLog& log
593  )
594 {
595  if ((!classifier1) || (!classifier2))
596  {
597  log.Level (-1) << endl << endl << "ModelDual::ProbabilitiesByClass ***ERROR*** Both Classifiers are not defined." << endl << endl;
598  return NULL;
599  }
600 
603 
604  if (predictions1 == NULL)
605  return predictions2;
606 
607  else if (predictions2 == NULL)
608  return predictions1;
609 
610  ClassProbList::iterator idx;
611  for (idx = predictions2->begin (); idx != predictions2->end (); ++idx)
612  {
613  ClassProbPtr cp = *idx;
614  predictions1->MergeIn (cp);
615  }
616  delete predictions2;
617  predictions2 = NULL;
618 
619  predictions1->NormalizeToOne ();
620 
621  return predictions1;
622 } /* ProbabilitiesByClass */
623 
624 
625 
626 
627 
629  KKStr& classifier1Desc,
630  KKStr& classifier2Desc,
631  ClassProbListPtr& classifier1Results,
632  ClassProbListPtr& classifier2Results,
633  RunLog& log
634  )
635 {
636  delete classifier1Results; classifier1Results = NULL;
637  delete classifier2Results; classifier2Results = NULL;
638 
639  if ((!classifier1) || (!classifier2))
640  {
641  log.Level (-1) << endl << endl << "ModelDual::ProbabilitiesByClassDual ***ERROR*** Both Classifiers are not defined." << endl << endl;
642  return;
643  }
644 
645  classifier1Desc = trainer1->ModelDescription ();
646  classifier2Desc = trainer2->ModelDescription ();
647 
648  {
649  bool newExampleCreated = false;
650  FeatureVectorPtr encodedExample = PrepExampleForPrediction (example, newExampleCreated);
651  classifier1Results = classifier1->ProbabilitiesByClass (encodedExample);
652  if (newExampleCreated)
653  {
654  delete encodedExample;
655  encodedExample = NULL;
656  }
657  }
658 
659  {
660  bool newExampleCreated = false;
661  FeatureVectorPtr encodedExample = PrepExampleForPrediction (example, newExampleCreated);
662  classifier2Results = classifier2->ProbabilitiesByClass (encodedExample);
663  if (newExampleCreated)
664  {
665  delete encodedExample;
666  encodedExample = NULL;
667  }
668  }
669 
670  return;
671 } /* ProbabilitiesByClass */
672 
673 
674 
675 
677  const MLClassList& _mlClasses,
678  kkint32* _votes,
679  double* _probabilities,
680  RunLog& _log
681  )
682 {
683  kkint32 numClasses = _mlClasses.QueueSize ();
684  for (kkint32 idx = 0; idx < numClasses; idx++)
685  {
686  _probabilities[idx] = 0.0;
687  _votes [idx] = 0;
688  }
689 
690  if ((!classifier1) || (!classifier2))
691  {
692  _log.Level (-1) << endl << "ModelDual::ProbabilitiesByClass ***ERROR*** Both Classifiers are not defined." << endl << endl;
693  return;
694  }
695 
698 
699  if (predictions1 == NULL)
700  {
701  predictions1 = predictions2;
702  predictions2 = NULL;
703  }
704 
705  else if (predictions2 == NULL)
706  {
707  // 'predictions1' already has the total of both.
708  }
709 
710  else
711  {
712  predictions1->AddIn (predictions2);
713  delete predictions2;
714  predictions2 = NULL;
715  }
716 
717  kkuint32 x = 0;
718  predictions1->NormalizeToOne ();
719  MLClassList::const_iterator idx2;
720  for (idx2 = _mlClasses.begin (), x = 0; idx2 != _mlClasses.end (); ++idx2, ++x)
721  {
722  MLClassPtr c =*idx2;
723  ClassProbPtr cp = predictions1->LookUp (c);
724  if (cp)
725  {
726  _votes [x] = (kkint32)(0.5f + cp->votes);
727  _probabilities[x] = cp->probability;
728  }
729  }
730 
731  delete predictions1;
732  predictions1 = NULL;
733 
734  return;
735 } /* ProbabilitiesByClass */
736 
737 
738 
739 
740 
742  const MLClassList& _mlClasses,
743  double* _probabilities,
744  RunLog& _log
745  )
746 {
747  kkint32 numClasses = _mlClasses.QueueSize ();
748  for (kkint32 idx = 0; idx < numClasses; idx++)
749  {
750  _probabilities[idx] = 0.0;
751  }
752 
753  if ((!classifier1) || (!classifier2))
754  {
755  _log.Level (-1) << endl << "ModelDual::ProbabilitiesByClass ***ERROR*** Both Classifiers are not defined." << endl << endl;
756  return;
757  }
758 
761 
762  if (predictions1 == NULL)
763  {
764  predictions1 = predictions2;
765  predictions2 = NULL;
766  }
767 
768  else if (predictions2 == NULL)
769  {
770  // 'predictions1' already has the total of both.
771  }
772 
773  else
774  {
775  predictions1->AddIn (predictions2);
776  delete predictions2;
777  predictions2 = NULL;
778  }
779 
780  kkuint32 x = 0;
781  predictions1->NormalizeToOne ();
782  MLClassList::const_iterator idx2;
783  for (idx2 = _mlClasses.begin (), x = 0; idx2 != _mlClasses.end (); ++idx2, ++x)
784  {
785  MLClassPtr c =*idx2;
786  ClassProbPtr cp = predictions1->LookUp (c);
787  if (cp)
788  _probabilities[x] = cp->probability;
789  }
790 
791  delete predictions1;
792  predictions1 = NULL;
793 
794  return;
795 } /* ProbabilitiesByClass */
796 
797 
798 
799 
801  double** _crossProbTable, /**< two dimension matrix that needs to be classes.QueueSize () squared. */
802  RunLog& _log
803  )
804 {
805  if ((!classifier1) || (!classifier2))
806  {
807  _log.Level (-1) << endl << "ModelDual::RetrieveCrossProbTable ***ERROR*** Both Classifiers are not defined." << endl << endl;
808  return;
809  }
810 
811  kkint32 x = 0, y = 0;
812 
813  kkint32 numClasses = _classes.QueueSize ();
814 
815  double** crossProbTableC1 = new double*[numClasses];
816  double** crossProbTableC2 = new double*[numClasses];
817 
818  for (x = 0; x < numClasses; ++x)
819  {
820  crossProbTableC1[x] = new double[numClasses];
821  crossProbTableC2[x] = new double[numClasses];
822  }
823 
824  classifier1->RetrieveCrossProbTable (_classes, crossProbTableC1);
825  classifier2->RetrieveCrossProbTable (_classes, crossProbTableC2);
826 
827  for (x = 0; x < numClasses; ++x)
828  {
829  for (y = 0; y < numClasses; ++y)
830  _crossProbTable[x][y] = (crossProbTableC1[x][y] + crossProbTableC2[x][y]) / 2.0;
831  }
832 
833  for (x = 0; x < numClasses; ++x)
834  {
835  delete crossProbTableC1[x]; crossProbTableC1[x] = NULL;
836  delete crossProbTableC2[x]; crossProbTableC2[x] = NULL;
837  }
838 
839  delete[] crossProbTableC1; crossProbTableC1 = NULL;
840  delete[] crossProbTableC2; crossProbTableC2 = NULL;
841 
842 } /* RetrieveCrossProbTable */
843 
844 
845 
846 
848 {
849  float totalSVs = 0.0;
850  kkuint32 count = 0;
851 
852  if (trainer1)
853  {
854  totalSVs += (float)(trainer1->NumOfSupportVectors ());
855  ++count;
856  }
857 
858  if (trainer2)
859  {
860  totalSVs += (float)(trainer2->NumOfSupportVectors ());
861  ++count;
862  }
863 
864  if (count > 0)
865  return (kkint32)(0.5f + totalSVs / (float)count);
866  else
867  return 0;
868 
869 } /* NumOfSupportVectors */
870 
871 
872 
873 
874 
875 void ModelDual::WriteXML (const KKStr& varName,
876  ostream& o
877  ) const
878 {
879  XmlTag startTag ("ModelDual", XmlTag::TagTypes::tagStart);
880  if (!varName.Empty ())
881  startTag.AddAtribute ("VarName", varName);
882  startTag.WriteXML (o);
883  o << endl;
884 
885  WriteModelXMLFields (o); // Write the base class data fields 1st.
886 
887  config1->WriteXML ("config1", o);
888  config2->WriteXML ("config2", o);
889 
890  trainer1->WriteXML ("trainer1", o);
891  trainer2->WriteXML ("trainer2", o);
892 
893  XmlTag endTag ("ModelDual", XmlTag::TagTypes::tagEnd);
894  endTag.WriteXML (o);
895  o << endl;
896 } /* WriteXML */
897 
898 
899 
900 
901 
903  XmlTagConstPtr tag,
904  VolConstBool& cancelFlag,
905  RunLog& log
906  )
907 {
908  delete config1; config1 = NULL;
909  delete config2; config2 = NULL;
910 
911  KKStr config1Name = "";
912  KKStr config2Name = "";
913 
914  XmlTokenPtr t = s.GetNextToken (cancelFlag, log);
915  while (t && (!cancelFlag))
916  {
917  t = ReadXMLModelToken (t, log);
918  bool tokenFound = true;
919  if ((t != NULL) && (t->TokenType () == XmlToken::TokenTypes::tokElement))
920  {
921  XmlElementPtr e = dynamic_cast<XmlElementPtr> (t);
922  if (!e)
923  {
924  tokenFound = false;
925  }
926  else
927  {
928  const KKStr& varName = e->VarName();
929  const KKStr& sectionName = e->SectionName ();
930 
931  if ((varName.EqualIgnoreCase ("config1")) && (typeid (*e) == typeid (XmlElementTrainingConfiguration2)))
932  {
933  delete config1;
934  config1 = dynamic_cast<XmlElementTrainingConfiguration2Ptr>(e)->TakeOwnership ();
935  config1Name = config1->ConfigRootName ();
936 
937  /**@todo I need the Config1 configuration read from the XML file to be correct; but to deal with this problem for now; will reload the original. */
938  delete config1;
939  config1 = new TrainingConfiguration2 ();
940  config1 ->Load (config1Name, false, log);
941  }
942 
943  else if ((varName.EqualIgnoreCase ("config2")) && (typeid (*e) == typeid (XmlElementTrainingConfiguration2)))
944  {
945  delete config2;
946  config2 = dynamic_cast<XmlElementTrainingConfiguration2Ptr>(e)->TakeOwnership ();
947  config2Name = config1->ConfigRootName ();
948  /**@todo I need the Config1 configuration read from the XML file to be correct; but to deal with this problem for now; will reload the original. */
949  delete config2;
950  config2 = new TrainingConfiguration2 ();
951  config2 ->Load (config2Name, false, log);
952  }
953 
954  else if ((varName.EqualIgnoreCase ("trainer1")) && (typeid (*e) == typeid (XmlElementTrainingProcess2)))
955  {
956  delete trainer1;
957  trainer1 = dynamic_cast<XmlElementTrainingProcess2Ptr>(e)->TakeOwnership ();
958  }
959 
960  else if ((varName.EqualIgnoreCase ("trainer2")) && (typeid (*e) == typeid (XmlElementTrainingProcess2)))
961  {
962  delete trainer2;
963  trainer2 = dynamic_cast<XmlElementTrainingProcess2Ptr>(e)->TakeOwnership ();
964  }
965  else
966  {
967  tokenFound = false;
968  }
969  }
970  }
971  if (!tokenFound)
972  {
973  KKStr errMsg (128);
974  errMsg << "ModelDual::ReadXML ***ERROR*** Unexpected Element: Section: " << t->SectionName () << " VarName:" << t->VarName ();
975  log.Level (-1) << endl << errMsg << endl << endl;
976  AddErrorMsg (errMsg, 0);
977  }
978 
979  delete t;
980  t = s.GetNextToken (cancelFlag, log);
981  }
982 
983  delete t;
984  t = NULL;
985 
986  if (cancelFlag)
987  validModel = false;
988 
989  if (validModel)
990  {
991  if (!trainer1)
992  {
993  validModel = false;
994  KKStr errMsg = "ModelDual::ReadXML ***ERROR*** trainer1 not loaded!!!";
995  log.Level (-1) << endl << errMsg << endl << endl;
996  AddErrorMsg (errMsg, 0);
997  }
998 
999  if (!trainer2)
1000  {
1001  validModel = false;
1002  KKStr errMsg = "ModelDual::ReadXML ***ERROR*** trainer2 not loaded!!!";
1003  log.Level (-1) << endl << errMsg << endl << endl;
1004  AddErrorMsg (errMsg, 0);
1005  }
1006 
1007  if (validModel)
1008  {
1009  delete classifier1; classifier1 = new Classifier2 (trainer1, log);
1010  delete classifier2; classifier2 = new Classifier2 (trainer2, log);
1011  }
1012  }
1013 
1014  if (!param)
1015  param = dynamic_cast<ModelParamDualPtr> (Model::param);
1016 
1017  if (Model::param == NULL)
1018  {
1019  KKStr errMsg (128);
1020  errMsg << "ModelDual::ReadXML ***ERROR*** Base class 'Model' does not have 'param' defined.";
1021  AddErrorMsg (errMsg, 0);
1022  log.Level (-1) << endl << errMsg << endl << endl;
1023  }
1024 
1025  else if (typeid (*Model::param) != typeid(ModelParamDual))
1026  {
1027  KKStr errMsg (128);
1028  errMsg << "ModelDual::ReadXML ***ERROR*** Base class 'Model' param parameter is of the wrong type; found: " << Model::param->ModelParamTypeStr ();
1029  AddErrorMsg (errMsg, 0);
1030  log.Level (-1) << endl << errMsg << endl << endl;
1031  }
1032 
1033  else
1034  {
1035  param = dynamic_cast<ModelParamDualPtr> (Model::param);
1036  }
1037 
1038  ReadXMLModelPost (log);
1039 } /* ReadXML */
1040 
1041 
1042 
1043 XmlFactoryMacro(ModelDual)
virtual void Load(const KKStr &_configFileName, bool _validateDirectories, RunLog &log)
KKStr(kkint32 size)
Creates a KKStr object that pre-allocates space for &#39;size&#39; characters.
Definition: KKStr.cpp:655
XmlTag(const KKStr &_name, TagTypes _tagType)
Definition: XmlStream.cpp:586
const KKStr & Name() const
Definition: Model.h:178
Base class to all Learning Algorithms.
Definition: Model.h:82
TrainingProcess2Ptr trainer2
Definition: ModelDual.h:221
KKStr & operator+=(const KKStr &right)
Definition: KKStr.h:682
TrainingConfiguration2Ptr config2
Definition: ModelDual.h:218
__int32 kkint32
Definition: KKBaseTypes.h:88
FeatureVector * FeatureVectorPtr
Definition: Model.h:44
KKStr ExtractToken2(const char *delStr="\n\t\r ")
Extract first Token from the string.
Definition: KKStr.cpp:3026
virtual ClassProbListPtr ProbabilitiesByClass(FeatureVectorPtr example, RunLog &log)
Definition: ModelDual.cpp:591
KKException(const KKStr &_exceptionStr, const KKException &_innerException)
Definition: KKException.cpp:83
virtual void WriteXML(const KKStr &varName, ostream &o) const
Definition: ModelDual.cpp:875
XmlTokenPtr ReadXMLModelToken(XmlTokenPtr t, RunLog &log)
Will process any tokens that belong to &#39;ModelParam&#39; and return NULL ones that are not will be passed ...
Definition: Model.cpp:884
void MergeIn(const ClassProbPtr cp)
Adds the Prediction in &#39;cp&#39; into this list.
Definition: ClassProb.cpp:268
ModelParamPtr param
Definition: Model.h:412
const KKStr & ConfigFileName2() const
FeatureVectorListPtr trainExamples
Definition: Model.h:424
void ReconcileProbAndVotes(Classifier2Ptr classifier, MLClassPtr predClass, FeatureVectorPtr encodedExample, double &predClassProb, kkint32 &predClassVotes)
Definition: ModelDual.cpp:396
Represents a "Class" in the Machine Learning Sense.
Definition: MLClass.h:52
void AddErrorMsg(const KKStr &errMsg, kkint32 lineNum)
Definition: Model.cpp:239
virtual void ProbabilitiesByClassDual(FeatureVectorPtr example, KKStr &classifier1Desc, KKStr &classifier2Desc, ClassProbListPtr &classifier1Results, ClassProbListPtr &classifier2Results, RunLog &log)
Only applied to ModelDual classifier.
Definition: ModelDual.cpp:628
Classifier2Ptr classifier1
Definition: ModelDual.h:223
void WriteModelXMLFields(std::ostream &o) const
The "WriteXML" method in Derived classes call this method to include the parents classes fields in th...
Definition: Model.cpp:854
FactoryFVProducerPtr factoryFVProducer
Definition: Model.h:404
ModelParamDualPtr Param()
Definition: ModelDual.cpp:158
KKStr operator+(const char *right) const
Definition: KKStr.cpp:3986
virtual const KKStr & SectionName() const
Definition: XmlStream.h:265
XmlToken * XmlTokenPtr
Definition: XmlStream.h:18
unsigned __int32 kkuint32
Definition: KKBaseTypes.h:89
void DeleteExistingClassifiers()
Definition: ModelDual.cpp:164
virtual void WriteXML(const KKStr &varName, std::ostream &o) const
virtual KKStr Description() const
Definition: ModelDual.cpp:133
KKException(const KKStr &_exceptionStr, const std::exception &_innerException)
Definition: KKException.cpp:52
virtual FeatureVectorPtr PrepExampleForPrediction(FeatureVectorPtr fv, bool &newExampleCreated)
Every prediction method in every class that is inherited from this class should call this method befo...
Definition: Model.cpp:574
KKStr & operator=(KKStr &&src)
Definition: KKStr.cpp:1369
kkuint32 Len() const
Returns the number of characters in the string.
Definition: KKStr.h:366
kkint32 NumOfSupportVectors() const
virtual kkint32 MemoryConsumedEstimated() const
KKTHread * KKTHreadPtr
void Append(char ch)
Definition: KKStr.cpp:1863
KKStr operator+(const char *left, const KKStr &right)
Definition: KKStr.cpp:3976
const ClassProbPtr LookUp(MLClassPtr targetClass) const
Definition: ClassProb.cpp:160
void ClassifyAExample(FeatureVector &example, MLClassPtr &predClass1, MLClassPtr &predClass2, kkint32 &predClass1Votes, kkint32 &predClass2Votes, double &knownClassProb, double &predClass1Prob, double &predClass2Prob, kkint32 &numOfWinners, double &breakTie)
XmlElement * XmlElementPtr
Definition: XmlStream.h:21
void AddAtribute(const KKStr &attributeName, const KKStr &attributeValue)
Definition: XmlStream.cpp:602
virtual void RetrieveCrossProbTable(MLClassList &classes, double **crossProbTable, RunLog &log)
Definition: ModelDual.cpp:800
static TrainingProcess2Ptr CreateTrainingProcessFromTrainingExamples(TrainingConfiguration2Const *config, FeatureVectorListPtr trainingExamples, bool takeOwnershipOfTrainingExamples, bool featuresAlreadyNormalized, VolConstBool &cancelFlag, RunLog &log)
Will Construct an instance using provided list of examples rather than loading from training library...
static bool ConfigFileExists(const KKStr &_configFileName)
bool Empty() const
Definition: KKStr.h:241
virtual MLClassPtr Predict(FeatureVectorPtr example, RunLog &log)
Definition: ModelDual.cpp:430
XmlTag const * XmlTagConstPtr
Definition: KKStr.h:45
void WriteXML(const KKStr &varName, std::ostream &o) const
bool validModel
Definition: Model.h:426
Manages the reading and writing of objects in a simple XML format. For a class to be supported by Xml...
Definition: XmlStream.h:46
virtual ModelDualPtr Duplicate() const
Definition: ModelDual.cpp:151
void TrainingTimeEnd()
Derived classes call this method to stop the clock for &#39;trainingTime&#39;.
Definition: Model.cpp:452
virtual kkint32 MemoryConsumedEstimated() const
Definition: Model.cpp:208
kkint32 MemoryConsumedEstimated() const
static KKStr Concat(const std::vector< std::string > &values)
Concatenates the list of &#39;std::string&#39; strings.
Definition: KKStr.cpp:1082
ClassProbList * ClassProbListPtr
Definition: Classifier2.h:30
double probability
Definition: ClassProb.h:36
Classifier2(TrainingProcess2Ptr _trainer, RunLog &_log)
Definition: Classifier2.cpp:42
Classifier2Ptr classifier2
Definition: ModelDual.h:224
void AddIn(const ClassProbListPtr otherPredictions)
Adds the contents of &#39;otherPredictions&#39; to this list.
Definition: ClassProb.cpp:246
virtual void Predict(FeatureVectorPtr example, MLClassPtr knownClass, MLClassPtr &predClass1, MLClassPtr &predClass2, kkint32 &predClass1Votes, kkint32 &predClass2Votes, double &probOfKnownClass, double &predClass1Prob, double &predClass2Prob, kkint32 &numOfWinners, bool &knownClassOneOfTheWinners, double &breakTie, RunLog &log)
Definition: ModelDual.cpp:462
virtual const KKStr & VarName() const
Definition: XmlStream.cpp:794
bool operator==(const KKStr &right) const
Definition: KKStr.cpp:1550
const KKStr & Name() const
Definition: MLClass.h:154
Model(const KKStr &_name, const ModelParam &_param, FactoryFVProducerPtr _factoryFVProducer)
Construct a instance of &#39;Model&#39; using the parameters specified in &#39;_param&#39;.
Definition: Model.cpp:152
ModelParamDual * ModelParamDualPtr
Definition: ModelDual.h:56
KKStr operator+(const KKStr &right) const
Definition: KKStr.cpp:3998
virtual const KKStr & SectionName() const
Definition: XmlStream.cpp:785
Will implement the Dual Classifier Model.
Definition: ModelDual.h:66
static MLClassPtr CreateNewMLClass(const KKStr &_name, kkint32 _classId=-1)
Static method used to create a new instance of a MLClass object.
Definition: MLClass.cpp:100
TrainingConfiguration2Ptr config1
Definition: ModelDual.h:217
virtual TrainingConfiguration2Ptr ManufacturTrainingConfiguration() const
Returns a &#39;TrainingConfiguration2&#39; derived instance.
ModelParamDualPtr param
Definition: ModelDual.h:229
ModelDual(const ModelDual &_model)
Definition: ModelDual.cpp:86
virtual ~ModelDual()
Frees any memory allocated by, and owned by the ModelDual.
Definition: ModelDual.cpp:106
virtual void ReadXML(XmlStream &s, XmlTagConstPtr tag, VolConstBool &cancelFlag, RunLog &log)
To be implemented by derived classes; the parent classes fields will be updated by the derived class ...
Definition: ModelDual.cpp:902
void NormalizeToOne()
Will normalize the list of predictions such that the total probability will equal 1...
Definition: ClassProb.cpp:336
virtual kkint32 MemoryConsumedEstimated() const
Definition: ModelDual.cpp:120
void WriteXML(std::ostream &o)
Definition: XmlStream.cpp:723
Used for logging messages.
Definition: RunLog.h:49
void EncodeProblem(const struct svm_paramater &param, struct svm_problem &prob_in, struct svm_problem &prob_out)
const KKStr & ConfigFileName() const
virtual void TrainModel(FeatureVectorListPtr _trainExamples, bool _alreadyNormalized, bool _takeOwnership, VolConstBool &_cancelFlag, RunLog &_log)
Performs operations such as FeatureEncoding, and Normalization. The actual training of models occurs ...
Definition: Model.cpp:467
bool StartsWith(const KKStr &value) const
Definition: KKStr.cpp:1137
ClassProbListPtr ProbabilitiesByClass(FeatureVectorPtr example)
void TrainingTimeStart()
Derived classes call this method to start the clock for &#39;trainingTime&#39;.
Definition: Model.cpp:445
void ReadXMLModelPost(RunLog &log)
Definition: Model.cpp:987
const KKStr & ConfigFileName1() const
virtual KKStr ModelParamTypeStr() const
Definition: ModelParam.h:108
virtual TokenTypes TokenType()=0
void RetrieveCrossProbTable(MLClassList &classes, double **crossProbTable)
virtual kkint32 NumOfSupportVectors() const
Definition: ModelDual.cpp:847
Model(const Model &_madel)
Copy Constructor.
Definition: Model.cpp:69
virtual XmlTokenPtr GetNextToken(VolConstBool &cancelFlag, RunLog &log)
Definition: XmlStream.cpp:116
KKException(const KKStr &_exceptionStr)
Definition: KKException.cpp:45
Maintains a list of MLClass instances.
Definition: MLClass.h:233
virtual void ProbabilitiesByClass(FeatureVectorPtr example, const MLClassList &_mlClasses, kkint32 *_votes, double *_probabilities, RunLog &log)
Definition: ModelDual.cpp:676
FeatureVectorList * FeatureVectorListPtr
Definition: Model.h:46
MLClassPtr classLabel
Definition: ClassProb.h:35
virtual void ProbabilitiesByClass(FeatureVectorPtr _example, const MLClassList &_mlClasses, double *_probabilities, RunLog &_log)
Derives predicted probabilities by class.
Definition: ModelDual.cpp:741
bool FullHierarchyMustMatch() const
virtual const KKStr & VarName() const
Definition: XmlStream.h:269
#define XmlFactoryMacro(NameOfClass)
Definition: XmlStream.h:688
MLClassPtr ReconcilePredictions(MLClassPtr pred1, MLClassPtr pred2, RunLog &log)
Definition: ModelDual.cpp:320
TrainingProcess2Ptr trainer1
Definition: ModelDual.h:220
FactoryFVProducer * FactoryFVProducerPtr
Definition: Model.h:75
ModelDual(const KKStr &_name, const ModelParamDual &_param, FactoryFVProducerPtr _factoryFVProducer)
Definition: ModelDual.cpp:67
ModelDual(FactoryFVProducerPtr _factoryFVProducer)
Definition: ModelDual.cpp:54
Model(FactoryFVProducerPtr _factoryFVProducer)
Use this when you are planning on creating a empty model without parameters.
Definition: Model.cpp:117
KKStr osGetRootName(const KKStr &fullFileName)
MLClassPtr ClassifyAExample(FeatureVector &example)
MLClassPtr OtherClass() const
ClassProb * ClassProbPtr
Definition: Classifier2.h:28
volatile const bool VolConstBool
Definition: KKBaseTypes.h:163
virtual void TrainModel(FeatureVectorListPtr _trainExamples, bool _alreadyNormalized, bool _takeOwnership, VolConstBool &_cancelFlag, RunLog &_log)
Performs operations such as FeatureEncoding, and Normalization. The actual training of models occurs ...
Definition: ModelDual.cpp:177