Changeset 14837


Ignore:
Timestamp:
04/10/17 15:50:16 (2 weeks ago)
Author:
gkronber
Message:

#2700 made some changes while reviewing (comparsion with bh_tsne implementation by van der Maarten)

Location:
branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEAlgorithm.cs

    r14807 r14837  
    200200      Parameters.Add(new ValueParameter<IDistance<double[]>>(DistanceParameterName, "The distance function used to differentiate similar from non-similar points", new EuclideanDistance()));
    201201      Parameters.Add(new FixedValueParameter<DoubleValue>(PerplexityParameterName, "Perplexity-parameter of tSNE. Comparable to k in a k-nearest neighbour algorithm. Recommended value is floor(number of points /3) or lower", new DoubleValue(25)));
    202       Parameters.Add(new FixedValueParameter<DoubleValue>(ThetaParameterName, "Value describing how much appoximated gradients my differ from exact gradients. Set to 0 for exact calculation and in [0,1] otherwise. CAUTION: exact calculation of forces requires building a non-sparse N*N matrix where N is the number of data points. This may exceed memory limitations.", new DoubleValue(0)));
     202      Parameters.Add(new FixedValueParameter<DoubleValue>(ThetaParameterName, "Value describing how much appoximated " +
     203                                                                              "gradients my differ from exact gradients. Set to 0 for exact calculation and in [0,1] otherwise. " +
     204                                                                              "Appropriate values for theta are between 0.1 and 0.7 (default = 0.5). CAUTION: exact calculation of " +
     205                                                                              "forces requires building a non-sparse N*N matrix where N is the number of data points. This may " +
     206                                                                              "exceed memory limitations. The function is designed to run on large (N > 5000) data sets. It may give" +
     207                                                                              " poor performance on very small data sets(it is better to use a standard t - SNE implementation on such data).", new DoubleValue(0)));
    203208      Parameters.Add(new FixedValueParameter<IntValue>(NewDimensionsParameterName, "Dimensionality of projected space (usually 2 for easy visual analysis)", new IntValue(2)));
    204209      Parameters.Add(new FixedValueParameter<IntValue>(MaxIterationsParameterName, "Maximum number of iterations for gradient descent.", new IntValue(1000)));
     
    207212      Parameters.Add(new FixedValueParameter<DoubleValue>(InitialMomentumParameterName, "The initial momentum in the gradient descent.", new DoubleValue(0.5)));
    208213      Parameters.Add(new FixedValueParameter<DoubleValue>(FinalMomentumParameterName, "The final momentum.", new DoubleValue(0.8)));
    209       Parameters.Add(new FixedValueParameter<DoubleValue>(EtaParameterName, "Gradient descent learning rate.", new DoubleValue(200)));
     214      Parameters.Add(new FixedValueParameter<DoubleValue>(EtaParameterName, "Gradient descent learning rate.", new DoubleValue(10)));
    210215      Parameters.Add(new FixedValueParameter<BoolValue>(SetSeedRandomlyParameterName, "If the seed should be random.", new BoolValue(true)));
    211216      Parameters.Add(new FixedValueParameter<IntValue>(SeedParameterName, "The seed used if it should not be random.", new IntValue(0)));
     
    217222      FinalMomentumParameter.Hidden = true;
    218223      StopLyingIterationParameter.Hidden = true;
    219       EtaParameter.Hidden = true;
     224      EtaParameter.Hidden = false;
    220225    }
    221226    #endregion
  • branches/TSNE/HeuristicLab.Algorithms.DataAnalysis/3.4/TSNE/TSNEStatic.cs

    r14807 r14837  
    168168
    169169      [StorableConstructor]
    170       public TSNEState(bool deserializing)  { }
     170      public TSNEState(bool deserializing) { }
    171171      public TSNEState(T[] data, IDistance<T> distance, IRandom random, int newDimensions, double perplexity, double theta, int stopLyingIter, int momSwitchIter, double momentum, double finalMomentum, double eta) {
    172172        this.distance = distance;
     
    205205        else CalculateApproximateSimilarities(data, distance, perplexity, out rowP, out colP, out valP);
    206206
    207         // Lie about the P-values
     207        // Lie about the P-values (factor is 4 in the MATLAB implementation)
    208208        if(exact) for(var i = 0; i < noDatapoints; i++) for(var j = 0; j < noDatapoints; j++) p[i, j] *= 12.0;
    209209        else for(var i = 0; i < rowP[noDatapoints]; i++) valP[i] *= 12.0;
     
    213213        for(var i = 0; i < noDatapoints; i++)
    214214          for(var j = 0; j < newDimensions; j++)
    215             newData[i, j] = rand.NextDouble() * .0001;  // TODO const  ?
     215            newData[i, j] = rand.NextDouble() * .0001;
    216216      }
    217217
     
    224224      private static void CalculateApproximateSimilarities(T[] data, IDistance<T> distance, double perplexity, out int[] rowP, out int[] colP, out double[] valP) {
    225225        // Compute asymmetric pairwise input similarities
    226         ComputeGaussianPerplexity(data, distance, out rowP, out colP, out valP, perplexity, (int)(3 * perplexity));        // TODO: why 3?
     226        ComputeGaussianPerplexity(data, distance, out rowP, out colP, out valP, perplexity, (int)(3 * perplexity));
    227227        // Symmetrize input similarities
    228228        int[] sRowP, symColP;
     
    270270
    271271        // Build ball tree on data set
    272         var tree = new VantagePointTree<IndexedItem<T>>(new IndexedItemDistance<T>(distance), objX);           // do we really want to re-create the tree on each call?
     272        var tree = new VantagePointTree<IndexedItem<T>>(new IndexedItemDistance<T>(distance), objX);
    273273
    274274        // Loop over all points to find nearest neighbors
     
    343343          var found = false;
    344344          var beta = 1.0;
    345           var minBeta = -double.MaxValue;
     345          var minBeta = double.MinValue;
    346346          var maxBeta = double.MaxValue;
    347347          const double tol = 1e-5;
     
    350350          // Iterate until we found a good perplexity
    351351          var iter = 0;
    352           while(!found && iter < 200) {       // TODO constant
     352          while(!found && iter < 200) {      // 200 iterations as in tSNE implementation by van der Maarten
    353353
    354354            // Compute Gaussian kernel row
     
    414414        var dd = new double[n, n];
    415415        var q = new double[n, n];
    416         ComputeSquaredEuclideanDistance(y, n, d, dd); // TODO: we use Euclidian distance regardless of the actual distance function
     416        ComputeSquaredEuclideanDistance(y, n, d, dd);
    417417
    418418        // Compute Q-matrix and normalization sum
     
    455455            for(var j = 0; j < d; j++) buff[j] = y[k, j];
    456456            for(var j = 0; j < d; j++) buff[j] -= y[colP[i], j];
    457             for(var j = 0; j < d; j++) q += buff[j] * buff[j];     // TODO: squared error is used here!
    458             q = 1.0 / (1.0 + q) / sumQ;
     457            for(var j = 0; j < d; j++) q += buff[j] * buff[j];
     458            q = (1.0 / (1.0 + q)) / sumQ;
    459459            c += valP[i] * Math.Log((valP[i] + float.Epsilon) / (q + float.Epsilon));
    460460          }
     
    580580        for(var j = 0; j < state.newDimensions; j++) {
    581581          state.gains[i, j] = Math.Sign(state.dY[i, j]) != Math.Sign(state.uY[i, j])
    582             ? state.gains[i, j] + .2
    583             : state.gains[i, j] * .8; // 20% up or 20% down // TODO: +0.2?!
    584 
    585           if(state.gains[i, j] < .01) state.gains[i, j] = .01; // TODO why limit the gains?
     582            ? state.gains[i, j] + .2  // +0.2 nd *0.8 are used in two separate implementations of tSNE -> seems to be correct
     583            : state.gains[i, j] * .8;
     584
     585          if(state.gains[i, j] < .01) state.gains[i, j] = .01;
    586586        }
    587587      }
     
    605605          for(var i = 0; i < state.noDatapoints; i++)
    606606            for(var j = 0; j < state.noDatapoints; j++)
    607               state.p[i, j] /= 12.0;                                   //XXX why 12?
     607              state.p[i, j] /= 12.0;
    608608        else
    609609          for(var i = 0; i < state.rowP[state.noDatapoints]; i++)
    610             state.valP[i] /= 12.0;                       // XXX are we not scaling all values?
     610            state.valP[i] /= 12.0;
    611611      }
    612612
     
    645645      // Compute the squared Euclidean distance matrix
    646646      var dd = new double[n, n];
    647       ComputeSquaredEuclideanDistance(y, n, d, dd); // TODO: we use Euclidian distance regardless which distance function is actually set!
     647      ComputeSquaredEuclideanDistance(y, n, d, dd);
    648648
    649649      // Compute Q-matrix and normalization sum
Note: See TracChangeset for help on using the changeset viewer.