public void GammaSigmaTest() { var dtw = new DynamicTimeWarping(1); var gaussian = new Gaussian <DynamicTimeWarping>(dtw, 1); double expected, actual, gamma, sigma; expected = 0.01; gaussian.Sigma = expected; gamma = gaussian.Gamma; gaussian.Gamma = gamma; actual = gaussian.Sigma; Assert.AreEqual(expected, actual); expected = 0.01; gaussian.Gamma = expected; sigma = gaussian.Sigma; gaussian.Sigma = sigma; actual = gaussian.Gamma; Assert.AreEqual(expected, actual, 1e-12); }
public void DynamicalTimeWarpingConstructorTest2() { // Declare some testing data double[][] inputs = { // Class -1 new double[] { 0, 1, 1, 0 }, new double[] { 0, 0, 1, 0 }, new double[] { 0, 1, 1,1, 0 }, new double[] { 0, 1,0 }, // Class +1 new double[] { 1, 0, 0, 1 }, new double[] { 1, 1, 0, 1 }, new double[] { 1, 0, 0,0, 1 }, new double[] { 1, 0,1 }, new double[] { 1, 0, 0,0, 1, 1 } }; int[] outputs = { -1, -1, -1,-1, // First four sequences are of class -1 1, 1, 1,1, 1 // Last five sequences are of class +1 }; // Set the parameters of the kernel double alpha = 1.0; int degree = 1; int innerVectorLength = 1; // Create the kernel. Note that the input vector will be given out automatically DynamicTimeWarping target = new DynamicTimeWarping(innerVectorLength, alpha, degree); // When using variable-length kernels, specify 0 as the input length. KernelSupportVectorMachine svm = new KernelSupportVectorMachine(target, 0); // Create the Sequential Minimal Optimization as usual SequentialMinimalOptimization smo = new SequentialMinimalOptimization(svm, inputs, outputs); smo.Complexity = 1.5; double error = smo.Run(); // Check if the model has learnt the sequences correctly. for (int i = 0; i < inputs.Length; i++) { int expected = outputs[i]; int actual = System.Math.Sign(svm.Compute(inputs[i])); Assert.AreEqual(expected, actual); } // Testing new sequences Assert.AreEqual(-1, System.Math.Sign(svm.Compute(new double[] { 0, 1, 1, 0, 0 }))); Assert.AreEqual(+1, System.Math.Sign(svm.Compute(new double[] { 1, 1, 0, 0, 1, 1 }))); }
public void generic_test() { var x = new int[] { 0, 4, 2, 1 }; var y = new int[] { 3, 2, }; double expected, actual; var target = new DynamicTimeWarping <Dirac <int>, int>(); expected = 1; actual = target.Function(x, x); Assert.AreEqual(expected, actual, 1e-6); expected = 1; actual = target.Function(y, y); Assert.AreEqual(expected, actual, 1e-6); expected = 1; actual = target.Function(x, y); Assert.AreEqual(expected, actual, 1e-6); actual = target.Function(y, x); Assert.AreEqual(expected, actual, 1e-6); target = new DynamicTimeWarping <Dirac <int>, int>(sigma: 1.42); var z = new int[] { 3, 2, 1, 5, 7, 8 }; expected = 1; actual = target.Function(x, x); Assert.AreEqual(expected, actual, 1e-6); expected = 1; actual = target.Function(y, y); Assert.AreEqual(expected, actual, 1e-6); expected = 1; actual = target.Function(z, z); Assert.AreEqual(expected, actual, 1e-6); expected = 0.28943244309220884; actual = target.Function(x, z); Assert.AreEqual(expected, actual, 1e-6); actual = target.Function(z, x); Assert.AreEqual(expected, actual, 1e-6); expected = 0.475256785561611; actual = target.Function(x, y); Assert.AreEqual(expected, actual, 1e-6); actual = target.Function(y, x); Assert.AreEqual(expected, actual, 1e-6); }
public void FunctionTest_EqualInputs() { var x = new double[] { 1, 2, 5, 1 }; var y = new double[] { 1, 2, 5, 1 }; var target = new DynamicTimeWarping(1, 4.2); double expected = target.Function(x, y); double actual = target.Function(x, x); Assert.AreEqual(expected, actual); }
public void GaussianEstimateTest() { // Suppose we have the following data // double[][] data = { new double[] { 5.1, 3.5, 1.4, 0.2 }, new double[] { 5.0, 3.6, 1.4, 0.2 }, new double[] { 4.9, 3.0, 1.4, 0.2 }, new double[] { 5.8, 4.0, 1.2, 0.2 }, new double[] { 4.7, 3.2, 1.3, 0.2 }, }; // Estimate an appropriate sigma from data var dtw = new DynamicTimeWarping(1); var kernel = Gaussian.Estimate(dtw, data); double sigma = kernel.Sigma; double sigma2 = kernel.SigmaSquared; Assert.AreEqual(0.044282096049367413, sigma); Assert.AreEqual(sigma * sigma, sigma2); }
public void GaussianFunctionTest() { var x = new double[] { 0, 4, 2, 1 }; var y = new double[] { 3, 2, }; var dtw = new DynamicTimeWarping(1); IKernel gaussian = new Gaussian <DynamicTimeWarping>(dtw, 1); double actual = gaussian.Function(x, y); Assert.AreEqual(0.3407192298459587, actual); gaussian = new Gaussian <DynamicTimeWarping>(dtw, 11.5); x = new double[] { 0.2, 5 }; y = new double[] { 3, 0.7 }; actual = gaussian.Function(x, y); Assert.AreEqual(0.99065918303292089, actual); }
public void GammaSigmaSquaredTest() { var dtw = new DynamicTimeWarping(1); var gaussian = new Gaussian <DynamicTimeWarping>(dtw, 3.6); Assert.AreEqual(3.6 * 3.6, gaussian.SigmaSquared); Assert.AreEqual(3.6, gaussian.Sigma); Assert.AreEqual(1.0 / (2 * 3.6 * 3.6), gaussian.Gamma); gaussian.SigmaSquared = 81; Assert.AreEqual(81, gaussian.SigmaSquared); Assert.AreEqual(9, gaussian.Sigma); Assert.AreEqual(1.0 / (2 * 81), gaussian.Gamma); gaussian.Sigma = 6; Assert.AreEqual(36, gaussian.SigmaSquared); Assert.AreEqual(6, gaussian.Sigma); Assert.AreEqual(1.0 / (2 * 36), gaussian.Gamma); gaussian.Gamma = 1.0 / (2 * 49); Assert.AreEqual(49, gaussian.SigmaSquared, 1e-10); Assert.AreEqual(7, gaussian.Sigma, 1e-10); Assert.AreEqual(1.0 / (2 * 49), gaussian.Gamma); }
public void DynamicalTimeWarpingConstructorTest() { double[][] sequences = { new double[] // -1 { 0, 0, 0, 1, 1, 1, 2, 2, 2, }, new double[] // -1 { 0, 1, 0, 0, 2, 0, 0, 3, 0 }, new double[] // +1 { 1, 1, 0, 1, 2, 0, 2, 1, 0, }, new double[] // +1 { 0, 0, 1, 0, 0, 2, 0, 1, 3, }, }; int[] outputs = { -1, -1, +1, +1 }; // Set the parameters of the kernel double alpha = 0.85; int innerVectorLength = 3; // Create the kernel. Note that the input vector will be given out automatically DynamicTimeWarping target = new DynamicTimeWarping(innerVectorLength, alpha); // When using variable-length kernels, specify 0 as the input length. KernelSupportVectorMachine svm = new KernelSupportVectorMachine(target, 0); // Create the Sequential Minimal Optimization as usual SequentialMinimalOptimization smo = new SequentialMinimalOptimization(svm, sequences, outputs); smo.Complexity = 1.5; double error = smo.Run(); // Computing the training values var a0 = svm.Compute(sequences[0]); var a1 = svm.Compute(sequences[1]); var a2 = svm.Compute(sequences[2]); var a3 = svm.Compute(sequences[3]); Assert.AreEqual(-1, System.Math.Sign(a0)); Assert.AreEqual(-1, System.Math.Sign(a1)); Assert.AreEqual(+1, System.Math.Sign(a2)); Assert.AreEqual(+1, System.Math.Sign(a3)); // Computing a new testing value double[] test = { 1, 0, 1, 0, 0, 2, 0, 1, 3, }; var a4 = svm.Compute(test); }
public void DynamicalTimeWarpingConstructorTest3() { // Suppose you have sequences of multivariate observations, and that // those sequences could be of arbitrary length. On the other hand, // each observation have a fixed, delimited number of dimensions. // In this example, we have sequences of 3-dimensional observations. // Each sequence can have an arbitrary length, but each observation // will always have length 3: double[][][] sequences = { new double[][] // first sequence { new double[] { 1, 1, 1 }, // first observation of the first sequence new double[] { 1, 2, 1 }, // second observation of the first sequence new double[] { 1, 4, 2 }, // third observation of the first sequence new double[] { 2, 2, 2 }, // fourth observation of the first sequence }, new double[][] // second sequence (note that this sequence has a different length) { new double[] { 1, 1, 1 }, // first observation of the second sequence new double[] { 1, 5, 6 }, // second observation of the second sequence new double[] { 2, 7, 1 }, // third observation of the second sequence }, new double[][] // third sequence { new double[] { 8, 2, 1 }, // first observation of the third sequence }, new double[][] // fourth sequence { new double[] { 8, 2, 5 }, // first observation of the fourth sequence new double[] { 1, 5, 4 }, // second observation of the fourth sequence } }; // Now, we will also have different class labels associated which each // sequence. We will assign -1 to sequences whose observations start // with { 1, 1, 1 } and +1 to those that do not: int[] outputs = { -1, -1, // First two sequences are of class -1 (those start with {1,1,1}) 1, 1, // Last two sequences are of class +1 (don't start with {1,1,1}) }; // At this point, we will have to "flat" out the input sequences from double[][][] // to a double[][] so they can be properly understood by the SVMs. The problem is // that, normally, SVMs usually expect the data to be comprised of fixed-length // input vectors and associated class labels. But in this case, we will be feeding // them arbitrary-length sequences of input vectors and class labels associated with // each sequence, instead of each vector. double[][] inputs = new double[sequences.Length][]; for (int i = 0; i < sequences.Length; i++) { inputs[i] = Matrix.Concatenate(sequences[i]); } // Now we have to setup the Dynamic Time Warping kernel. We will have to // inform the length of the fixed-length observations contained in each // arbitrary-length sequence: // DynamicTimeWarping kernel = new DynamicTimeWarping(length: 3); // Now we can create the machine. When using variable-length // kernels, we will need to pass zero as the input length: var svm = new KernelSupportVectorMachine(kernel, inputs: 0); // Create the Sequential Minimal Optimization learning algorithm var smo = new SequentialMinimalOptimization(svm, inputs, outputs) { Complexity = 1.5 }; // And start learning it! double error = smo.Run(); // error will be 0.0 // At this point, we should have obtained an useful machine. Let's // see if it can understand a few examples it hasn't seem before: double[][] a = { new double[] { 1, 1, 1 }, new double[] { 7, 2, 5 }, new double[] { 2, 5, 1 }, }; double[][] b = { new double[] { 7, 5, 2 }, new double[] { 4, 2, 5 }, new double[] { 1, 1, 1 }, }; // Following the aforementioned logic, sequence (a) should be // classified as -1, and sequence (b) should be classified as +1. int resultA = System.Math.Sign(svm.Compute(Matrix.Concatenate(a))); // -1 int resultB = System.Math.Sign(svm.Compute(Matrix.Concatenate(b))); // +1 Assert.AreEqual(0, error); Assert.AreEqual(-1, resultA); Assert.AreEqual(+1, resultB); }
public void FunctionTest() { var x = new double[] { 0, 4, 2, 1 }; var y = new double[] { 3, 2, }; DynamicTimeWarping target; double expected, actual; target = new DynamicTimeWarping(1); expected = 1; actual = target.Function(x, x); Assert.AreEqual(expected, actual, 1e-5); expected = 1; actual = target.Function(y, y); Assert.AreEqual(expected, actual, 1e-5); expected = -0.076696513742007991; actual = target.Function(x, y); Assert.AreEqual(expected, actual, 1e-5); actual = target.Function(y, x); Assert.AreEqual(expected, actual, 1e-5); target = new DynamicTimeWarping(2, 1.42); var z = new double[] { 3, 2, 1, 5, 7, 8 }; expected = 1; actual = target.Function(x, x); Assert.AreEqual(expected, actual, 1e-5); expected = 1; actual = target.Function(y, y); Assert.AreEqual(expected, actual, 1e-5); expected = 1; actual = target.Function(z, z); Assert.AreEqual(expected, actual, 1e-5); expected = -0.10903562560104614; actual = target.Function(x, z); Assert.AreEqual(expected, actual, 1e-5); actual = target.Function(z, x); Assert.AreEqual(expected, actual, 1e-5); expected = 0.4208878392918925; actual = target.Function(x, y); Assert.AreEqual(expected, actual, 1e-5); actual = target.Function(y, x); Assert.AreEqual(expected, actual, 1e-5); target = new DynamicTimeWarping(1, 1e-5); expected = 1; actual = target.Function(x, x); Assert.AreEqual(expected, actual); expected = 1; actual = target.Function(y, y); Assert.AreEqual(expected, actual); expected = 0.000000000033333397321663391; actual = target.Function(x, y); Assert.AreEqual(expected, actual, 1e-5); actual = target.Function(y, x); Assert.AreEqual(expected, actual, 1e-5); target = new DynamicTimeWarping(1, 292.12); expected = 1; actual = target.Function(x, x); Assert.AreEqual(expected, actual, 1e-10); actual = target.Function(y, y); Assert.AreEqual(expected, actual, 1e-10); expected = 0.99985353675500488; actual = target.Function(x, y); Assert.AreEqual(expected, actual, 1e-10); actual = target.Function(y, x); Assert.AreEqual(expected, actual, 1e-10); }
public void DistanceTest() { var x = new double[] { 0, 4, 2, 1 }; var y = new double[] { 3, 2, }; DynamicTimeWarping target; double expected, actual; target = new DynamicTimeWarping(1); expected = 0; actual = target.Distance(x, x); Assert.AreEqual(expected, actual, 0); expected = 0; actual = target.Distance(y, y); Assert.AreEqual(expected, actual, 0); expected = 2.1533930274840158; actual = target.Distance(x, y); Assert.AreEqual(expected, actual); actual = target.Distance(y, x); Assert.AreEqual(expected, actual); target = new DynamicTimeWarping(2, 1.42); var z = new double[] { 3, 2, 1, 5, 7, 8 }; expected = 0; actual = target.Distance(x, x); Assert.AreEqual(expected, actual); expected = 0; actual = target.Distance(y, y); Assert.AreEqual(expected, actual); expected = 0; actual = target.Distance(z, z); Assert.AreEqual(expected, actual); expected = 2.2180712512020921; actual = target.Distance(x, z); Assert.AreEqual(expected, actual); actual = target.Distance(z, x); Assert.AreEqual(expected, actual); expected = 1.1582243214162151; actual = target.Distance(x, y); Assert.AreEqual(expected, actual); actual = target.Distance(y, x); Assert.AreEqual(expected, actual); target = new DynamicTimeWarping(1, 0.0000000001); expected = 0; actual = target.Distance(x, x); Assert.AreEqual(expected, actual); expected = 0; actual = target.Distance(y, y); Assert.AreEqual(expected, actual); expected = 1.9999999999333331; actual = target.Distance(x, y); Assert.AreEqual(expected, actual); actual = target.Distance(y, x); Assert.AreEqual(expected, actual); target = new DynamicTimeWarping(1, 292.12); expected = 0; actual = target.Distance(x, x); Assert.AreEqual(expected, actual); actual = target.Distance(y, y); Assert.AreEqual(expected, actual); expected = 0.00029292648999024173; actual = target.Distance(x, y); Assert.AreEqual(expected, actual); actual = target.Distance(y, x); Assert.AreEqual(expected, actual); }
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)); }
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)); }
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)); }