Skip to content

Commit

Permalink
Fixed the Projector infinite loop issue
Browse files Browse the repository at this point in the history
When closure compilation is turned on, it uses prototype definitions to
mangle and optimize the calls. This made some method not defined
statically problematic and it seems to have turned `numeric.div` into
something else.

According to numericjs, unlike other methods we use like dot and
transpose, is genearted dynamically from numeric.ops2 and Closure seems
to not handle it well.
https://github.com/sloisel/numeric/blob/master/src/numeric.js

Concretely, it turns numeric.div(a, b) into mangledName(numeric, a) and
this led division operation to infinitely loop.
```
c = d.slice(0, a.PCA_SAMPLE_SIZE);
c = Oa(numeric, numeric.dot(numeric.transpose(c), c));
var e = numeric.svd(c)
```
In above code snippet, `Oa` is the `div` method.
  • Loading branch information
stephanwlee committed Oct 2, 2018
1 parent e9e9e65 commit 3935e4f
Showing 1 changed file with 13 additions and 10 deletions.
23 changes: 13 additions & 10 deletions tensorboard/plugins/projector/vz_projector/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,18 @@ export class DataSet {
if (dim > PCA_SAMPLE_DIM) {
vectors = vector.projectRandom(vectors, PCA_SAMPLE_DIM);
}
let sampledVectors = vectors.slice(0, PCA_SAMPLE_SIZE);

let sigma = numeric.div(
numeric.dot(numeric.transpose(sampledVectors), sampledVectors),
sampledVectors.length);
let svd = numeric.svd(sigma);

let variances: number[] = svd.S;
const sampledVectors = vectors.slice(0, PCA_SAMPLE_SIZE);
const {dot, transpose, svd: numericSvd} = numeric;
// numeric dynamically generates `numeric.div` and Closure compiler has
// incorrectly compiles `numeric.div` property accessor. We use below
// signature to prevent Closure from mangling and guessing.
const div = numeric['div'];

const scalar = dot(transpose(sampledVectors), sampledVectors);
const sigma = div(scalar, sampledVectors.length);
const svd = numericSvd(sigma);

const variances: number[] = svd.S;
let totalVariance = 0;
for (let i = 0; i < variances.length; ++i) {
totalVariance += variances[i];
Expand All @@ -277,7 +281,6 @@ export class DataSet {
variances[i] /= totalVariance;
}
this.fracVariancesExplained = variances;

let U: number[][] = svd.U;
let pcaVectors = vectors.map(vector => {
let newV = new Float32Array(NUM_PCA_COMPONENTS);
Expand Down Expand Up @@ -392,7 +395,7 @@ export class DataSet {
let sampledIndices =
this.shuffledDataIndices.slice(0, TSNE_SAMPLE_SIZE);
let labels = new Array(sampledIndices.length);
sampledIndices.forEach((index, i) =>
sampledIndices.forEach((index, i) =>
labels[i] = this.points[index].metadata[superviseColumn].toString());
this.superviseLabels = labels;
}
Expand Down

0 comments on commit 3935e4f

Please sign in to comment.