public override void Run() { _converter = new MovListToCodeConverter(Properties.Settings.Default.movementsList.Count,Properties.Settings.Default.allowedMovements); movCode=(int)_converter.Convert(new ushort[] { 1, 3 }, null, null, null); movCode = (int)_converter.Convert(new ushort[] { 1, 2 }, null, null, null); movCode = (int)_converter.Convert(new ushort[] { 5 }, null, null, null); movCode = (int)_converter.Convert(new ushort[] { 1, 3, 6 }, null, null, null); }
/// <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 *********"); }
/// <summary> /// Composes a recording schedule by using as inputs the list of selected movements, the number of /// simultaneous movements and checking the restrictions for combining movements /// </summary> public void ComposeSchedule() { ObservableCollection<ScheduleItem> schedule = recordingConfig.schedule; List<ushort[]> provList = new List<ushort[]>(); ushort[] movement; if ((_selectedMovements.Count <= 0) || (simultMovements <= 0)) return; if (_simultMovements > 1) recursiveCompose(provList, new ushort[_simultMovements], 0, 0); else { for (int i = 0; i < _selectedMovements.Count; i++) { movement = new ushort[_simultMovements]; movement[0] = (ushort)_selectedMovements.ElementAt(i).idTag; provList.Add(movement); } } if (provList.Count > 0) { //At this point we should have a list of allowed compound movements created from the list //of selected simple movements and the number simultaneous movements selected. Now we compose //a schedule including rests and repetitions //Adding as much initial rests as WarmupItems are configured in the recording configuration. These //WILL NOT BE RECORDED MovListToCodeConverter converter = new MovListToCodeConverter(numSingleMovements , allowedComplexMovements); for (int i = 0; i < recordingConfig.scheduleWarmupItems; i++) { movement = new ushort[1]; movement[0] = 0; schedule.Add(new ScheduleItem((int)converter.Convert(movement,null,null,null), movement)); } for (int i = 0; i < provList.Count; i++) { for (int j = 0; j < recordingConfig.repetitions; j++) { schedule.Add(new ScheduleItem((int)converter.Convert(provList.ElementAt(i),null,null,null), provList.ElementAt(i))); movement = new ushort[1]; movement[0] = 0; schedule.Add(new ScheduleItem((int)converter.Convert(movement,null,null,null), movement)); //An rest after each movement } } //The schedule is now complete. } }