/// <summary> /// Computes the variable importance in projection (VIP) /// </summary> /// <returns> /// A predictors x factors matrix in which each row represents /// the importance of the variable in a projection considering /// the number of factors indicated by the column. /// </returns> /// <remarks> /// References: /// - http://mevik.net/work/software/VIP.R /// - http://www.postech.ac.kr/~chjun/publication/Chemometrics/chemo05.pdf /// </remarks> protected double[,] ComputeVariableImportanceInProjection(int factors) { int xcols = sourceX.GetLength(1); double[,] importance = new double[xcols, factors]; // For each input variable for (int j = 0; j < xcols; j++) { double[] SS1 = new double[factors]; double[] SS2 = new double[factors]; // For each latent factor for (int k = 0; k < factors; k++) { // Assume single response variable var b = loadingsY.GetColumn(k)[0]; var t = scoresX.GetColumn(k); var w = loadingsX.GetColumn(k); var ss = (b * b) * (t.InnerProduct(t)); var wn = (w[j] * w[j]) / Norm.SquareEuclidean(w); SS1[k] = ss * wn; SS2[k] = ss; } var sum1 = Matrix.CumulativeSum(SS1); var sum2 = Matrix.CumulativeSum(SS2); for (int k = 0; k < factors; k++) { importance[j, k] = System.Math.Sqrt(xcols * sum1[k] / sum2[k]); } } return(importance); // Matricial form (possibly more efficient) solution /* * var SS = loadingsY.ElementwisePower(2).GetRow(0) * .ElementwiseMultiply(scoresX.ElementwisePower(2).Sum(1)); * * var loadingsX2 = loadingsX.ElementwisePower(2); * * var Wnorm2 = loadingsX2.Sum(1); * * var SSW = loadingsX2.ElementwiseMultiply(SS.ElementwiseDivide(Wnorm2), 1); * * var division = SSW.CumulativeSum(0).ToMatrix() * .ElementwiseDivide(SS.CumulativeSum(), 0); * * this.vip = Matrix.Sqrt(division.Multiply(SSW.GetLength(0))).Transpose(); */ }
/// <summary> /// Gets the Euclidean norm for a matrix. /// </summary> /// public static float[] Euclidean(this float[,] a, int dimension) { float[] norm = Norm.SquareEuclidean(a, dimension); for (int i = 0; i < norm.Length; i++) { norm[i] = (float)System.Math.Sqrt(norm[i]); } return(norm); }
/// <summary> /// Gets the Euclidean norm for a matrix. /// </summary> /// public static double[] Euclidean(this double[,] a, int dimension) { double[] norm = Norm.SquareEuclidean(a, dimension); for (int i = 0; i < norm.Length; i++) { norm[i] = System.Math.Sqrt(norm[i]); } return(norm); }
/// <summary> /// Calculate the Procrustes Distance between two sets of data /// </summary> /// <param name="samples1">First data set</param> /// <param name="samples2">Second data set</param> /// <returns>The Procrustes distance</returns> double ProcrustesDistance(double[,] samples1, double[,] samples2) { double sum = 0; // Only calculate the distance for the maximal common number of points (i.e. the Min between samples1 and samples2 number of points) for (int i = 0; i < System.Math.Min(samples1.GetLength(0), samples2.GetLength(0)); i++) { sum += Norm.SquareEuclidean(samples1.GetRow(i).Subtract(samples2.GetRow(i))); } return(System.Math.Sqrt(sum)); }
/// <summary> /// Estimates suitable values for the sigmoid kernel /// by exploring the response area of the tanh function. /// </summary> /// /// <param name="inputs">An input data set.</param> /// /// <returns>A Sigmoid kernel initialized with appropriate values.</returns> /// public static Sigmoid Estimate(double[][] inputs) { double[] norm = new double[inputs.Length]; for (int i = 0; i < inputs.Length; i++) { norm[i] = Norm.SquareEuclidean(inputs[i]); } double max = Matrix.Max(norm); double r = -Math.E; double a = -r / max; return(new Sigmoid(a, r)); }
/// <summary> /// Projects an input point into feature space. /// </summary> /// /// <param name="input">The input point to be projected into feature space.</param> /// /// <returns> /// The feature space representation of the given <paramref name="input"/> point. /// </returns> /// public double[] Transform(double[] input) { // http://epubs.siam.org/doi/pdf/10.1137/1.9781611972818.19 double[] features = new double[coefficients.Length]; features[0] = 1; for (int index = 1, k = 0; index < coefficients.Length; k++) { double alpha = coefficients[k]; foreach (int[] s in Combinatorics.Sequences(input.Length, k + 1)) { double prod = 1.0; for (int i = 0; i < s.Length; i++) { prod *= input[s[i]]; } features[index++] = alpha * prod; if (index >= coefficients.Length) { break; } } } double norm = Norm.SquareEuclidean(input); double constant = Math.Exp(-gaussian.Gamma * norm); for (int i = 0; i < features.Length; i++) { features[i] *= constant; } return(features); }