public void Transform_SimpleExample_ReturnsExpectedOutput() { var m = new Matrix(new[] { new [] { 2d, 4d}, new [] { 1d, 3d}, new [] { 0d, 0d}, new [] { 0d, 0d} }); var svd = new SingularValueDecomposition(); var t = svd.Transform(m); }
private double regress(double[][] inputs, double[] outputs, out double[,] designMatrix, bool robust) { if (inputs.Length != outputs.Length) { throw new ArgumentException("Number of input and output samples does not match", "outputs"); } int rows = inputs.Length; // number of instance points int cols = inputs[0].Length; // dimension of each point NumberOfInputs = cols; ISolverMatrixDecomposition <double> solver; // Create the problem's design matrix. If we // have to add an intercept term, add a new // extra column at the end and fill with 1s. if (!addIntercept) { // Just copy values over designMatrix = new double[rows, cols]; for (int i = 0; i < inputs.Length; i++) { for (int j = 0; j < inputs[i].Length; j++) { designMatrix[i, j] = inputs[i][j]; } } } else { // Add an intercept term designMatrix = new double[rows, cols + 1]; for (int i = 0; i < inputs.Length; i++) { for (int j = 0; j < inputs[i].Length; j++) { designMatrix[i, j] = inputs[i][j]; } designMatrix[i, cols] = 1; } } // Check if we have an overdetermined or underdetermined // system to select an appropriate matrix solver method. if (robust || cols >= rows) { // We have more variables than equations, an // underdetermined system. Solve using a SVD: solver = new SingularValueDecomposition(designMatrix, computeLeftSingularVectors: true, computeRightSingularVectors: true, autoTranspose: true); } else { // We have more equations than variables, an // overdetermined system. Solve using the QR: solver = new QrDecomposition(designMatrix); } // Solve V*C = B to find C (the coefficients) coefficients = solver.Solve(outputs); if (addIntercept) { intercept = coefficients[coefficients.Length - 1]; } // Calculate Sum-Of-Squares error double error = 0.0; double e; for (int i = 0; i < outputs.Length; i++) { e = outputs[i] - Compute(inputs[i]); error += e * e; } return(error); }
public static double[,] PseudoInverse(this double[,] m) { SingularValueDecomposition svd = new SingularValueDecomposition(m); return(svd.Solve(Matrix.Diagonal(m.GetLength(0), m.GetLength(1), 1.0))); }
/// <summary> /// Parallel (symmetric) iterative algorithm. /// </summary> /// /// <returns> /// Returns a matrix in which each row contains /// the mixing coefficients for each component. /// </returns> /// private double[,] parallel(double[,] X, int components, double[,] winit) { // References: // - Hyvärinen, A (1999). Fast and Robust Fixed-Point // Algorithms for Independent Component Analysis. // There are two ways to apply the fixed-unit algorithm to compute the whole // ICA iteration. The second approach is to perform orthogonalization at once // using an Eigendecomposition [Hyvärinen]. The Eigendecomposition can in turn // be converted to a more stable singular value decomposition and be used to // create a projection basis in the same way as in Principal Component Analysis. int n = X.GetLength(0); int m = X.GetLength(1); // Algorithm initialization double[,] W0 = winit; double[,] W = winit; double[,] K = new double[components, components]; bool stop = false; int iterations = 0; double lastChange = 1; do // until convergence { // [Hyvärinen, 1997]'s paper suggests the use of the Eigendecomposition // to orthogonalize W (after equation 10). However, [E, D] = eig(W'W) // can be replaced by [U, S] = svd(W), which is more stable and avoids // computing W'W. Since the singular values are already the square roots // of the eigenvalues of W'W, the computation of E'*D^(-1/2)*E' reduces // to U*S^(-1)*U'. // Perform simultaneous decorrelation of all components at once var svd = new SingularValueDecomposition(W, computeLeftSingularVectors: true, computeRightSingularVectors: false, autoTranspose: true); double[] S = svd.Diagonal; double[,] U = svd.LeftSingularVectors; // Form orthogonal projection basis K for (int i = 0; i < components; i++) { for (int j = 0; j < components; j++) { double s = 0; for (int k = 0; k < S.Length; k++) { if (S[k] != 0.0) { s += U[i, k] * U[j, k] / S[k]; } } K[i, j] = s; } } // Orthogonalize W = K.Multiply(W); // Gets the maximum parameter absolute change double delta = getMaximumAbsoluteChange(W0, W); // Check for convergence if (delta < tolerance * lastChange || iterations >= maxIterations) { stop = true; } else { // Advance to the next iteration W0 = W; W = new double[components, m]; lastChange = delta; iterations++; // For each component (in parallel) global::Accord.Threading.Tasks.Parallel.For(0, components, i => { double[] wx = new double[n]; double[] dgwx = new double[n]; double[] gwx = new double[n]; double[] means = new double[m]; // Compute wx = w*x for (int j = 0; j < wx.Length; j++) { double s = 0; for (int k = 0; k < m; k++) { s += W0[i, k] * X[j, k]; } wx[j] = s; } // Compute g(wx) and g'(wx) contrast.Evaluate(wx, gwx, dgwx); // Compute E{ x*g(w*x) } for (int j = 0; j < means.Length; j++) { for (int k = 0; k < gwx.Length; k++) { means[j] += X[k, j] * gwx[k]; } means[j] /= n; } // Compute E{ g'(w*x) } double mean = Statistics.Tools.Mean(dgwx); // Compute next update for w according // to Hyvärinen paper's equation (20). // w+ = E{ xg(w*x)} - E{ g'(w*x)}*w for (int j = 0; j < means.Length; j++) { W[i, j] = means[j] - mean * W0[i, j]; } // The normalization to w* will be performed // in the beginning of the next iteration. }); } } while (!stop); // Return the component basis matrix return(W); // vectors stored as rows. }
/// <summary> /// Performs the regression using the input vectors and output /// vectors, returning the sum of squared errors of the fit. /// </summary> /// /// <param name="inputs">The input vectors to be used in the regression.</param> /// <param name="outputs">The output values for each input vector.</param> /// <returns>The Sum-Of-Squares error of the regression.</returns> /// public virtual double Regress(double[][] inputs, double[][] outputs) { if (inputs.Length != outputs.Length) { throw new ArgumentException("Number of input and output samples does not match", "outputs"); } int cols = inputs[0].Length; // inputs int rows = inputs.Length; // points if (insertConstant) { cols++; } for (int c = 0; c < coefficients.GetLength(1); c++) { double[] B = new double[cols]; double[,] V = new double[cols, cols]; // Compute V and B matrices for (int i = 0; i < cols; i++) { // Least Squares Matrix for (int j = 0; j < cols; j++) { for (int k = 0; k < rows; k++) { if (insertConstant) { double a = (i == cols - 1) ? 1 : inputs[k][i]; double b = (j == cols - 1) ? 1 : inputs[k][j]; V[i, j] += a * b; } else { V[i, j] += inputs[k][i] * inputs[k][j]; } } } // Function to minimize for (int k = 0; k < rows; k++) { if (insertConstant && (i == cols - 1)) { B[i] += outputs[k][c]; } else { B[i] += inputs[k][i] * outputs[k][c]; } } } // Solve V*C = B to find C (the coefficients) double[] coef = new SingularValueDecomposition(V).Solve(B); if (insertConstant) { intercepts[c] = coef[coef.Length - 1]; for (int i = 0; i < cols - 1; i++) { coefficients[i, c] = coef[i]; } } else { for (int i = 0; i < cols; i++) { coefficients[i, c] = coef[i]; } } } // Calculate Sum-Of-Squares error double error = 0.0, e; for (int i = 0; i < outputs.Length; i++) { double[] y = Compute(inputs[i]); for (int c = 0; c < y.Length; c++) { e = outputs[i][c] - y[c]; error += e * e; } } return(error); }
// decompositions #region svd protected double[] svd(double[,] m) { var svd = new SingularValueDecomposition(m, false, false, true); return(svd.Diagonal); }
/// <summary> /// Calculates the pseudo inverse of the matrix <c>input</c> by means of singular value decomposition. /// A relative value of <c>100*DBL_EPSILON</c> is used to chop the singular values before calculation. /// </summary> /// <param name="input">Input matrix</param> /// <param name="rank">Returns the rank of the input matrix.</param> /// <returns>The pseudo inverse of matrix <c>input</c>.</returns> public static IMatrix PseudoInverse(IROMatrix input, out int rank) { MatrixMath.BEMatrix ma = new BEMatrix(input.Rows,input.Columns); MatrixMath.Copy(input,ma); SingularValueDecomposition svd = new SingularValueDecomposition(ma); double[][] B = GetMatrixArray(input.Columns,input.Rows); /* compute the pseudoinverse in B */ double[] s = svd.Diagonal; int m = input.Rows; int n = input.Columns; int minmn = Math.Min(m,n); double[][] v = svd.V; double[][] u = svd.U; double thresh = (DoubleConstants.DBL_EPSILON*100) * s[0]; for(rank=0; rank<minmn && s[rank]>thresh; rank++) { double one_over_denom=1.0/s[rank]; for(int j=0; j<m; j++) for(int i=0; i<n; i++) B[i][j]+=v[i][rank]*u[j][rank]*one_over_denom; } return new JaggedArrayMatrix(B); }
public static double SquareMahalanobis(double[] x, double[] y, SingularValueDecomposition svd) { return(new SquareMahalanobis(svd).Distance(x, y)); }
public void SingularValueDecompositionConstructorTest1() { // This test catches the bug in SingularValueDecomposition in the line // for (int j = k + 1; j < nu; j++) // where it should be // for (int j = k + 1; j < n; j++) // Test for m-x-n matrices where m < n. The available SVD // routine was not meant to be used in this case. double[,] value = new double[, ] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }.Transpose(); // value is 2x4, having less rows than columns. var target = new SingularValueDecomposition(value, true, true, false); double[,] actual = target.LeftSingularVectors.Dot( target.DiagonalMatrix).Dot(target.RightSingularVectors.Transpose()); // Checking the decomposition Assert.IsTrue(Matrix.IsEqual(actual, value, 1e-2)); Assert.IsTrue(Matrix.IsEqual(target.Reverse(), value, 1e-2)); // Checking values double[,] U = { { -0.641423027995072, -0.767187395072177 }, { -0.767187395072177, 0.641423027995072 }, }; // U should be equal Assert.IsTrue(Matrix.IsEqual(target.LeftSingularVectors, U, 0.001)); double[,] V = // economy svd { { -0.152483233310201, 0.822647472225661, }, { -0.349918371807964, 0.421375287684580, }, { -0.547353510305727, 0.0201031031435023, }, { -0.744788648803490, -0.381169081397574, }, }; var matrix = target.RightSingularVectors.Submatrix(0, 3, 0, 1); // V can be different, but for the economy SVD it is often equal Assert.IsTrue( Matrix.IsEqual(matrix, V, 0.0001)); double[,] S = { { 14.2690954992615, 0.000000000000000 }, { 0.0000000000000, 0.626828232417543 }, }; // The diagonal values should be equal Assert.IsTrue(Matrix.IsEqual(target.Diagonal.First(2), Matrix.Diagonal(S), 0.001)); }
/// <summary> /// Reverts a set of projected data into it's original form. Complete reverse /// transformation is not always possible and is not even guaranteed to exist. /// </summary> /// /// <remarks> /// <para> /// This method works using a closed-form MDS approach as suggested by /// Kwok and Tsang. It is currently a direct implementation of the algorithm /// without any kind of optimization. /// </para> /// <para> /// Reference: /// - http://cmp.felk.cvut.cz/cmp/software/stprtool/manual/kernels/preimage/list/rbfpreimg3.html /// </para> /// </remarks> /// /// <param name="data">The kpca-transformed data.</param> /// <param name="neighbors">The number of nearest neighbors to use while constructing the pre-image.</param> /// public double[,] Revert(double[,] data, int neighbors) { if (data == null) { throw new ArgumentNullException("data"); } if (sourceCentered == null) { throw new InvalidOperationException("The analysis must have been computed first."); } if (neighbors < 2) { throw new ArgumentOutOfRangeException("neighbors", "At least two neighbors are necessary."); } // Verify if the current kernel supports // distance calculation in feature space. var distance = kernel as IReverseDistance; if (distance == null) { throw new NotSupportedException( "Current kernel does not support distance calculation in feature space."); } int rows = data.GetLength(0); var result = Result; double[,] reversion = new double[rows, sourceCentered.GetLength(1)]; // number of neighbors cannot exceed the number of training vectors. int nn = System.Math.Min(neighbors, sourceCentered.GetLength(0)); // For each point to be reversed for (int p = 0; p < rows; p++) { // 1. Get the point in feature space double[] y = data.GetRow(p); // 2. Select nn nearest neighbors of the feature space double[,] X = sourceCentered; double[] d2 = new double[Result.GetLength(0)]; int[] inx = new int[Result.GetLength(0)]; // 2.1 Calculate distances for (int i = 0; i < X.GetLength(0); i++) { inx[i] = i; d2[i] = distance.ReverseDistance(y, result.GetRow(i).Submatrix(y.Length)); if (Double.IsNaN(d2[i])) { d2[i] = Double.PositiveInfinity; } } // 2.2 Order them Array.Sort(d2, inx); // 2.3 Select nn neighbors int def = 0; for (int i = 0; i < d2.Length && i < nn; i++, def++) { if (Double.IsInfinity(d2[i])) { break; } } inx = inx.Submatrix(def); X = X.Submatrix(inx).Transpose(); // X is in input space d2 = d2.Submatrix(def); // distances in input space // 3. Perform SVD // [U,L,V] = svd(X*H); // TODO: If X has more columns than rows, the SV decomposition should be // computed on the transpose of X and the left and right vectors should // be swapped. This should be fixed after more unit tests are elaborated. SingularValueDecomposition svd = new SingularValueDecomposition(X, computeLeftSingularVectors: true, computeRightSingularVectors: true, autoTranspose: false); double[,] U = svd.LeftSingularVectors; double[,] L = Matrix.Diagonal(def, svd.Diagonal); double[,] V = svd.RightSingularVectors; // 4. Compute projections // Z = L*V'; double[,] Z = L.Multiply(V.Transpose()); // 5. Calculate distances // d02 = sum(Z.^2)'; double[] d02 = Matrix.Sum(Matrix.ElementwisePower(Z, 2)); // 6. Get the pre-image using z = -0.5*inv(Z')*(d2-d02) double[,] inv = Matrix.PseudoInverse(Z.Transpose()); double[] w = (-0.5).Multiply(inv).Multiply(d2.Subtract(d02)); double[] z = w.Submatrix(U.GetLength(1)); // 8. Project the pre-image on the original basis // using x = U*z + sum(X,2)/nn; double[] x = (U.Multiply(z)).Add(Matrix.Sum(X.Transpose()).Multiply(1.0 / nn)); // 9. Store the computed pre-image. for (int i = 0; i < reversion.GetLength(1); i++) { reversion[p, i] = x[i]; } } // if the data has been standardized or centered, // we need to revert those operations as well if (this.Method == AnalysisMethod.Standardize) { // multiply by standard deviation and add the mean for (int i = 0; i < reversion.GetLength(0); i++) { for (int j = 0; j < reversion.GetLength(1); j++) { reversion[i, j] = (reversion[i, j] * StandardDeviations[j]) + Means[j]; } } } else if (this.Method == AnalysisMethod.Center) { // only add the mean for (int i = 0; i < reversion.GetLength(0); i++) { for (int j = 0; j < reversion.GetLength(1); j++) { reversion[i, j] = reversion[i, j] + Means[j]; } } } return(reversion); }
/// <summary> /// Reverts a set of projected data into it's original form. Complete reverse /// transformation is not always possible and is not even guaranteed to exist. /// </summary> /// <remarks> /// This method works using a closed-form MDS approach as suggested by /// Kwok and Tsang. It is currently a direct implementation of the algorithm /// without any kind of optimization. /// /// Reference: /// - http://cmp.felk.cvut.cz/cmp/software/stprtool/manual/kernels/preimage/list/rbfpreimg3.html /// </remarks> /// <param name="data">The kpca-transformed data.</param> /// <param name="neighbors">The number of nearest neighbors to use while constructing the pre-image.</param> public double[,] Revert(double[,] data, int neighbors) { int rows = data.GetLength(0); int cols = data.GetLength(1); double[,] reversion = new double[rows, sourceCentered.GetLength(1)]; // number of neighbors cannot exceed the number of training vectors. int nn = System.Math.Min(neighbors, sourceCentered.GetLength(0)); // For each point to be reversed for (int p = 0; p < rows; p++) { // 1. Get the point in feature space double[] y = data.GetRow(p); // 2. Select nn nearest neighbors of the feature space double[,] X = sourceCentered; double[] d2 = new double[Result.GetLength(0)]; int[] inx = new int[Result.GetLength(0)]; // 2.1 Calculate distances for (int i = 0; i < X.GetLength(0); i++) { inx[i] = i; d2[i] = kernel.Distance(y, Result.GetRow(i).Submatrix(y.Length)); } // 2.2 Order them Array.Sort(d2, inx); // 2.3 Select nn neighbors inx = inx.Submatrix(nn); X = X.Submatrix(inx).Transpose(); // X is in input space d2 = d2.Submatrix(nn); // distances in input space // 3. Create centering matrix // H = eye(nn, nn) - 1 / nn * ones(nn, nn); double[,] H = Matrix.Identity(nn).Subtract(Matrix.Create(nn, 1.0 / nn)); // 4. Perform SVD // [U,L,V] = svd(X*H); SingularValueDecomposition svd = new SingularValueDecomposition(X.Multiply(H)); double[,] U = svd.LeftSingularVectors; double[,] L = Matrix.Diagonal(nn, svd.Diagonal); double[,] V = svd.RightSingularVectors; // 5. Compute projections // Z = L*V'; double[,] Z = L.Multiply(V.Transpose()); // 6. Calculate distances // d02 = sum(Z.^2)'; double[] d02 = Matrix.Sum(Matrix.DotPow(Z, 2)); // 7. Get the pre-image using z = -0.5*inv(Z')*(d2-d02) double[,] inv = Matrix.PseudoInverse(Z.Transpose()); double[] z = (-0.5).Multiply(inv).Multiply(d2.Subtract(d02)); // 8. Project the pre-image on the original basis // using x = U*z + sum(X,2)/nn; double[] x = (U.Multiply(z)).Add(Matrix.Sum(X.Transpose()).Multiply(1.0 / nn)); // 9. Store the computed pre-image. for (int i = 0; i < reversion.GetLength(1); i++) { reversion[p, i] = x[i]; } } // if the data has been standardized or centered, // we need to revert those operations as well if (this.Method == AnalysisMethod.Correlation) { // multiply by standard deviation and add the mean for (int i = 0; i < reversion.GetLength(0); i++) { for (int j = 0; j < reversion.GetLength(1); j++) { reversion[i, j] = (reversion[i, j] * StandardDeviations[j]) + Means[j]; } } } else { // only add the mean for (int i = 0; i < reversion.GetLength(0); i++) { for (int j = 0; j < reversion.GetLength(1); j++) { reversion[i, j] = reversion[i, j] + Means[j]; } } } return(reversion); }
public void PC() { Random rng = new Random(1); double s = 1.0 / Math.Sqrt(2.0); MultivariateSample MS = new MultivariateSample(2); RectangularMatrix R = new RectangularMatrix(1000, 2); for (int i = 0; i < 1000; i++) { double r1 = 2.0 * rng.NextDouble() - 1.0; double r2 = 2.0 * rng.NextDouble() - 1.0; double x = r1 * 4.0 * s - r2 * 9.0 * s; double y = r1 * 4.0 * s + r2 * 9.0 * s; R[i, 0] = x; R[i, 1] = y; MS.Add(x, y); } Console.WriteLine("x {0} {1}", MS.Column(0).Mean, MS.Column(0).Variance); Console.WriteLine("y {0} {1}", MS.Column(1).Mean, MS.Column(1).Variance); Console.WriteLine("SVD"); SingularValueDecomposition SVD = R.SingularValueDecomposition(); for (int i = 0; i < SVD.Dimension; i++) { Console.WriteLine("{0} {1}", i, SVD.SingularValue(i)); ColumnVector v = SVD.RightSingularVector(i); Console.WriteLine(" {0} {1}", v[0], v[1]); } Console.WriteLine("PCA"); PrincipalComponentAnalysis PCA = MS.PrincipalComponentAnalysis(); Console.WriteLine("Dimension = {0} Count = {1}", PCA.Dimension, PCA.Count); for (int i = 0; i < PCA.Dimension; i++) { PrincipalComponent PC = PCA.Component(i); Console.WriteLine(" {0} {1} {2} {3}", PC.Index, PC.Weight, PC.VarianceFraction, PC.CumulativeVarianceFraction); RowVector v = PC.NormalizedVector(); Console.WriteLine(" {0} {1}", v[0], v[1]); } // reconstruct SquareMatrix U = SVD.LeftTransformMatrix(); SquareMatrix V = SVD.RightTransformMatrix(); double x1 = U[0, 0] * SVD.SingularValue(0) * V[0, 0] + U[0, 1] * SVD.SingularValue(1) * V[0, 1]; Console.WriteLine("x1 = {0} {1}", x1, R[0, 0]); double y1 = U[0, 0] * SVD.SingularValue(0) * V[1, 0] + U[0, 1] * SVD.SingularValue(1) * V[1, 1]; Console.WriteLine("y1 = {0} {1}", y1, R[0, 1]); double x100 = U[100, 0] * SVD.SingularValue(0) * V[0, 0] + U[100, 1] * SVD.SingularValue(1) * V[0, 1]; Console.WriteLine("x100 = {0} {1}", x100, R[100, 0]); double y100 = U[100, 0] * SVD.SingularValue(0) * V[1, 0] + U[100, 1] * SVD.SingularValue(1) * V[1, 1]; Console.WriteLine("y100 = {0} {1}", y100, R[100, 1]); ColumnVector d1 = U[0, 0] * SVD.SingularValue(0) * SVD.RightSingularVector(0) + U[0, 1] * SVD.SingularValue(1) * SVD.RightSingularVector(1); Console.WriteLine("d1 = ({0} {1})", d1[0], d1[1]); ColumnVector d100 = U[100, 0] * SVD.SingularValue(0) * SVD.RightSingularVector(0) + U[100, 1] * SVD.SingularValue(1) * SVD.RightSingularVector(1); Console.WriteLine("d100 = ({0} {1})", d100[0], d100[1]); Console.WriteLine("compare"); MultivariateSample RS = PCA.TransformedSample(); IEnumerator <double[]> RSE = RS.GetEnumerator(); RSE.MoveNext(); double[] dv1 = RSE.Current; Console.WriteLine("{0} {1}", dv1[0], dv1[1]); Console.WriteLine("{0} {1}", U[0, 0], U[0, 1]); RSE.Dispose(); }
public void AllTests() { Matrix A, B, C, Z, O, I, R, S, X, SUB, M, T, SQ, DEF, SOL; double tmp; double[] columnwise = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 }; double[] rowwise = { 1.0, 4.0, 7.0, 10.0, 2.0, 5.0, 8.0, 11.0, 3.0, 6.0, 9.0, 12.0 }; double[][] avals = { new double[] { 1.0, 4.0, 7.0, 10.0 }, new double[] { 2.0, 5.0, 8.0, 11.0 }, new double[] { 3.0, 6.0, 9.0, 12.0 } }; double[][] rankdef = avals; double[][] tvals = { new double[] { 1.0, 2.0, 3.0 }, new double[] { 4.0, 5.0, 6.0 }, new double[] { 7.0, 8.0, 9.0 }, new double[] { 10.0, 11.0, 12.0 } }; double[][] subavals = { new double[] { 5.0, 8.0, 11.0 }, new double[] { 6.0, 9.0, 12.0 } }; double[][] pvals = { new double[] { 25, -5, 10 }, new double[] { -5, 17, 10 }, new double[] { 10, 10, 62 } }; double[][] ivals = { new double[] { 1.0, 0.0, 0.0, 0.0 }, new double[] { 0.0, 1.0, 0.0, 0.0 }, new double[] { 0.0, 0.0, 1.0, 0.0 } }; double[][] evals = { new double[] { 0.0, 1.0, 0.0, 0.0 }, new double[] { 1.0, 0.0, 2e-7, 0.0 }, new double[] { 0.0, -2e-7, 0.0, 1.0 }, new double[] { 0.0, 0.0, 1.0, 0.0 } }; double[][] square = { new double[] { 166.0, 188.0, 210.0 }, new double[] { 188.0, 214.0, 240.0 }, new double[] { 210.0, 240.0, 270.0 } }; double[][] sqSolution = { new double[] { 13.0 }, new double[] { 15.0 } }; double[][] condmat = { new double[] { 1.0, 3.0 }, new double[] { 7.0, 9.0 } }; int rows = 3, cols = 4; int invalidld = 5; /* should trigger bad shape for construction with val */ int validld = 3; /* leading dimension of intended test Matrices */ int nonconformld = 4; /* leading dimension which is valid, but nonconforming */ int ib = 1, ie = 2, jb = 1, je = 3; /* index ranges for sub Matrix */ int[] rowindexset = new int[] { 1, 2 }; int[] badrowindexset = new int[] { 1, 3 }; int[] columnindexset = new int[] { 1, 2, 3 }; int[] badcolumnindexset = new int[] { 1, 2, 4 }; double columnsummax = 33.0; double rowsummax = 30.0; double sumofdiagonals = 15; double sumofsquares = 650; #region Testing constructors and constructor-like methods // Constructors and constructor-like methods: // double[], int // double[,] // int, int // int, int, double // int, int, double[,] // Create(double[,]) // Random(int,int) // Identity(int) try { // check that exception is thrown in packed constructor with invalid length A = new Matrix(columnwise, invalidld); Assert.Fail("Catch invalid length in packed constructor: exception not thrown for invalid input"); } catch (ArgumentException) { } A = new Matrix(columnwise, validld); B = new Matrix(avals); tmp = B[0, 0]; avals[0][0] = 0.0; C = B - A; avals[0][0] = tmp; B = Matrix.Create(avals); tmp = B[0, 0]; avals[0][0] = 0.0; Assert.AreEqual((tmp - B[0, 0]), 0.0, "Create"); avals[0][0] = columnwise[0]; I = new Matrix(ivals); NumericAssert.AreAlmostEqual(I, Matrix.Identity(3, 4), "Identity"); #endregion #region Testing access methods // Access Methods: // getColumnDimension() // getRowDimension() // getArray() // getArrayCopy() // getColumnPackedCopy() // getRowPackedCopy() // get(int,int) // GetMatrix(int,int,int,int) // GetMatrix(int,int,int[]) // GetMatrix(int[],int,int) // GetMatrix(int[],int[]) // set(int,int,double) // SetMatrix(int,int,int,int,Matrix) // SetMatrix(int,int,int[],Matrix) // SetMatrix(int[],int,int,Matrix) // SetMatrix(int[],int[],Matrix) // Various get methods B = new Matrix(avals); Assert.AreEqual(B.RowCount, rows, "getRowDimension"); Assert.AreEqual(B.ColumnCount, cols, "getColumnDimension"); B = new Matrix(avals); double[][] barray = (Matrix)B; Assert.AreSame(barray, avals, "getArray"); barray = B.Clone(); Assert.AreNotSame(barray, avals, "getArrayCopy"); NumericAssert.AreAlmostEqual(new Matrix(barray), B, "getArrayCopy II"); // double[] bpacked = B.ColumnPackedCopy; // try // { // check(bpacked, columnwise); // try_success("getColumnPackedCopy... ", ""); // } // catch (System.SystemException e) // { // errorCount = try_failure(errorCount, "getColumnPackedCopy... ", "data not successfully (deep) copied by columns"); // System.Console.Out.WriteLine(e.Message); // } // bpacked = B.RowPackedCopy; // try // { // check(bpacked, rowwise); // try_success("getRowPackedCopy... ", ""); // } // catch (System.SystemException e) // { // errorCount = try_failure(errorCount, "getRowPackedCopy... ", "data not successfully (deep) copied by rows"); // System.Console.Out.WriteLine(e.Message); // } try { tmp = B[B.RowCount, B.ColumnCount - 1]; Assert.Fail("get(int,int): OutOfBoundsException expected but not thrown"); } catch (IndexOutOfRangeException) { } try { tmp = B[B.RowCount - 1, B.ColumnCount]; Assert.Fail("get(int,int): OutOfBoundsException expected but not thrown II"); } catch (IndexOutOfRangeException) { } Assert.AreEqual(B[B.RowCount - 1, B.ColumnCount - 1], avals[B.RowCount - 1][B.ColumnCount - 1], "get(int,int)"); SUB = new Matrix(subavals); try { M = B.GetMatrix(ib, ie + B.RowCount + 1, jb, je); Assert.Fail("GetMatrix(int,int,int,int): IndexOutOfBoundsException expected but not thrown"); } catch (IndexOutOfRangeException) { } try { M = B.GetMatrix(ib, ie, jb, je + B.ColumnCount + 1); Assert.Fail("GetMatrix(int,int,int,int): IndexOutOfBoundsException expected but not thrown II"); } catch (IndexOutOfRangeException) { } M = B.GetMatrix(ib, ie, jb, je); NumericAssert.AreAlmostEqual(SUB, M, "GetMatrix(int,int,int,int)"); try { M = B.GetMatrix(ib, ie, badcolumnindexset); Assert.Fail("GetMatrix(int,int,int[]): IndexOutOfBoundsException expected but not thrown"); } catch (IndexOutOfRangeException) { } try { M = B.GetMatrix(ib, ie + B.RowCount + 1, columnindexset); Assert.Fail("GetMatrix(int,int,int[]): IndexOutOfBoundsException expected but not thrown II"); } catch (IndexOutOfRangeException) { } M = B.GetMatrix(ib, ie, columnindexset); NumericAssert.AreAlmostEqual(SUB, M, "GetMatrix(int,int,int[])"); try { M = B.GetMatrix(badrowindexset, jb, je); Assert.Fail("GetMatrix(int[],int,int): IndexOutOfBoundsException expected but not thrown"); } catch (IndexOutOfRangeException) { } try { M = B.GetMatrix(rowindexset, jb, je + B.ColumnCount + 1); Assert.Fail("GetMatrix(int[],int,int): IndexOutOfBoundsException expected but not thrown II"); } catch (IndexOutOfRangeException) { } M = B.GetMatrix(rowindexset, jb, je); NumericAssert.AreAlmostEqual(SUB, M, "GetMatrix(int[],int,int)"); try { M = B.GetMatrix(badrowindexset, columnindexset); Assert.Fail("GetMatrix(int[],int[]): IndexOutOfBoundsException expected but not thrown"); } catch (IndexOutOfRangeException) { } try { M = B.GetMatrix(rowindexset, badcolumnindexset); Assert.Fail("GetMatrix(int[],int[]): IndexOutOfBoundsException expected but not thrown II"); } catch (IndexOutOfRangeException) { } M = B.GetMatrix(rowindexset, columnindexset); NumericAssert.AreAlmostEqual(SUB, M, "GetMatrix(int[],int[])"); // Various set methods: try { B[B.RowCount, B.ColumnCount - 1] = 0.0; Assert.Fail("set(int,int,double): IndexOutOfBoundsException expected but not thrown"); } catch (IndexOutOfRangeException) { } try { B[B.RowCount - 1, B.ColumnCount] = 0.0; Assert.Fail("set(int,int,double): IndexOutOfBoundsException expected but not thrown II"); } catch (IndexOutOfRangeException) { } B[ib, jb] = 0.0; tmp = B[ib, jb]; NumericAssert.AreAlmostEqual(tmp, 0.0, "set(int,int,double)"); M = new Matrix(2, 3, 0.0); try { B.SetMatrix(ib, ie + B.RowCount + 1, jb, je, M); Assert.Fail("SetMatrix(int,int,int,int,Matrix): IndexOutOfBoundsException expected but not thrown"); } catch (IndexOutOfRangeException) { } try { B.SetMatrix(ib, ie, jb, je + B.ColumnCount + 1, M); Assert.Fail("SetMatrix(int,int,int,int,Matrix): IndexOutOfBoundsException expected but not thrown II"); } catch (IndexOutOfRangeException) { } B.SetMatrix(ib, ie, jb, je, M); NumericAssert.AreAlmostEqual(M - B.GetMatrix(ib, ie, jb, je), M, "SetMatrix(int,int,int,int,Matrix)"); B.SetMatrix(ib, ie, jb, je, SUB); try { B.SetMatrix(ib, ie + B.RowCount + 1, columnindexset, M); Assert.Fail("SetMatrix(int,int,int[],Matrix): IndexOutOfBoundsException expected but not thrown"); } catch (IndexOutOfRangeException) { } try { B.SetMatrix(ib, ie, badcolumnindexset, M); Assert.Fail("SetMatrix(int,int,int[],Matrix): IndexOutOfBoundsException expected but not thrown II"); } catch (IndexOutOfRangeException) { } B.SetMatrix(ib, ie, columnindexset, M); NumericAssert.AreAlmostEqual(M - B.GetMatrix(ib, ie, columnindexset), M, "SetMatrix(int,int,int[],Matrix)"); B.SetMatrix(ib, ie, jb, je, SUB); try { B.SetMatrix(rowindexset, jb, je + B.ColumnCount + 1, M); Assert.Fail("SetMatrix(int[],int,int,Matrix): IndexOutOfBoundsException expected but not thrown"); } catch (IndexOutOfRangeException) { } try { B.SetMatrix(badrowindexset, jb, je, M); Assert.Fail("SetMatrix(int[],int,int,Matrix): IndexOutOfBoundsException expected but not thrown II"); } catch (IndexOutOfRangeException) { } B.SetMatrix(rowindexset, jb, je, M); NumericAssert.AreAlmostEqual(M - B.GetMatrix(rowindexset, jb, je), M, "SetMatrix(int[],int,int,Matrix)"); B.SetMatrix(ib, ie, jb, je, SUB); try { B.SetMatrix(rowindexset, badcolumnindexset, M); Assert.Fail("SetMatrix(int[],int[],Matrix): IndexOutOfBoundsException expected but not thrown"); } catch (IndexOutOfRangeException) { } try { B.SetMatrix(badrowindexset, columnindexset, M); Assert.Fail("SetMatrix(int[],int[],Matrix): IndexOutOfBoundsException expected but not thrown"); } catch (IndexOutOfRangeException) { } B.SetMatrix(rowindexset, columnindexset, M); NumericAssert.AreAlmostEqual(M - B.GetMatrix(rowindexset, columnindexset), M, "SetMatrix(int[],int[],Matrix)"); #endregion #region Testing array-like methods // Array-like methods: // Subtract // SubtractEquals // Add // AddEquals // ArrayLeftDivide // ArrayLeftDivideEquals // ArrayRightDivide // ArrayRightDivideEquals // arrayTimes // ArrayMultiplyEquals // uminus S = new Matrix(columnwise, nonconformld); R = Matrix.Random(A.RowCount, A.ColumnCount); A = R; try { S = A - S; Assert.Fail("Subtract conformance check: nonconformance not raised"); } catch (ArgumentException) { } Assert.AreEqual((A - R).Norm1(), 0.0, "Subtract: difference of identical Matrices is nonzero,\nSubsequent use of Subtract should be suspect"); A = R.Clone(); A.Subtract(R); Z = new Matrix(A.RowCount, A.ColumnCount); try { A.Subtract(S); Assert.Fail("SubtractEquals conformance check: nonconformance not raised"); } catch (ArgumentException) { } Assert.AreEqual((A - Z).Norm1(), 0.0, "SubtractEquals: difference of identical Matrices is nonzero,\nSubsequent use of Subtract should be suspect"); A = R.Clone(); B = Matrix.Random(A.RowCount, A.ColumnCount); C = A - B; try { S = A + S; Assert.Fail("Add conformance check: nonconformance not raised"); } catch (ArgumentException) { } NumericAssert.AreAlmostEqual(C + B, A, "Add"); C = A - B; C.Add(B); try { A.Add(S); Assert.Fail("AddEquals conformance check: nonconformance not raised"); } catch (ArgumentException) { } NumericAssert.AreAlmostEqual(C, A, "AddEquals"); A = ((Matrix)R.Clone()); A.UnaryMinus(); NumericAssert.AreAlmostEqual(A + R, Z, "UnaryMinus"); A = (Matrix)R.Clone(); O = new Matrix(A.RowCount, A.ColumnCount, 1.0); try { Matrix.ArrayDivide(A, S); Assert.Fail("ArrayRightDivide conformance check: nonconformance not raised"); } catch (ArgumentException) { } C = Matrix.ArrayDivide(A, R); NumericAssert.AreAlmostEqual(C, O, "ArrayRightDivide"); try { A.ArrayDivide(S); Assert.Fail("ArrayRightDivideEquals conformance check: nonconformance not raised"); } catch (ArgumentException) { } A.ArrayDivide(R); NumericAssert.AreAlmostEqual(A, O, "ArrayRightDivideEquals"); A = (Matrix)R.Clone(); B = Matrix.Random(A.RowCount, A.ColumnCount); try { S = Matrix.ArrayMultiply(A, S); Assert.Fail("arrayTimes conformance check: nonconformance not raised"); } catch (ArgumentException) { } C = Matrix.ArrayMultiply(A, B); C.ArrayDivide(B); NumericAssert.AreAlmostEqual(C, A, "arrayTimes"); try { A.ArrayMultiply(S); Assert.Fail("ArrayMultiplyEquals conformance check: nonconformance not raised"); } catch (ArgumentException) { } A.ArrayMultiply(B); A.ArrayDivide(B); NumericAssert.AreAlmostEqual(A, R, "ArrayMultiplyEquals"); #endregion #region Testing linear algebra methods // LA methods: // Transpose // Multiply // Condition // Rank // Determinant // trace // Norm1 // norm2 // normF // normInf // Solve // solveTranspose // Inverse // chol // Eigen // lu // qr // svd A = new Matrix(columnwise, 3); T = new Matrix(tvals); T = Matrix.Transpose(A); NumericAssert.AreAlmostEqual(Matrix.Transpose(A), T, "Transpose"); NumericAssert.AreAlmostEqual(A.Norm1(), columnsummax, "Norm1"); NumericAssert.AreAlmostEqual(A.NormInf(), rowsummax, "NormInf"); NumericAssert.AreAlmostEqual(A.NormF(), Math.Sqrt(sumofsquares), "NormF"); NumericAssert.AreAlmostEqual(A.Trace(), sumofdiagonals, "Trace"); NumericAssert.AreAlmostEqual(A.GetMatrix(0, A.RowCount - 1, 0, A.RowCount - 1).Determinant(), 0.0, "Determinant"); SQ = new Matrix(square); NumericAssert.AreAlmostEqual(A * Matrix.Transpose(A), SQ, "Multiply(Matrix)"); NumericAssert.AreAlmostEqual(0.0 * A, Z, "Multiply(double)"); A = new Matrix(columnwise, 4); QRDecomposition QR = A.QRDecomposition; R = QR.R; NumericAssert.AreAlmostEqual(A, QR.Q * R, "QRDecomposition"); SingularValueDecomposition SVD = A.SingularValueDecomposition; NumericAssert.AreAlmostEqual(A, SVD.LeftSingularVectors * (SVD.S * Matrix.Transpose(SVD.RightSingularVectors)), "SingularValueDecomposition"); DEF = new Matrix(rankdef); NumericAssert.AreAlmostEqual(DEF.Rank(), Math.Min(DEF.RowCount, DEF.ColumnCount) - 1, "Rank"); B = new Matrix(condmat); SVD = B.SingularValueDecomposition; double[] singularvalues = SVD.SingularValues; NumericAssert.AreAlmostEqual(B.Condition(), singularvalues[0] / singularvalues[Math.Min(B.RowCount, B.ColumnCount) - 1], "Condition"); int n = A.ColumnCount; A = A.GetMatrix(0, n - 1, 0, n - 1); A[0, 0] = 0.0; LUDecomposition LU = A.LUDecomposition; NumericAssert.AreAlmostEqual(A.GetMatrix(LU.Pivot, 0, n - 1), LU.L * LU.U, "LUDecomposition"); X = A.Inverse(); NumericAssert.AreAlmostEqual(A * X, Matrix.Identity(3, 3), "Inverse"); O = new Matrix(SUB.RowCount, 1, 1.0); SOL = new Matrix(sqSolution); SQ = SUB.GetMatrix(0, SUB.RowCount - 1, 0, SUB.RowCount - 1); NumericAssert.AreAlmostEqual(SQ.Solve(SOL), O, "Solve"); A = new Matrix(pvals); CholeskyDecomposition Chol = A.CholeskyDecomposition; Matrix L = Chol.TriangularFactor; NumericAssert.AreAlmostEqual(A, L * Matrix.Transpose(L), "CholeskyDecomposition"); X = Chol.Solve(Matrix.Identity(3, 3)); NumericAssert.AreAlmostEqual(A * X, Matrix.Identity(3, 3), "CholeskyDecomposition Solve"); EigenvalueDecomposition Eig = A.EigenvalueDecomposition; Matrix D = Eig.BlockDiagonal; Matrix V = Eig.EigenVectors; NumericAssert.AreAlmostEqual(A * V, V * D, "EigenvalueDecomposition (symmetric)"); A = new Matrix(evals); Eig = A.EigenvalueDecomposition; D = Eig.BlockDiagonal; V = Eig.EigenVectors; NumericAssert.AreAlmostEqual(A * V, V * D, "EigenvalueDecomposition (nonsymmetric)"); #endregion }
/// <summary> /// Parallel (symmetric) iterative algorithm. /// </summary> /// <returns> /// Returns a matrix in which each row contains /// the mixing coefficients for each component. /// </returns> private double[,] parallel(double[,] X, int components, double[,] winit) { int n = X.GetLength(0); int m = X.GetLength(1); // Algorithm initialization double[,] W0 = winit; double[,] W = winit; double[,] K = new double[components, components]; bool stop = false; int iterations = 0; do // until convergence { // Perform simultaneous decorrelation of all components at once var svd = new SingularValueDecomposition(W, true, false, true); var S = svd.Diagonal; var U = svd.LeftSingularVectors; // Normalize for (int i = 0; i < components; i++) { for (int j = 0; j < components; j++) { double s = 0; for (int k = 0; k < components; k++) if (S[k] != 0.0) s += U[i, k] * U[j, k] / S[k]; K[i, j] = s; } } // Decorrelate W = K.Multiply(W); // Gets the maximum absolute change in the parameters double delta = Matrix.Max(Matrix.Abs(Matrix.Abs(Matrix.Diagonal(W0.Multiply(W.Transpose()))).Subtract(1.0))); // Check for convergence if (delta < tolerance || iterations >= maxIterations) { stop = true; } else { // Advance to the next iteration W0 = W; W = new double[components,m]; iterations++; #if DEBUG // For each component (in parallel) for (int i = 0; i < components; i++) #else GABIZ.Base.Parallel.For(0, components, i => #endif { double[] wx = new double[n]; double[] dgwx = new double[n]; double[] gwx = new double[n]; double[] means = new double[m]; // Compute wx = w*x for (int j = 0; j < n; j++) { double s = 0; for (int k = 0; k < m; k++) s += W0[i, k] * X[j, k]; wx[j] = s; } // Compute g(wx) and g'(wx) contrast.Evaluate(wx, gwx, dgwx); // Compute E{ x*g(w*x) } for (int j = 0; j < m; j++) { for (int k = 0; k < n; k++) means[j] += X[k, j] * gwx[k]; means[j] /= n; } // Compute E{ g'(w*x) } double mean = GABIZ.Base.Statistics.Tools.Mean(dgwx); // Compute next update for w for (int j = 0; j < m; j++) W[i, j] = means[j] - W0[i, j] * mean; } #if !DEBUG ); #endif } } while (!stop); // Return the component basis matrix return W; // vectors stored as rows. }
protected static void svd(double[,] m, out double[,] U) { var svd = new SingularValueDecomposition(m, true, false, true); U = svd.LeftSingularVectors; }
/// <summary> /// Perform the Singular Value Decomposition and identify the rank of the embedding subspace /// Characteristic of projection: the proportion of variance captured in the subspace /// </summary> public void Decompose() { //transformation of the embedded matrix var XT = _xCom.Transpose(); //embedding (trajectory) matrix helper var var X = _xCom; //S matrix calculation double[,] S = _xCom.Dot(XT); /*Single Value Decomposition * For an m-by-n matrix A with m >= n, the singular value decomposition is * * an m-by-n orthogonal matrix U, * an n-by-n diagonal matrix S, * and an n-by-n orthogonal matrix V * so that A = U * S * V'. * * The singular values, sigma[k] = S[k,k], are ordered so that sigma[0] >= sigma[1] >= ... >= sigma[n-1]. */ var svd = new SingularValueDecomposition(S); //summary of the SVD calculation //left eigenvector double[,] U = svd.LeftSingularVectors; double[] s = svd.Diagonal.Sqrt(); //right eigenvector double[,] V = svd.RightSingularVectors; int d = svd.Rank; //helper variable to calculate characteristics of projection double[][] Ys = new double[d][]; double[][] Zs = new double[d][]; var Vs = new double[d][]; //SVD trajectory matrix written as Xs = X1 + X2 + X3 + ... + Xd _Xs = new Dictionary <int, double[, ]>(); //calculation of the eigen-triple of the SVD for (int i = 0; i < d; i++) { // Zs[i] = V.GetColumn(i).Multiply(s[i]); // Vs[i] = XT.Dot(U.GetColumn(i).Divide(s[i])); // Ys[i] = U.GetColumn(i).Multiply(s[i]); //vector of Ys[i] to matrix d x 1 var y = Ys[i].ToMatrix(asColumnVector: true); //vector of Vs[i] to matrix 1 x n var v = Vs[i].ToMatrix(asColumnVector: false); //matrix multiplication var x = y.Dot(v); _Xs.Add(i, x); } //calculate contributions _sContributions = getControbutions(X, s); int r = _sContributions.Length; var firstRValues = s.Take(r).ToArray(); var _rCharacteristic = Math.Round(firstRValues.Multiply(firstRValues).Sum() / s.Multiply(s).Sum(), 4); // var orthonormalBase = new double[r][]; foreach (var ind in Enumerable.Range(0, r)) { orthonormalBase[ind] = U.GetColumn(ind); } //set final value of the orthonormal matrix _orthonormalBase = orthonormalBase; }
private static void decompose(NormalOptions options, double[,] cov, out CholeskyDecomposition chol, out SingularValueDecomposition svd) { svd = null; chol = null; if (options == null) { // We don't have options. Just attempt a standard fitting. If // the matrix is not positive semi-definite, throw an exception. chol = new CholeskyDecomposition(cov); if (!chol.IsPositiveDefinite) { throw new NonPositiveDefiniteMatrixException("Covariance matrix is not positive " + "definite. Try specifying a regularization constant in the fitting options " + "(there is an example in the Multivariate Normal Distribution documentation)."); } return; } else { // We have options. In this case, we will either be using the SVD // or we can add a regularization constant until the covariance // matrix becomes positive semi-definite. if (options.Robust) { // No need to apply a regularization constant in this case svd = new SingularValueDecomposition(cov, true, true, true); } else { // Apply a regularization constant until covariance becomes positive chol = new CholeskyDecomposition(cov); // Check if need to add a regularization constant double regularization = options.Regularization; if (regularization > 0) { int dimension = cov.Rows(); while (!chol.IsPositiveDefinite) { for (int i = 0; i < dimension; i++) { for (int j = 0; j < dimension; j++) { if (Double.IsNaN(cov[i, j]) || Double.IsInfinity(cov[i, j])) { cov[i, j] = 0.0; } } cov[i, i] += regularization; } chol = new CholeskyDecomposition(cov, false, true); } } if (!chol.IsPositiveDefinite) { throw new NonPositiveDefiniteMatrixException("Covariance matrix is not positive " + "definite. Try specifying a regularization constant in the fitting options " + "(there is an example in the Multivariate Normal Distribution documentation)."); } } } }
/// <summary> /// Fits the underlying distribution to a given set of observations. /// </summary> /// /// <param name="observations">The array of observations to fit the model against. The array /// elements can be either of type double (for univariate data) or /// type double[] (for multivariate data).</param> /// <param name="weights">The weight vector containing the weight for each of the samples.</param> /// <param name="options">Optional arguments which may be used during fitting, such /// as regularization constants and additional parameters.</param> /// /// <example> /// Please see <see cref="MultivariateNormalDistribution"/>. /// </example> /// public void Fit(double[][] observations, double[] weights, NormalOptions options) { double[] means; double[,] cov; if (weights != null) { #if DEBUG for (int i = 0; i < weights.Length; i++) { if (Double.IsNaN(weights[i]) || Double.IsInfinity(weights[i])) { throw new ArgumentException("Invalid numbers in the weight vector.", "weights"); } } #endif // Compute weighted mean vector means = Measures.WeightedMean(observations, weights); // Compute weighted covariance matrix if (options != null && options.Diagonal) { cov = Matrix.Diagonal(Measures.WeightedVariance(observations, weights, means)); } else { cov = Measures.WeightedCovariance(observations, weights, means); } } else { // Compute mean vector means = Measures.Mean(observations); // Compute covariance matrix if (options != null && options.Diagonal) { cov = Matrix.Diagonal(Measures.Variance(observations, means)); } cov = Measures.Covariance(observations, means); } CholeskyDecomposition chol = null; SingularValueDecomposition svd = null; if (options == null) { // We don't have further options. Just attempt a standard // fitting. If the matrix is not positive semi-definite, // throw an exception. chol = new CholeskyDecomposition(cov, robust: false, lowerTriangular: true); if (!chol.PositiveDefinite) { throw new NonPositiveDefiniteMatrixException("Covariance matrix is not positive " + "definite. Try specifying a regularization constant in the fitting options " + "(there is an example in the Multivariate Normal Distribution documentation)."); } // Become the newly fitted distribution. initialize(means, cov, chol, svd: null); return; } // We have options. In this case, we will either be using the SVD // or we can add a regularization constant until the covariance // matrix becomes positive semi-definite. if (options.Robust) { svd = new SingularValueDecomposition(cov, true, true, true); // No need to apply a regularization constant in this case // Become the newly fitted distribution. initialize(means, cov, null, svd); return; } chol = new CholeskyDecomposition(cov, robust: false, lowerTriangular: true); // Check if need to add a regularization constant double regularization = options.Regularization; if (regularization > 0) { int dimension = observations[0].Length; while (!chol.PositiveDefinite) { for (int i = 0; i < dimension; i++) { for (int j = 0; j < dimension; j++) { if (Double.IsNaN(cov[i, j]) || Double.IsInfinity(cov[i, j])) { cov[i, j] = 0.0; } } cov[i, i] += regularization; } chol = new CholeskyDecomposition(cov, false, true); } } if (!chol.PositiveDefinite) { throw new NonPositiveDefiniteMatrixException("Covariance matrix is not positive " + "definite. Try specifying a regularization constant in the fitting options " + "(there is an example in the Multivariate Normal Distribution documentation)."); } // Become the newly fitted distribution. initialize(means, cov, chol, svd: null); }
public virtual void Compute() { if (!onlyCovarianceMatrixAvailable) { int rows; if (this.array != null) { rows = array.Length; // Center and standardize the source matrix double[][] matrix = Adjust(array, Overwrite); // Perform the Singular Value Decomposition (SVD) of the matrix var svd = new JaggedSingularValueDecomposition(matrix, computeLeftSingularVectors: true, computeRightSingularVectors: true, autoTranspose: true, inPlace: true); SingularValues = svd.Diagonal; // The principal components of 'Source' are the eigenvectors of Cov(Source). Thus if we // calculate the SVD of 'matrix' (which is Source standardized), the columns of matrix V // (right side of SVD) will be the principal components of Source. // The right singular vectors contains the principal components of the data matrix ComponentVectors = svd.RightSingularVectors.Transpose(); } else { rows = source.GetLength(0); // Center and standardize the source matrix #pragma warning disable 612, 618 double[,] matrix = Adjust(source, Overwrite); #pragma warning restore 612, 618 // Perform the Singular Value Decomposition (SVD) of the matrix var svd = new SingularValueDecomposition(matrix, computeLeftSingularVectors: true, computeRightSingularVectors: true, autoTranspose: true, inPlace: true); SingularValues = svd.Diagonal; // The principal components of 'Source' are the eigenvectors of Cov(Source). Thus if we // calculate the SVD of 'matrix' (which is Source standardized), the columns of matrix V // (right side of SVD) will be the principal components of Source. // The right singular vectors contains the principal components of the data matrix ComponentVectors = svd.RightSingularVectors.ToArray().Transpose(); // The left singular vectors contains the factor scores for the principal components } // Eigenvalues are the square of the singular values Eigenvalues = new double[SingularValues.Length]; for (int i = 0; i < SingularValues.Length; i++) { Eigenvalues[i] = SingularValues[i] * SingularValues[i] / (rows - 1); } } else { // We only have the covariance matrix. Compute the Eigenvalue decomposition var evd = new EigenvalueDecomposition(covarianceMatrix, assumeSymmetric: true, sort: true); // Gets the Eigenvalues and corresponding Eigenvectors Eigenvalues = evd.RealEigenvalues; var eigenvectors = evd.Eigenvectors.ToJagged(); SingularValues = Eigenvalues.Sqrt(); ComponentVectors = eigenvectors.Transpose(); } if (Whiten) { ComponentVectors = ComponentVectors.Transpose().Divide(Eigenvalues, dimension: 0).Transpose(); } CreateComponents(); if (!onlyCovarianceMatrixAvailable) { if (array != null) { result = Transform(array).ToMatrix(); } else if (source != null) { result = Transform(source.ToJagged()).ToMatrix(); } } }
public ArgumentsValue Function(MatrixValue M) { var svd = new SingularValueDecomposition(M); return(new ArgumentsValue(svd.S, svd.GetU(), svd.GetV())); }
private void computeMagCalButton_Click(object sender, EventArgs e) { int i, j; calStatusText.Text = "Computing Calibration..."; // Construct D matrix // D = [x.^2, y.^2, z.^2, x.*y, x.*z, y.*z, x, y, z, ones(N,1)]; for (i = 0; i < SAMPLES; i++) { // x^2 term D.SetElement(i, 0, loggedData[i, 0] * loggedData[i, 0]); // y^2 term D.SetElement(i, 1, loggedData[i, 1] * loggedData[i, 1]); // z^2 term D.SetElement(i, 2, loggedData[i, 2] * loggedData[i, 2]); // x*y term D.SetElement(i, 3, loggedData[i, 0] * loggedData[i, 1]); // x*z term D.SetElement(i, 4, loggedData[i, 0] * loggedData[i, 2]); // y*z term D.SetElement(i, 5, loggedData[i, 1] * loggedData[i, 2]); // x term D.SetElement(i, 6, loggedData[i, 0]); // y term D.SetElement(i, 7, loggedData[i, 1]); // z term D.SetElement(i, 8, loggedData[i, 2]); // Constant term D.SetElement(i, 9, 1); } // QR=triu(qr(D)) QRDecomposition QR = new QRDecomposition(D); // [U,S,V] = svd(D) SingularValueDecomposition SVD = new SingularValueDecomposition(QR.R); GeneralMatrix V = SVD.GetV(); GeneralMatrix A = new GeneralMatrix(3, 3); double[] p = new double[V.RowDimension]; for (i = 0; i < V.RowDimension; i++) { p[i] = V.GetElement(i, V.ColumnDimension - 1); } /* * A = [p(1) p(4)/2 p(5)/2; * p(4)/2 p(2) p(6)/2; * p(5)/2 p(6)/2 p(3)]; */ if (p[0] < 0) { for (i = 0; i < V.RowDimension; i++) { p[i] = -p[i]; } } A.SetElement(0, 0, p[0]); A.SetElement(0, 1, p[3] / 2); A.SetElement(1, 2, p[4] / 2); A.SetElement(1, 0, p[3] / 2); A.SetElement(1, 1, p[1]); A.SetElement(1, 2, p[5] / 2); A.SetElement(2, 0, p[4] / 2); A.SetElement(2, 1, p[5] / 2); A.SetElement(2, 2, p[2]); CholeskyDecomposition Chol = new CholeskyDecomposition(A); GeneralMatrix Ut = Chol.GetL(); GeneralMatrix U = Ut.Transpose(); double[] bvect = { p[6] / 2, p[7] / 2, p[8] / 2 }; double d = p[9]; GeneralMatrix b = new GeneralMatrix(bvect, 3); GeneralMatrix v = Ut.Solve(b); double vnorm_sqrd = v.GetElement(0, 0) * v.GetElement(0, 0) + v.GetElement(1, 0) * v.GetElement(1, 0) + v.GetElement(2, 0) * v.GetElement(2, 0); double s = 1 / Math.Sqrt(vnorm_sqrd - d); GeneralMatrix c = U.Solve(v); for (i = 0; i < 3; i++) { c.SetElement(i, 0, -c.GetElement(i, 0)); } U = U.Multiply(s); for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { calMat[i, j] = U.GetElement(i, j); } } for (i = 0; i < 3; i++) { bias[i] = c.GetElement(i, 0); } magAlignment00.Text = calMat[0, 0].ToString(); magAlignment01.Text = calMat[0, 1].ToString(); magAlignment02.Text = calMat[0, 2].ToString(); magAlignment10.Text = calMat[1, 0].ToString(); magAlignment11.Text = calMat[1, 1].ToString(); magAlignment12.Text = calMat[1, 2].ToString(); magAlignment20.Text = calMat[2, 0].ToString(); magAlignment21.Text = calMat[2, 1].ToString(); magAlignment22.Text = calMat[2, 2].ToString(); biasX.Text = bias[0].ToString(); biasY.Text = bias[1].ToString(); biasZ.Text = bias[2].ToString(); calStatusText.Text = "Done"; flashCommitButton.Enabled = true; magAlignmentCommitButton.Enabled = true; }
public SingularValueDecompositionWrapper(SingularValueDecomposition svd) { _svd = svd; }