/// <summary> /// Calculates accuracy of the PCA Classifier /// </summary> /// <param name="testingPath"> Location of the Testing Files</param> /// <param name="decision"> Whether ClossestNeighbor or KNN</param> /// <param name="measureType"> Wether Euclidean or Projection</param> /// <param name="numberNeighbs"> How many neighbors to take into account for KNN</param> /// <returns></returns> public double Accuracy(String testingPath, DecisionType decision, ClossenessMeasure measureType, int numberNeighbs) { List <ATTFace> testingFaces = DataUnit.GetTestingData(testingPath); double accu = 0; foreach (ATTFace testFace in testingFaces) { int guessID = 0; List <ATTFace> bestFaces = new List <ATTFace>(); FindBestMatch(testFace.ImageVector, decision, measureType, ref bestFaces, ref guessID, neighborNumber: numberNeighbs); if (guessID == testFace.personID) { accu += 1; } } return(accu / testingFaces.Count); }
/// <summary> /// Finds the Best Match(es) as a list, and provides a guessed Person ID. /// </summary> /// <param name="imageAsVector"> Image of the person to be classified.</param> /// <param name="decisionType"> Either ClossestNeighbor or KKN</param> /// <param name="measureType"> Either Euclidean or Projection. Determines which measurement is to be used.</param> /// <param name="BestFaces"> List of ATTFaces passed by reference. Must be empty. BestMatches added to the list if onlyID = false</param> /// <param name="guessID">int passed by reference. The class of the person images guessed by PCA.</param> /// <param name="neighborNumber"> How many neighbors to use for KNN. Default is 3</param> /// <param name="numberFaces">How many Best Matches to add to BestFaces. Default is 6</param> /// <param name="onlyID"> Whether ONLY the class of the person is of interest. If the BestFaces are also of interest, set to false/</param> public void FindBestMatch(double[] imageAsVector, DecisionType decisionType, ClossenessMeasure measureType, ref List <ATTFace> BestFaces, ref int guessID, int neighborNumber = 3, int numberFaces = 6, bool onlyID = true) { double[] meanAdjusted = SubstractArrays(imageAsVector, MeanFaceAsArray); double[] projectedImage = ComputeProjection(meanAdjusted); foreach (ATTFace Person in DataSet) { double similarity; if (measureType == ClossenessMeasure.Euclidean) { similarity = EuclideanDistance(Person.ImageVectorTransformed, projectedImage); Person.Closeness = similarity; } else if (measureType == ClossenessMeasure.Projection) { similarity = DotProduct(Person.ImageVectorTransformed, projectedImage); Person.Closeness = -similarity; //A maximization is transformed to a minimization by putting a - } else { throw new ArgumentException("ClosenessMeasure is not supported!"); } } DataSet.Sort(); // ------------------------------------------ Retrieving best guess ------------------------------// if (decisionType == DecisionType.ClossestNeighbor) { guessID = DataSet[0].personID; } else if (decisionType == DecisionType.KNN) { IDictionary <int, int> Tally = new Dictionary <int, int>(); int maxVotes = 0; guessID = -1; for (int i = 0; i < neighborNumber; i++) { ATTFace Person = DataSet[i]; if (Tally.ContainsKey(Person.personID)) { Tally[Person.personID]++; if (Tally[Person.personID] > maxVotes) { //To be here, a personID needs at leats two votes maxVotes = Tally[Person.personID]; guessID = Person.personID; } } else { Tally.Add(Person.personID, 1); } } } else { throw new ArgumentException("DecisionType not valid!"); } // ---------------------------- Populating the list onlyID = False ----------------// if (!onlyID) { for (int i = 0; i < numberFaces; i++) { BestFaces.Add((ATTFace)DataSet[i].Clone()); } } }