示例#1
0
 private TSNEState(TSNEState original, Cloner cloner) : base(original, cloner)
 {
     distance      = cloner.Clone(original.distance);
     random        = cloner.Clone(original.random);
     perplexity    = original.perplexity;
     exact         = original.exact;
     noDatapoints  = original.noDatapoints;
     finalMomentum = original.finalMomentum;
     momSwitchIter = original.momSwitchIter;
     stopLyingIter = original.stopLyingIter;
     theta         = original.theta;
     eta           = original.eta;
     newDimensions = original.newDimensions;
     if (original.valP != null)
     {
         valP = new double[original.valP.Length];
         Array.Copy(original.valP, valP, valP.Length);
     }
     if (original.rowP != null)
     {
         rowP = new int[original.rowP.Length];
         Array.Copy(original.rowP, rowP, rowP.Length);
     }
     if (original.colP != null)
     {
         colP = new int[original.colP.Length];
         Array.Copy(original.colP, colP, colP.Length);
     }
     if (original.p != null)
     {
         p = new double[original.p.GetLength(0), original.p.GetLength(1)];
         Array.Copy(original.p, p, p.Length);
     }
     newData = new double[original.newData.GetLength(0), original.newData.GetLength(1)];
     Array.Copy(original.newData, newData, newData.Length);
     iter            = original.iter;
     currentMomentum = original.currentMomentum;
     gains           = new double[original.gains.GetLength(0), original.gains.GetLength(1)];
     Array.Copy(original.gains, gains, gains.Length);
     uY = new double[original.uY.GetLength(0), original.uY.GetLength(1)];
     Array.Copy(original.uY, uY, uY.Length);
     dY = new double[original.dY.GetLength(0), original.dY.GetLength(1)];
     Array.Copy(original.dY, dY, dY.Length);
 }
示例#2
0
        public static double[,] Iterate(TSNEState state)
        {
            if (state.exact)
            {
                ComputeExactGradient(state.p, state.newData, state.noDatapoints, state.newDimensions, state.dY);
            }
            else
            {
                ComputeApproximateGradient(state.rowP, state.colP, state.valP, state.newData, state.noDatapoints, state.newDimensions, state.dY, state.theta);
            }

            // Update gains
            for (var i = 0; i < state.noDatapoints; i++)
            {
                for (var j = 0; j < state.newDimensions; j++)
                {
                    state.gains[i, j] = Math.Sign(state.dY[i, j]) != Math.Sign(state.uY[i, j])
            ? state.gains[i, j] + .2 // +0.2 nd *0.8 are used in two separate implementations of tSNE -> seems to be correct
            : state.gains[i, j] * .8;
                    if (state.gains[i, j] < .01)
                    {
                        state.gains[i, j] = .01;
                    }
                }
            }

            // Perform gradient update (with momentum and gains)
            for (var i = 0; i < state.noDatapoints; i++)
            {
                for (var j = 0; j < state.newDimensions; j++)
                {
                    state.uY[i, j] = state.currentMomentum * state.uY[i, j] - state.eta * state.gains[i, j] * state.dY[i, j];
                }
            }

            for (var i = 0; i < state.noDatapoints; i++)
            {
                for (var j = 0; j < state.newDimensions; j++)
                {
                    state.newData[i, j] = state.newData[i, j] + state.uY[i, j];
                }
            }

            // Make solution zero-mean
            ZeroMean(state.newData);

            // Stop lying about the P-values after a while, and switch momentum
            if (state.iter == state.stopLyingIter)
            {
                if (state.exact)
                {
                    for (var i = 0; i < state.noDatapoints; i++)
                    {
                        for (var j = 0; j < state.noDatapoints; j++)
                        {
                            state.p[i, j] /= 12.0;
                        }
                    }
                }
                else
                {
                    for (var i = 0; i < state.rowP[state.noDatapoints]; i++)
                    {
                        state.valP[i] /= 12.0;
                    }
                }
            }

            if (state.iter == state.momSwitchIter)
            {
                state.currentMomentum = state.finalMomentum;
            }

            state.iter++;
            return(state.newData);
        }