예제 #1
0
        public double Verify(double[] features, string identifier)
        {
            // trying to match on an identifier that hasn't been trained wouldn't make sense
            if (!trainedIdentifiers.Contains(identifier))
            {
                throw new ArgumentException("Provided identifier does not match any trained identifiers");
            }

            // scale/shift features to fit within standard range
            double[] standardizedFeatures = StandardizationHelpers.GenerateTransformedData(features, (value, i) => (value * featureScaling[i]) + featureShift[i]);
            return(classifier.Verify(standardizedFeatures, identifier));
        }
 public List <Tuple <double, double[]> > GetScaledDimensions(ISample sample)
 {
     return(StandardizationHelpers.GenerateTransformedData(sample.GetDimensions(), (value, i) => (value * featureScaling[i]) + featureShift[i])
            .Select((value, i) => new Tuple <double, double[]>(i, new double[] { value })).ToList());
 }
예제 #3
0
        public override P Train <P>(List <ISample> trainingSamples)
        {
            InitializeTimeAndCountProperties(trainingSamples, columns);
            // get the aligned training samples
            Dictionary <int, List <AlignedRegressionColumn> > csAlignedSamples = FindApproximateDTWAlignment(trainingSamples, base.trainingColumnCount, base.trainingRowCount, bandwidth); // resample back to original number of training rows

            // the dtw path in the alignment for the sample with the lowest total cost (marked as IsTemplate)
            Templates = csAlignedSamples.Select(column => new { column = column.Key, template = column.Value.First(row => row.IsTemplate) }).ToDictionary(col => col.column, col => StandardizationHelpers.Resample(col.template.GetRows(), trainingRowCount));

            // calculate the regression slopes for the set of aligned signals (key = time slopes, value = force slopes)
            AlignedRegressor regressor = GenerateRegressionSlopes <AlignedRegressionColumn, AlignedRegressor>(csAlignedSamples);

            AmplitudeSlopes = regressor.GetAmplitudeSlopes().ToDictionary(slopes => slopes.Key, slopes => StandardizationHelpers.Resample(slopes.Value, trainingRowCount)); // resample back to original number of training rows
            PhaseSlopes     = regressor.GetPhaseSlopes().ToDictionary(slopes => slopes.Key, slopes => StandardizationHelpers.Resample(slopes.Value, trainingRowCount));

            return(this as P);
        }
예제 #4
0
        protected override List <Tuple <double, double[]> > GetTransformedRows(ISample sample, int[] columns)
        {
            if (!sample.GetDuration().HasValue)
            {
                throw new ArgumentException("Sample does not have duration");
            }
            // find the dtw path between the sample and template for each column, use it to get the slopes mapping, then apply the amplitude/phase transformation for each feature
            var pathsToTemplates = Templates.Where(template => columns.Contains(template.Key)).Select(template => new { column = template.Key, pathToTemplate = FindDTWPath(template.Value, sample.GetDataRows(template.Key), bandwidth).Select(s => s.Item2).ToArray() });

            Dictionary <int, double[]> dtwAmplitudeSlopes = pathsToTemplates.Select(path => new { path.column, slopes = DynamicTimeWarping.GenerateFlatPath(path.pathToTemplate, StandardizationHelpers.Resample(AmplitudeSlopes[path.column], path.pathToTemplate.Length)) })
                                                            .ToDictionary(path => path.column, path => path.slopes);

            Dictionary <int, double[]> dtwPhaseSlopes = pathsToTemplates.Select(path => new { path.column, slopes = DynamicTimeWarping.GenerateFlatPath(path.pathToTemplate, StandardizationHelpers.Resample(AmplitudeSlopes[path.column], path.pathToTemplate.Length)) })
                                                        .ToDictionary(path => path.column, path => path.slopes);

            // create amplitude warping
            var amplitudeWarp = dtwAmplitudeSlopes.Select(amplitude => new { column = amplitude.Key, amplitudeWarp = sample.GetDataRows(amplitude.Key).Select((value, j) => value + dtwAmplitudeSlopes[amplitude.Key][j] * (standardTime - sample.GetDuration().Value)) });

            // create phase warping
            Dictionary <int, double[]> phaseWarp = dtwPhaseSlopes.Select(phase => new { column = phase.Key, phaseWarp = StandardizationHelpers.GenerateL1NormalizedValues(sample.GetDataRows().Select((data, i) => phase.Value[i] * (standardTime - sample.GetDuration().Value)).ToArray()) })
                                                   .ToDictionary(warp => warp.column, warp => warp.phaseWarp);

            // get phase warping average
            Dictionary <int, double> phaseWarpAverage = phaseWarp.ToDictionary(warp => warp.Key, warp => warp.Value.Average());

            // normalize the phase warp to have a mean value of 1 then multiply it by the respective amplitude slopes to scale the phase accordingly
            double amplitudeSum = amplitudeWarp.SelectMany(warp => warp.amplitudeWarp).Sum(); // TODO - make this configurable so can be disabled for performance

            Dictionary <int, double[]> phaseAmplitudeWarp = amplitudeWarp.Select(warp => new { warp.column, phaseWarped = warp.amplitudeWarp.Select((value, j) => value * (phaseWarp[warp.column][j] - phaseWarpAverage[warp.column] + 1)).ToArray() })
                                                            .ToDictionary(warp => warp.column, warp => warp.phaseWarped);

            double phaseSum = phaseAmplitudeWarp.SelectMany(warp => warp.Value).Sum(); // TODO - make this configurable so can be disabled for performance

            // warn if difference is beyond tolerance (TODO - make configurable)
            if (Math.Abs(amplitudeSum - phaseSum) > (Math.Abs(amplitudeSum) * 0.05))
            {
                Console.WriteLine("Potentially weak phase normalization. Amplitude Norm Sum: " + amplitudeSum + ", Phase Norm Sum: " + phaseSum);
            }

            // NOTE - the lambda expression references an outer variable - this will be stored in the lambda and not garbaged collected until the lambda is (see Variable Scope in Lambda Expressions)
            return(TransformData(sample, (interval, i) => i * (standardTime / sample.GetDataRows().Count), (value, i, j) => phaseAmplitudeWarp[j][i], columns));
        }
예제 #5
0
 protected static double FindDTWCost(double[] d1, double[] d2, double bandwidth)
 {
     // normalize each signal to the same height to ensure transformation only affects phase of the signals
     return(DynamicTimeWarping.FindDTWCost(StandardizationHelpers.GenerateLinfNormalizedValues(d1), StandardizationHelpers.GenerateLinfNormalizedValues(d2), bandwidth));
 }
예제 #6
0
 protected static List <Tuple <int, int> > FindDTWPath(double[] template, double[] sample, double bandwidth)
 {
     // normalize each signal to the same height to ensure transformation only affects phase of the signals
     return(DynamicTimeWarping.FindDTWPath(StandardizationHelpers.GenerateLinfNormalizedValues(template), StandardizationHelpers.GenerateLinfNormalizedValues(sample), bandwidth));
 }