/// <summary> /// Performs initialization functions common to all constructors /// </summary> private void Init() { this.PropertyChanged += PatternRecognizer_PropertyChanged; _progressLog = new ProgressLog(); activationFunctionIdx = -1; normalizerIdx = -1; _converter = new ClassifToMovCodeConverter(); activationTolerance = 0.1; }
/// <summary> /// Worker method performing the actual validation process /// </summary> private void ValidationWorker() { /* * WE HAVE MOVED THE VALIDATION CODE FROM THE PatternRecognizer OBJECT TO HERE. * This was done because certain required value objects like movement lists have * nothing to do with pattern recognising. */ int okCount = 0; int failCount = 0; int expected; int predicted; ClassifToMovCodeConverter c2mConverter = new ClassifToMovCodeConverter(); MovListToCodeConverter ml2cConverter = new MovListToCodeConverter(totalSingleMovements, allowedComplexMovements); c2mConverter.multipleActivation = _patternRecognizer.multipleActivationEnabled; c2mConverter.activationLevel = _patternRecognizer.activationLevel; c2mConverter.activationTolerance = _patternRecognizer.activationTolerance; c2mConverter.movementCodes = _patternRecognizer.trainingPackage.movementCodes; Dictionary<int, Dictionary<int, int>> confusionMatrix = new Dictionary<int, Dictionary<int, int>>(); Dictionary<int, int> predictedDictionary; progressLog.Log(ProgressLogItem.Info, "*********** VALIDATION ************"); foreach (DataSet dataSet in _patternRecognizer.trainingPackage.validationSets) { expected = dataSet.movementCode; okCount = 0; failCount = 0; foreach (DataWindow dataWindow in dataSet.set) { double[] inputVector = new double[_patternRecognizer.inputDim]; for (int j = 0; j < dataWindow.features.Values.Count; j++) { double[] channelVector = (double[])dataWindow.features.Values.ElementAt(j); for (int k = 0; k < channelVector.Length; k++) inputVector[(j * channelVector.Length) + k] = channelVector[k]; } double[] outputVector = (double[])_patternRecognizer.Classify(inputVector); //Here we must determine which movement code corresponds better //with the input vector. The method for doing this changes depending on //whether we are using explicit movement codes or not, so we implement it using a converter class if (_patternRecognizer.multipleActivationEnabled) { List<ushort> movementList = (List<ushort>)c2mConverter.Convert(outputVector, null, null, null); predicted = (int)ml2cConverter.Convert(movementList.ToArray(), null, null, null); //The following happens when several outputs went active producing an impossible composite movement //such as "rest + open" or "open + close", for instance. if (predicted == -1) predicted = movementList.First(); //TODO: in this case, we opt for getting the //first movement of the list, bur we could do other things, like try and remove an element at //a tome and see when we come to a valid combination } else predicted = (int)c2mConverter.Convert(outputVector, null, null, null); //Now we check if the predicted movement matches the expected movement if (predicted == expected) okCount++; else failCount++; //Additionally, we compose the confusion matrix. if (confusionMatrix.TryGetValue(expected, out predictedDictionary)) { int predictedCount; if (predictedDictionary.TryGetValue(predicted, out predictedCount)) { predictedDictionary[predicted]++; } else predictedDictionary.Add(predicted, 1); } else { predictedDictionary = new Dictionary<int, int>(); predictedDictionary.Add(predicted, 1); confusionMatrix.Add(expected, predictedDictionary); } } string report = "Testing movement <mov " + expected + "/> -> correct: " + Math.Round(100 * okCount / (double)(okCount + failCount), 2) + "%"; confusionMatrix.TryGetValue(expected, out predictedDictionary); if (predictedDictionary.Keys.Count > 1) { report = report + "; misclassified as: "; foreach (int prediction in predictedDictionary.Keys) { if (prediction != expected) { report = report + "<mov " + prediction + "/> " + Math.Round(100 * predictedDictionary[prediction] / (double)(okCount + failCount), 2) + "%; "; } } } progressLog.Log(ProgressLogItem.Info, report); } progressLog.Log(ProgressLogItem.Info, "********* VALIDATION FINISHED *********"); }
public override void Init() { base.Init(); _producerGuid = _objectServer.RegisterProducer(); _matchBuffer.Clear(); _lastOutput = int.MinValue; _converter = new ClassifToMovCodeConverter(); _converter.multipleActivation = multipleActivation; _converter.activationLevel = activationLevel; _converter.activationTolerance = activationTolerance; _converter.movementCodes = movementCodes; _codeConverter = new MovListToCodeConverter(numSingleMovements,allowedComplexMovements); if (levelControlled) movementCodeMaker = ThresholdCodeMaker; else movementCodeMaker = PatternRecognitionCodeMaker; }