Changeset 15451 for branches/Weighted TSNE/3.4/TSNE/TSNEStatic.cs
- Timestamp:
- 11/06/17 15:57:55 (6 years ago)
- 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 65 65 [StorableClass] 66 66 public class TSNEStatic<T> { 67 68 67 [StorableClass] 69 68 public sealed class TSNEState : DeepCloneable { … … 170 169 [StorableConstructor] 171 170 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) { 173 174 this.distance = distance; 174 175 this.random = random; … … 193 194 gains = new double[noDatapoints, newDimensions]; 194 195 for (var i = 0; i < noDatapoints; i++) 195 196 196 for (var j = 0; j < newDimensions; j++) 197 gains[i, j] = 1.0; 197 198 198 199 p = null; … … 212 213 var rand = new NormalDistributedRandom(random, 0, 1); 213 214 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 } 216 225 } 217 226 #endregion 218 227 219 228 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); 223 230 } 224 231 … … 226 233 private static void CalculateApproximateSimilarities(T[] data, IDistance<T> distance, double perplexity, out int[] rowP, out int[] colP, out double[] valP) { 227 234 // 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)); 229 236 // Symmetrize input similarities 230 237 int[] sRowP, symColP; … … 290 297 291 298 // Iterate until we found a good perplexity 292 var iter = 0; double sumP = 0; 299 var iter = 0; 300 double sumP = 0; 293 301 while (!found && iter < 200) { 294 295 302 // Compute Gaussian kernel row 296 303 for (var m = 0; m < k; m++) curP[m] = Math.Exp(-beta * distances[m + 1]); … … 307 314 if (hdiff < tol && -hdiff < tol) { 308 315 found = true; 309 } else { 316 } 317 else { 310 318 if (hdiff > 0) { 311 319 minBeta = beta; … … 314 322 else 315 323 beta = (beta + maxBeta) / 2.0; 316 } else { 324 } 325 else { 317 326 maxBeta = beta; 318 327 if (minBeta.IsAlmost(double.MinValue) || minBeta.IsAlmost(double.MaxValue)) … … 352 361 // Iterate until we found a good perplexity 353 362 var iter = 0; 354 while (!found && iter < 200) { 363 while (!found && iter < 200) { // 200 iterations as in tSNE implementation by van der Maarten 355 364 356 365 // Compute Gaussian kernel row … … 369 378 if (hdiff < tol && -hdiff < tol) { 370 379 found = true; 371 } else { 380 } 381 else { 372 382 if (hdiff > 0) { 373 383 minBeta = beta; … … 376 386 else 377 387 beta = (beta + maxBeta) / 2.0; 378 } else { 388 } 389 else { 379 390 maxBeta = beta; 380 391 if (minBeta.IsAlmost(double.MinValue) || minBeta.IsAlmost(double.MaxValue)) … … 425 436 q[n1, m] = 1 / (1 + dd[n1, m]); 426 437 sumQ += q[n1, m]; 427 } else q[n1, m] = double.Epsilon; 438 } 439 else q[n1, m] = double.Epsilon; 428 440 } 429 441 } … … 433 445 var c = .0; 434 446 for (var i = 0; i < n; i++) 435 436 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 } 438 450 return c; 439 451 } … … 463 475 } 464 476 private static void SymmetrizeMatrix(IReadOnlyList<int> rowP, IReadOnlyList<int> colP, IReadOnlyList<double> valP, out int[] symRowP, out int[] symColP, out double[] symValP) { 465 466 477 // Count number of elements and row counts of symmetric matrix 467 478 var n = rowP.Count - 1; … … 469 480 for (var j = 0; j < n; j++) { 470 481 for (var i = rowP[j]; i < rowP[j + 1]; i++) { 471 472 482 // Check whether element (col_P[i], n) is present 473 483 var present = false; … … 497 507 var offset = new int[n]; 498 508 for (var j = 0; j < n; j++) { 499 for (var i = rowP[j]; i < rowP[j + 1]; i++) { 509 for (var i = rowP[j]; i < rowP[j + 1]; i++) { // considering element(n, colP[i]) 500 510 501 511 // Check whether element (col_P[i], n) is present … … 552 562 int stopLyingIter = 0, int momSwitchIter = 0, double momentum = .5, 553 563 double finalMomentum = .8, double eta = 10.0 554 564 ) { 555 565 var state = CreateState(data, distance, random, newDimensions, perplexity, 556 566 theta, stopLyingIter, momSwitchIter, momentum, finalMomentum, eta); … … 565 575 int newDimensions = 2, double perplexity = 25, double theta = 0, 566 576 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); 570 580 } 571 581 … … 580 590 for (var j = 0; j < state.newDimensions; j++) { 581 591 state.gains[i, j] = Math.Sign(state.dY[i, j]) != Math.Sign(state.uY[i, j]) 582 ? state.gains[i, j] + .2 592 ? state.gains[i, j] + .2 // +0.2 nd *0.8 are used in two separate implementations of tSNE -> seems to be correct 583 593 : state.gains[i, j] * .8; 584 594 … … 590 600 // Perform gradient update (with momentum and gains) 591 601 for (var i = 0; i < state.noDatapoints; i++) 592 593 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]; 594 604 595 605 for (var i = 0; i < state.noDatapoints; i++) 596 597 606 for (var j = 0; j < state.newDimensions; j++) 607 state.newData[i, j] = state.newData[i, j] + state.uY[i, j]; 598 608 599 609 // Make solution zero-mean … … 604 614 if (state.exact) 605 615 for (var i = 0; i < state.noDatapoints; i++) 606 607 616 for (var j = 0; j < state.noDatapoints; j++) 617 state.p[i, j] /= 12.0; 608 618 else 609 619 for (var i = 0; i < state.rowP[state.noDatapoints]; i++) … … 634 644 // Compute final t-SNE gradient 635 645 for (var i = 0; i < n; i++) 636 637 638 646 for (var j = 0; j < d; j++) { 647 dC[i, j] = posF[i, j] - negF[i, j] / sumQ; 648 } 639 649 } 640 650
Note: See TracChangeset
for help on using the changeset viewer.