/// <summary> /// Gets the Square Mahalanobis distance between two points. /// </summary> /// /// <param name="x">A point in space.</param> /// <param name="y">A point in space.</param> /// <param name="covariance"> /// The <see cref="SingularValueDecomposition"/> of the covariance /// matrix of the distribution for the two points x and y. /// </param> /// /// <returns>The Square Mahalanobis distance between x and y.</returns> /// public static double SquareMahalanobis(this double[] x, double[] y, SingularValueDecomposition covariance) { double[] d = new double[x.Length]; for (int i = 0; i < x.Length; i++) d[i] = x[i] - y[i]; double[] z = covariance.Solve(d); double r = 0.0; for (int i = 0; i < d.Length; i++) r += d[i] * z[i]; return Math.Abs(r); }
public void InverseTest() { double[,] value = new double[,] { { 1.0, 1.0 }, { 2.0, 2.0 } }; SingularValueDecomposition target = new SingularValueDecomposition(value); double[,] expected = new double[,] { { 0.1, 0.2 }, { 0.1, 0.2 } }; double[,] actual = target.Solve(Matrix.Identity(2)); Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); actual = target.Inverse(); Assert.IsTrue(Matrix.IsEqual(expected, actual, 0.001)); }
public void InverseTest2() { int n = 5; var I = Matrix.Identity(n); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { double[,] value = Matrix.Magic(n); var target = new SingularValueDecomposition(value); double[,] solution = target.Solve(I); double[,] inverse = target.Inverse(); double[,] reverse = target.Reverse(); Assert.IsTrue(Matrix.IsEqual(solution, inverse, 1e-4)); Assert.IsTrue(Matrix.IsEqual(value, reverse, 1e-4)); } } }
public void MahalanobisTest3() { // Example from Statistical Distance Calculator // http://maplepark.com/~drf5n/cgi-bin/dist.cgi double[,] cov = { { 1.030303, 2.132728, 0.576716 }, { 2.132728, 4.510515, 1.185771 }, { 0.576716, 1.185771, 0.398922 } }; double[] x, y; double actual, expected; var svd = new SingularValueDecomposition(cov, true, true, true); var inv = cov.Inverse(); var pinv = svd.Inverse(); Assert.IsTrue(inv.IsEqual(pinv, 1e-6)); x = new double[] { 2, 4, 1 }; y = new double[] { 0, 0, 0 }; { var bla = cov.Solve(x); var blo = svd.Solve(x); var ble = inv.Multiply(x); var bli = pinv.Multiply(x); Assert.IsTrue(bla.IsEqual(blo, 1e-6)); Assert.IsTrue(bla.IsEqual(ble, 1e-6)); Assert.IsTrue(bla.IsEqual(bli, 1e-6)); } expected = 2.0773536867741504; actual = Distance.Mahalanobis(x, y, inv); Assert.AreEqual(expected, actual, 1e-6); actual = Distance.Mahalanobis(x, y, svd); Assert.AreEqual(expected, actual, 1e-6); x = new double[] { 7, 5, 1 }; y = new double[] { 1, 0.52, -79 }; expected = 277.8828871106366; actual = Distance.Mahalanobis(x, y, inv); Assert.AreEqual(expected, actual, 1e-5); actual = Distance.Mahalanobis(x, y, svd); Assert.AreEqual(expected, actual, 1e-5); }
public void SingularValueDecompositionConstructorTest7() { int count = 100; double[,] value = new double[count, 3]; double[] output = new double[count]; for (int i = 0; i < count; i++) { double x = i + 1; double y = 2 * (i + 1) - 1; value[i, 0] = x; value[i, 1] = y; value[i, 2] = 1; output[i] = 4 * x - y + 3; } SingularValueDecomposition target = new SingularValueDecomposition(value, computeLeftSingularVectors: true, computeRightSingularVectors: true); { double[,] expected = value; double[,] actual = target.LeftSingularVectors.Multiply( Matrix.Diagonal(target.Diagonal)).Multiply(target.RightSingularVectors.Transpose()); // Checking the decomposition Assert.IsTrue(Matrix.IsEqual(actual, expected, 1e-8)); } { double[] solution = target.Solve(output); double[] expected= output; double[] actual = value.Multiply(solution); Assert.IsTrue(Matrix.IsEqual(actual, expected, 1e-8)); } }
/// <summary> /// Attempts to find the best values for the parameter vector /// minimizing the discrepancy between the generated outputs /// and the expected outputs for a given set of input data. /// </summary> /// /// <param name="inputs">A set of input data.</param> /// <param name="outputs">The values associated with each /// vector in the <paramref name="inputs"/> data.</param> /// public double Minimize(double[][] inputs, double[] outputs) { Array.Clear(hessian, 0, hessian.Length); Array.Clear(gradient, 0, gradient.Length); errors = new double[inputs.Length]; jacobian = new double[inputs.Length, numberOfParameters]; for (int i = 0; i < inputs.Length; i++) errors[i] = outputs[i] - Function(weights, inputs[i]); double[] g = new double[numberOfParameters]; for (int i = 0; i < inputs.Length; i++) { Gradient(weights, inputs[i], result: g); for (int j = 0; j < gradient.Length; j++) jacobian[i, j] = -g[j]; } // Compute error gradient using Jacobian jacobian.TransposeAndMultiply(errors, result: gradient); // Compute Quasi-Hessian Matrix approximation jacobian.TransposeAndMultiply(jacobian, result: hessian); decomposition = new SingularValueDecomposition(hessian, computeLeftSingularVectors: true, computeRightSingularVectors: true, autoTranspose: true); deltas = decomposition.Solve(gradient); for (int i = 0; i < deltas.Length; i++) weights[i] -= deltas[i]; return ComputeError(inputs, outputs); }