Esempio n. 1
0
        public Array <float> x2p(Array <float> X, float tol = 1e-5f, float perplexity = 30f, bool sym = true, bool normalize = true)
        {
            //"""Performs a binary search to get P-values in such a way that each conditional Gaussian has the same perplexity."""

            // Initialize some variables
            Console.WriteLine("Computing pairwise distances...");
            int n = X.Shape[0], d = X.Shape[1];
            var sum_X = NN.Sum(X * X, axis: 1);
            var D     = (-2 * X.Dot(X.T) + sum_X).T + sum_X;
            var P     = NN.Zeros(n, n);
            var beta  = NN.Ones(n);
            var logU  = (float)Math.Log(perplexity);
            var Di    = NN.Zeros(n, n - 1);

            // Loop over all datapoints
            for (int i = 0; i < n; ++i)
            {
                // Print progress
                if (i % 500 == 0)
                {
                    Console.WriteLine("Computing P-values for point {0} of {1} ...", i, n);
                }

                // Compute the Gaussian kernel and entropy for the current precision
                var betamin = float.NegativeInfinity;
                var betamax = float.PositiveInfinity;
                Di[i, Until(i)] = D[Until(i)];
                if (i + 1 < n)
                {
                    Di[i, From(i + 1)] = D[From(i)];
                }

                var H_thisP = Hbeta(Di, beta.Item[i]);
                var H = H_thisP.Item1; var thisP = H_thisP.Item2;

                // Evaluate whether the perplexity is within tolerance
                var Hdiff = H - logU;
                var tries = 0;
                while (Math.Abs(Hdiff) > tol && tries < 50)
                {
                    // If not, increase or decrease precision
                    if (Hdiff > 0)
                    {
                        betamin = beta.Item[i];
                        if (float.IsInfinity(betamax))
                        {
                            beta.Item[i] = beta.Item[i] * 2;
                        }
                        else
                        {
                            beta.Item[i] = (beta.Item[i] + betamax) / 2;
                        }
                    }
                    else
                    {
                        betamax = beta.Item[i];
                        if (float.IsInfinity(betamin))
                        {
                            beta.Item[i] = beta.Item[i] / 2;
                        }
                        else
                        {
                            beta.Item[i] = (beta.Item[i] + betamin) / 2;
                        }
                    }
                    // Recompute the values
                    H_thisP = Hbeta(Di, beta.Item[i]);
                    H       = H_thisP.Item1; thisP = H_thisP.Item2;

                    Hdiff = H - logU;
                    tries = tries + 1;
                }

                // Set the final row of P
                P[i, Until(i)] = thisP[Until(i)];
                if (i + 1 < n)
                {
                    P[i, From(i + 1)] = thisP[From(i)];
                }
            }
            var sigma = NN.Mean(NN.Sqrt(1 / beta));

            Console.WriteLine("Mean value of sigma: {0}", sigma);

            // Return final P-matrix
            if (sym)
            {
                P += P.T;
            }
            if (normalize)
            {
                P /= NN.Sum(P);
            }
            return(P);
        }