27 using namespace KKMLL;
32 FeatureVectorListPtr _examples,
33 MLClassListPtr _mlClasses,
35 bool _featuresAreAlreadyNormalized,
40 featuresAreAlreadyNormalized (_featuresAreAlreadyNormalized),
42 foldAccuracies (NULL),
44 confusionMatrix (NULL),
45 cmByNumOfConflicts (NULL),
47 mlClasses (_mlClasses),
49 maxNumOfConflicts (0),
50 numOfFolds (_numOfFolds),
51 numOfSupportVectors (0),
52 numOfWinnersCounts (NULL),
53 numOfWinnersCorrects (NULL),
54 numOfWinnersOneOfTheWinners (NULL),
55 classificationTime (0.0),
60 examplesPerClass = 999999;
67 DeleteAllocatedMemory ();
68 delete examples; examples = NULL;
76 maxNumOfConflicts = mlClasses->QueueSize () + 1;
79 cmByNumOfConflicts =
new ConfusionMatrix2Ptr[maxNumOfConflicts];
81 numOfWinnersCounts =
new kkint32[maxNumOfConflicts];
82 numOfWinnersCorrects =
new kkint32[maxNumOfConflicts];
83 numOfWinnersOneOfTheWinners =
new kkint32[maxNumOfConflicts];
87 for (conflictIDX = 0; conflictIDX < maxNumOfConflicts; conflictIDX++)
90 numOfWinnersCounts [conflictIDX] = 0;
91 numOfWinnersCorrects [conflictIDX] = 0;
92 numOfWinnersOneOfTheWinners [conflictIDX] = 0;
95 foldAccuracies =
new float[numOfFolds];
96 foldCounts =
new kkint32[numOfFolds];
100 for (foldNum = 0; foldNum < numOfFolds; foldNum++)
102 foldAccuracies [foldNum] = 0.0;
103 foldCounts [foldNum] = 0;
112 maxNumOfConflicts = mlClasses->QueueSize () + 1;
115 delete confusionMatrix;
116 confusionMatrix = NULL;
121 if (cmByNumOfConflicts)
123 for (conflictIDX = 0; conflictIDX < maxNumOfConflicts; conflictIDX++)
125 delete cmByNumOfConflicts[conflictIDX];
126 cmByNumOfConflicts[conflictIDX] = NULL;
129 delete cmByNumOfConflicts;
130 cmByNumOfConflicts = NULL;
133 delete foldAccuracies; foldAccuracies = NULL;
134 delete foldCounts; foldCounts = NULL;
136 delete numOfWinnersCounts; numOfWinnersCounts = NULL;
137 delete numOfWinnersCorrects; numOfWinnersCorrects = NULL;
138 delete numOfWinnersOneOfTheWinners; numOfWinnersOneOfTheWinners = NULL;
146 log.Level (10) <<
"CrossValidationVoting::RunCrossValidationVoting" << endl;
150 log.Level (-1) << endl
152 <<
"CrossValidationVoting::RunCrossValidationVoting **** ERROR ****" << endl
154 <<
" Invalid numOfFolds[" << numOfFolds <<
"]." << endl
159 DeleteAllocatedMemory ();
160 AllocateMemory (log);
162 kkint32 imageCount = examples->QueueSize ();
163 kkint32 numImagesPerFold = (imageCount + numOfFolds - 1) / numOfFolds;
168 for (foldNum = 0; foldNum < numOfFolds; foldNum++)
174 if (foldNum == (numOfFolds - 1))
175 lastInGroup = imageCount;
177 lastInGroup = firstInGroup + numImagesPerFold - 1;
180 cout <<
"Fold [" << (foldNum + 1) <<
"] of [" << numOfFolds <<
"]" << endl;
185 log.Level (30) <<
"Fold Num[" << foldNum <<
"] " 186 <<
"FirstTestImage[" << firstInGroup <<
"] " 187 <<
"LastInGroup[" << lastInGroup <<
"]." 190 for (
kkint32 x = 0; x < imageCount; x++)
192 FeatureVectorPtr newImage = examples->IdxToPtr (x)->Duplicate ();
193 if ((x >= firstInGroup) && (x <= lastInGroup))
199 cout <<
"Number Of Training Images : " << trainingExamples->QueueSize () << endl;
200 cout <<
"Number Of Test Images : " << testImages->QueueSize () << endl;
202 CrossValidate (testImages, trainingExamples, foldNum, NULL, log);
204 delete trainingExamples; trainingExamples = NULL;
205 delete testImages; testImages = NULL;
206 firstInGroup = firstInGroup + numImagesPerFold;
215 bool* classedCorrectly,
219 log.Level (10) <<
"CrossValidationVoting::RunValidationOnly" << endl;
220 DeleteAllocatedMemory ();
221 AllocateMemory (log);
228 CrossValidate (testImages, trainingExamples, 0, classedCorrectly, log);
230 delete trainingExamples;
238 FeatureVectorListPtr trainingExamples,
240 bool* classedCorrectly,
244 log.Level (20) <<
"CrossValidationVoting::CrossValidate FoldNum[" << foldNum <<
"]." << endl;
246 kkint32 numOfClasses = mlClasses->QueueSize ();
248 bool cancelFlag =
false;
251 vector<TrainingProcess2Ptr> trainers;
252 vector<Classifier2Ptr> classifiers;
255 for (idx = 0; idx < configs->QueueSize (); idx++)
257 TrainingConfiguration2Ptr config = configs->IdxToPtr (idx);
264 featuresAreAlreadyNormalized
, 272 log.Level (20) <<
"CrossValidate Creating Classification Object" << endl;
276 trainers.push_back (trainer);
277 classifiers.push_back (classifier);
286 FeatureVectorList::iterator imageIDX = testImages->begin ();
294 log.Level (20) <<
"CrossValidate Classifying Test Images." << endl;
298 for (imageIDX = testImages->begin (); imageIDX != testImages->end (); imageIDX++)
300 MLClassPtr knownClass = (*imageIDX)->MLClass ();
303 bool knownClassOneOfTheWinners =
false;
304 MLClassPtr predictedClass = NULL;
305 double breakTie = 0.0;
309 vector<kkint32> voteTable (numOfClasses, 0);
310 vector<
double> probTable (numOfClasses, 0.0f);
312 for (idx = 0; idx < (kkint32)classifiers.size (); idx++)
314 classifier = classifiers[idx];
315 predictedClass = classifier->ClassifyAExample (*(*imageIDX),
318 knownClassOneOfTheWinners,
321 kkint32 predictedIdx = mlClasses->PtrToIdx (predictedClass);
323 if ((predictedIdx < 0) || (predictedIdx >= mlClasses->QueueSize ()))
326 log.Level (-1) << endl
328 <<
"CrossValidationVoting::CrossValidate *** ERROR ***" << endl
330 <<
"UnKnown Class was returned[" << predictedClass->Name () <<
"]" << endl
331 <<
"predictedIdx[" << predictedIdx <<
"]" << endl
337 voteTable[predictedIdx]++;
339 if (probTable[predictedIdx] == 0.0f)
340 probTable[predictedIdx] = probability;
342 probTable[predictedIdx] *= probability;
348 double probTotal = 0.0f;
349 for (x = 0; x < numOfClasses; x++)
350 probTotal += probTable[x];
352 for (x = 0; x < numOfClasses; x++)
353 probTable[x] = probTable[x] / probTotal;
365 for (x = 0; x < numOfClasses; x++)
367 if (voteTable[x] > highVote)
369 highVote = voteTable[x];
374 else if (voteTable[x] == highVote)
380 if (numOfWinners > 1)
383 double highProbability = 0.0f;
385 for (x = 0; x < numOfClasses; x++)
387 if (voteTable[x] >= highVote)
389 if (probTable[x] > highProbability)
391 highProbability = probTable[x];
398 predictedClass = mlClasses->IdxToPtr (winnerIdx);
399 probability = probTable[winnerIdx];
402 confusionMatrix->Increment (knownClass,
404 (kkint32)(*imageIDX)->OrigSize (),
409 cmByNumOfConflicts[numOfWinners]->Increment (knownClass,
411 (kkint32)(*imageIDX)->OrigSize (),
416 bool correctClassificationMade =
false;
417 numOfWinnersCounts[numOfWinners]++;
420 correctClassificationMade =
true;
421 numOfWinnersCorrects[numOfWinners]++;
425 if (classedCorrectly)
427 classedCorrectly[foldCount] = correctClassificationMade;
430 if (knownClassOneOfTheWinners)
431 numOfWinnersOneOfTheWinners[numOfWinners]++;
433 log.Level (50) <<
"CrossValidate - Known Class[" << knownClass->Name () <<
"] " 434 <<
"Predicted Class[" << predictedClass->Name () <<
"]." 441 classificationTime += (endClassificationTime - startClassificationTime);
443 float foldAccuracy = 0.0;
446 foldAccuracy = 100.0f * (
float)foldCorrect / (
float)foldCount;
448 foldAccuracies [foldNum] = foldAccuracy;
449 foldCounts [foldNum] = foldCount;
452 for (idx = 0; idx < (kkint32)trainers.size (); idx++)
453 {
delete trainers[idx]; trainers[idx] = NULL;}
455 for (idx = 0; idx < (kkint32)classifiers.size (); idx++)
456 {
delete classifiers[idx]; classifiers[idx] = NULL;}
458 log.Level (20) <<
"CrossValidationVoting::CrossValidate - Done." << endl;
480 KKStr foldAccuracyStr
(9 * numOfFolds
);
482 for (
kkint32 foldNum = 0; foldNum < numOfFolds; foldNum++)
485 foldAccuracyStr <<
"\t";
489 return foldAccuracyStr;
501 if ((foldNum < 0) || (foldNum >= numOfFolds))
504 return foldAccuracies[foldNum];
512 if ((numOfFolds <= 0) || (!foldAccuracies))
517 KKStr result
(numOfFolds + 10
);
519 for (x = 0; x < numOfFolds; x++)
523 result << foldAccuracies[x];
KKStr(kkint32 size)
Creates a KKStr object that pre-allocates space for 'size' characters.
void PushOnBack(FeatureVectorPtr image)
Overloading the PushOnBack function in KKQueue so we can monitor the Version and Sort Order...
double TrainingTime() const
MLClassPtr GetNoiseClass() const
virtual FeatureVectorListPtr DuplicateListAndContents() const
Creates a duplicate of list and also duplicates it contents.
virtual FeatureVectorListPtr ManufactureEmptyList(bool _owner) const
Creates an instance of a Empty FeatureVectorList.
void RunCrossValidation(RunLog &log)
kkint32 NumOfSupportVectors() const
KKStr FoldAccuracysToStr() const
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...
ConfusionMatrix2(const MLClassList &_classes)
static KKStr Concat(const std::vector< std::string > &values)
Concatenates the list of 'std::string' strings.
Classifier2(TrainingProcess2Ptr _trainer, RunLog &_log)
TrainingProcess2 * TrainingProcess2Ptr
bool operator==(const KKStr &right) const
const KKStr & UpperName() const
void RunValidationOnly(FeatureVectorListPtr validationData, bool *classedCorrectly, RunLog &log)
KKStr StrFormatDouble(double val, const char *mask)
double osGetSystemTimeUsed()
Returns the number of CPU seconds used by current process.
CrossValidationVoting(TrainingConfiguration2ListPtr _configs, FeatureVectorListPtr _examples, MLClassListPtr _mlClasses, kkint32 _numOfFolds, bool _featuresAreAlreadyNormalized, FileDescPtr _fileDesc)
Used for logging messages.
void EncodeProblem(const struct svm_paramater ¶m, struct svm_problem &prob_in, struct svm_problem &prob_out)
FeatureVectorListPtr ExtractExamplesForClassList(MLClassListPtr classes)
A confusion matrix object that is used to record the results from a CrossValidation. <see also cref="CrossValidation"
Classifier2 * Classifier2Ptr
float FoldAccuracy(kkint32 foldNum) const