-
Notifications
You must be signed in to change notification settings - Fork 0
/
isomap.js
60 lines (55 loc) · 1.61 KB
/
isomap.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
(function() {
this.isomap = function(nn_inds, dists, dim) {
var geodesic = adj_matrix(nn_inds, dists);
// fill out matrix with shortest path distances
floyd_warshall(geodesic);
// do classical MDS
return mds(geodesic, dim);
};
function floyd_warshall(dists) {
var n = dists.nr, n1 = n-1, data = dists.data;
var k, i, j, d, di, dk, dik;
for (k = 0; k < n; k++) {
dk = dists.row(k);
for (i = 0; i < n1; i++) {
di = dists.row(i);
dik = di[k];
if (dik === Infinity) continue;
for (j = i+1; j < n; j++) {
d = dik + dk[j];
if (d < di[j]) {
di[j] = d;
data[j*n+i] = d;
}
}
}
}
};
function mean_center_sym(X) {
var i, j, n = X.nr;
// symmetric matrix means row_means == col_means
var row_means = new Float32Array(n);
for (i = 0; i < n; i++) {
row_means[i] = numeric.mean(X.row(i));
}
// each row has the same number of elements, so this is ok
var X_mean = numeric.mean(row_means);
var data = X.data, idx = 0, mu_r;
for (i = 0; i < n; i++) {
mu_r = row_means[i];
for (j = 0; j < n; j++) {
data[idx++] -= mu_r + row_means[j] - X_mean;
}
}
};
function mds(dists, num_dims) {
dists = dists.map(function(x){ return -0.5 * x * x; });
mean_center_sym(dists);
var tmp = hotelling_deflation(dists, num_dims, 100, 1e-12, 3),
lambdas = tmp[0], E = tmp[1];
for (var i = 0; i < num_dims; i++) {
numeric.muleq(E.row(i), Math.sqrt(lambdas[i]));
}
return numeric.transpose(E);
};
}).call(this);