Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
11/06/17 15:57:55 (6 years ago)
Author:
bwerth
Message:

#2850 created branch & added WeightedEuclideanDistance

Location:
branches/Weighted TSNE
Files:
1 added
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/Weighted TSNE/3.4/TSNE/TSNEStatic.cs

    r15207 r15451  
    6565  [StorableClass]
    6666  public class TSNEStatic<T> {
    67 
    6867    [StorableClass]
    6968    public sealed class TSNEState : DeepCloneable {
     
    170169      [StorableConstructor]
    171170      public TSNEState(bool deserializing) { }
    172       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) {
     171
     172      public TSNEState(T[] data, IDistance<T> distance, IRandom random, int newDimensions, double perplexity,
     173        double theta, int stopLyingIter, int momSwitchIter, double momentum, double finalMomentum, double eta, bool randomInit) {
    173174        this.distance = distance;
    174175        this.random = random;
     
    193194        gains = new double[noDatapoints, newDimensions];
    194195        for (var i = 0; i < noDatapoints; i++)
    195           for (var j = 0; j < newDimensions; j++)
    196             gains[i, j] = 1.0;
     196        for (var j = 0; j < newDimensions; j++)
     197          gains[i, j] = 1.0;
    197198
    198199        p = null;
     
    212213        var rand = new NormalDistributedRandom(random, 0, 1);
    213214        for (var i = 0; i < noDatapoints; i++)
    214           for (var j = 0; j < newDimensions; j++)
    215             newData[i, j] = rand.NextDouble() * .0001;
     215        for (var j = 0; j < newDimensions; j++)
     216          newData[i, j] = rand.NextDouble() * .0001;
     217
     218        if (data[0] is IReadOnlyList<double> && !randomInit) {
     219          for (var i = 0; i < noDatapoints; i++)
     220          for (var j = 0; j < newDimensions; j++) {
     221            var row = (IReadOnlyList<double>) data[i];
     222            newData[i, j] = row[j % row.Count];
     223          }
     224        }
    216225      }
    217226      #endregion
    218227
    219228      public double EvaluateError() {
    220         return exact ?
    221           EvaluateErrorExact(p, newData, noDatapoints, newDimensions) :
    222           EvaluateErrorApproximate(rowP, colP, valP, newData, theta);
     229        return exact ? EvaluateErrorExact(p, newData, noDatapoints, newDimensions) : EvaluateErrorApproximate(rowP, colP, valP, newData, theta);
    223230      }
    224231
     
    226233      private static void CalculateApproximateSimilarities(T[] data, IDistance<T> distance, double perplexity, out int[] rowP, out int[] colP, out double[] valP) {
    227234        // Compute asymmetric pairwise input similarities
    228         ComputeGaussianPerplexity(data, distance, out rowP, out colP, out valP, perplexity, (int)(3 * perplexity));
     235        ComputeGaussianPerplexity(data, distance, out rowP, out colP, out valP, perplexity, (int) (3 * perplexity));
    229236        // Symmetrize input similarities
    230237        int[] sRowP, symColP;
     
    290297
    291298          // Iterate until we found a good perplexity
    292           var iter = 0; double sumP = 0;
     299          var iter = 0;
     300          double sumP = 0;
    293301          while (!found && iter < 200) {
    294 
    295302            // Compute Gaussian kernel row
    296303            for (var m = 0; m < k; m++) curP[m] = Math.Exp(-beta * distances[m + 1]);
     
    307314            if (hdiff < tol && -hdiff < tol) {
    308315              found = true;
    309             } else {
     316            }
     317            else {
    310318              if (hdiff > 0) {
    311319                minBeta = beta;
     
    314322                else
    315323                  beta = (beta + maxBeta) / 2.0;
    316               } else {
     324              }
     325              else {
    317326                maxBeta = beta;
    318327                if (minBeta.IsAlmost(double.MinValue) || minBeta.IsAlmost(double.MaxValue))
     
    352361          // Iterate until we found a good perplexity
    353362          var iter = 0;
    354           while (!found && iter < 200) {      // 200 iterations as in tSNE implementation by van der Maarten
     363          while (!found && iter < 200) { // 200 iterations as in tSNE implementation by van der Maarten
    355364
    356365            // Compute Gaussian kernel row
     
    369378            if (hdiff < tol && -hdiff < tol) {
    370379              found = true;
    371             } else {
     380            }
     381            else {
    372382              if (hdiff > 0) {
    373383                minBeta = beta;
     
    376386                else
    377387                  beta = (beta + maxBeta) / 2.0;
    378               } else {
     388              }
     389              else {
    379390                maxBeta = beta;
    380391                if (minBeta.IsAlmost(double.MinValue) || minBeta.IsAlmost(double.MaxValue))
     
    425436              q[n1, m] = 1 / (1 + dd[n1, m]);
    426437              sumQ += q[n1, m];
    427             } else q[n1, m] = double.Epsilon;
     438            }
     439            else q[n1, m] = double.Epsilon;
    428440          }
    429441        }
     
    433445        var c = .0;
    434446        for (var i = 0; i < n; i++)
    435           for (var j = 0; j < n; j++) {
    436             c += p[i, j] * Math.Log((p[i, j] + float.Epsilon) / (q[i, j] + float.Epsilon));
    437           }
     447        for (var j = 0; j < n; j++) {
     448          c += p[i, j] * Math.Log((p[i, j] + float.Epsilon) / (q[i, j] + float.Epsilon));
     449        }
    438450        return c;
    439451      }
     
    463475      }
    464476      private static void SymmetrizeMatrix(IReadOnlyList<int> rowP, IReadOnlyList<int> colP, IReadOnlyList<double> valP, out int[] symRowP, out int[] symColP, out double[] symValP) {
    465 
    466477        // Count number of elements and row counts of symmetric matrix
    467478        var n = rowP.Count - 1;
     
    469480        for (var j = 0; j < n; j++) {
    470481          for (var i = rowP[j]; i < rowP[j + 1]; i++) {
    471 
    472482            // Check whether element (col_P[i], n) is present
    473483            var present = false;
     
    497507        var offset = new int[n];
    498508        for (var j = 0; j < n; j++) {
    499           for (var i = rowP[j]; i < rowP[j + 1]; i++) {                                  // considering element(n, colP[i])
     509          for (var i = rowP[j]; i < rowP[j + 1]; i++) { // considering element(n, colP[i])
    500510
    501511            // Check whether element (col_P[i], n) is present
     
    552562      int stopLyingIter = 0, int momSwitchIter = 0, double momentum = .5,
    553563      double finalMomentum = .8, double eta = 10.0
    554       ) {
     564    ) {
    555565      var state = CreateState(data, distance, random, newDimensions, perplexity,
    556566        theta, stopLyingIter, momSwitchIter, momentum, finalMomentum, eta);
     
    565575      int newDimensions = 2, double perplexity = 25, double theta = 0,
    566576      int stopLyingIter = 0, int momSwitchIter = 0, double momentum = .5,
    567       double finalMomentum = .8, double eta = 10.0
    568       ) {
    569       return new TSNEState(data, distance, random, newDimensions, perplexity, theta, stopLyingIter, momSwitchIter, momentum, finalMomentum, eta);
     577      double finalMomentum = .8, double eta = 10.0, bool randomInit = true
     578    ) {
     579      return new TSNEState(data, distance, random, newDimensions, perplexity, theta, stopLyingIter, momSwitchIter, momentum, finalMomentum, eta, randomInit);
    570580    }
    571581
     
    580590        for (var j = 0; j < state.newDimensions; j++) {
    581591          state.gains[i, j] = Math.Sign(state.dY[i, j]) != Math.Sign(state.uY[i, j])
    582             ? state.gains[i, j] + .2  // +0.2 nd *0.8 are used in two separate implementations of tSNE -> seems to be correct
     592            ? state.gains[i, j] + .2 // +0.2 nd *0.8 are used in two separate implementations of tSNE -> seems to be correct
    583593            : state.gains[i, j] * .8;
    584594
     
    590600      // Perform gradient update (with momentum and gains)
    591601      for (var i = 0; i < state.noDatapoints; i++)
    592         for (var j = 0; j < state.newDimensions; j++)
    593           state.uY[i, j] = state.currentMomentum * state.uY[i, j] - state.eta * state.gains[i, j] * state.dY[i, j];
     602      for (var j = 0; j < state.newDimensions; j++)
     603        state.uY[i, j] = state.currentMomentum * state.uY[i, j] - state.eta * state.gains[i, j] * state.dY[i, j];
    594604
    595605      for (var i = 0; i < state.noDatapoints; i++)
    596         for (var j = 0; j < state.newDimensions; j++)
    597           state.newData[i, j] = state.newData[i, j] + state.uY[i, j];
     606      for (var j = 0; j < state.newDimensions; j++)
     607        state.newData[i, j] = state.newData[i, j] + state.uY[i, j];
    598608
    599609      // Make solution zero-mean
     
    604614        if (state.exact)
    605615          for (var i = 0; i < state.noDatapoints; i++)
    606             for (var j = 0; j < state.noDatapoints; j++)
    607               state.p[i, j] /= 12.0;
     616          for (var j = 0; j < state.noDatapoints; j++)
     617            state.p[i, j] /= 12.0;
    608618        else
    609619          for (var i = 0; i < state.rowP[state.noDatapoints]; i++)
     
    634644      // Compute final t-SNE gradient
    635645      for (var i = 0; i < n; i++)
    636         for (var j = 0; j < d; j++) {
    637           dC[i, j] = posF[i, j] - negF[i, j] / sumQ;
    638         }
     646      for (var j = 0; j < d; j++) {
     647        dC[i, j] = posF[i, j] - negF[i, j] / sumQ;
     648      }
    639649    }
    640650
Note: See TracChangeset for help on using the changeset viewer.