Exemple #1
0
        public void solve_for_diagonal()
        {
            int count = 3;

            double[][] value  = new double[count][];
            double[]   output = new double[count];

            for (int i = 0; i < count; i++)
            {
                value[i] = new double[3];

                double x = i + 1;
                double y = 2 * (i + 1) - 1;
                value[i][0] = x;
                value[i][1] = y;
                value[i][2] = System.Math.Pow(x, 2);
                output[i]   = 4 * x - y + 3;
            }



            var target = new JaggedSingularValueDecomposition(value,
                                                              computeLeftSingularVectors: true,
                                                              computeRightSingularVectors: true);

            {
                double[][] expected = value;
                double[][] actual   = Matrix.Multiply(Matrix.Multiply(target.LeftSingularVectors,
                                                                      target.DiagonalMatrix),
                                                      target.RightSingularVectors.Transpose());

                // Checking the decomposition
                Assert.IsTrue(Matrix.IsEqual(actual, expected, 1e-8));
            }

            {
                double[][] expected = value.Inverse();
                double[][] actual   = Matrix.Multiply(Matrix.Multiply(
                                                          target.RightSingularVectors.Transpose().Inverse(),
                                                          target.DiagonalMatrix.Inverse()),
                                                      target.LeftSingularVectors.Inverse()
                                                      );

                // Checking the invers decomposition
                Assert.IsTrue(Matrix.IsEqual(actual, expected, 1e-8));
            }


            {
                double[][] solution = target.SolveForDiagonal(output);

                double[][] expected = Jagged.Diagonal(output);
                double[][] actual   = value.Dot(solution);

                Assert.IsTrue(Matrix.IsEqual(actual, expected, 1e-8));
            }
        }
Exemple #2
0
        /// <summary>
        ///   Solves a set of equation systems of type <c>A * X = B</c> where B is a diagonal matrix.
        /// </summary>
        /// <param name="diagonal">Diagonal fo the right hand side matrix with as many rows as <c>A</c>.</param>
        /// <returns>Matrix <c>X</c> so that <c>L * U * X = B</c>.</returns>
        ///
        public Single[][] SolveForDiagonal(Single[] diagonal)
        {
            if (diagonal == null)
            {
                throw new ArgumentNullException("diagonal");
            }

            return(Solve(Jagged.Diagonal(diagonal)));
        }
Exemple #3
0
        /// <summary>Least squares solution of <c>A * X = I</c></summary>
        public Double[][] Inverse()
        {
            if (!this.FullRank)
            {
                throw new InvalidOperationException("Matrix is rank deficient.");
            }

            return(Solve(Jagged.Diagonal(n, n, (Double)1)));
        }
Exemple #4
0
        /// <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 = 10)
        {
            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.Rows();

            var result = this.result;

            double[][] reversion = Jagged.Zeros(rows, sourceCentered.Columns());

            // number of neighbors cannot exceed the number of training vectors.
            int nn = System.Math.Min(neighbors, sourceCentered.Rows());


            // 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).First(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.First(def);
                X   = X.Get(inx).Transpose(); // X is in input space
                d2  = d2.First(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.
                var svd = new JaggedSingularValueDecomposition(X,
                                                               computeLeftSingularVectors: true,
                                                               computeRightSingularVectors: true,
                                                               autoTranspose: false);

                double[][] U = svd.LeftSingularVectors;
                double[][] L = Jagged.Diagonal(def, svd.Diagonal);
                double[][] V = svd.RightSingularVectors;


                // 4. Compute projections
                //    Z = L*V';
                double[][] Z = Matrix.DotWithTransposed(L, V);

                // 5. Calculate distances
                //    d02 = sum(Z.^2)';
                double[] d02 = Matrix.Sum(Elementwise.Pow(Z, 2), 0);

                // 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).Dot(d2.Subtract(d02));
                double[] z = w.First(U.Columns());

                // 8. Project the pre-image on the original basis using
                //    x = U*z + sum(X,2)/nn;
                double[] x = (U.Dot(z)).Add(Matrix.Sum(X.Transpose(), 0).Multiply(1.0 / nn));

                // 9. Store the computed pre-image.
                for (int i = 0; i < reversion.Columns(); 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 == PrincipalComponentMethod.Standardize)
            {
                // multiply by standard deviation and add the mean
                reversion.Multiply(StandardDeviations, dimension: 0, result: reversion)
                .Add(Means, dimension: 0, result: reversion);
            }
            else if (this.Method == PrincipalComponentMethod.Center)
            {
                // only add the mean
                reversion.Add(Means, dimension: 0, result: reversion);
            }


            return(reversion);
        }