Skip to content

Instantly share code, notes, and snippets.

@noam87
Last active August 29, 2015 14:05
Show Gist options
  • Save noam87/e5dc6162f7a96a745db3 to your computer and use it in GitHub Desktop.
Save noam87/e5dc6162f7a96a745db3 to your computer and use it in GitHub Desktop.
kmeans?
var sample = [
[0,1],
[0,2],
[0,3],
[3,8],
[3,9],
[4,8],
[4,10],
[3,1],
[5,3],
[6,7],
[8,3],
[3,4],
[6,3],
[1,10],
[9,3],
[4,7],
[6,3],
[2,5],
[7,9]
]
var k_values = [
[2,1],
[5,4]
]
var old_ks = k_values;
var new_ks = kMeans(old_ks, sample);
var inn = 0;
// can't do recursive cause will hit stack limit
while (!equalKs(old_ks, new_ks)) {
console.log("ks: ", old_ks ,"--", new_ks);
old_ks = new_ks;
new_ks = kMeans(new_ks, sample);
// just in case
inn += 1;
if (inn > 1000) break;
}
console.log("final: ", new_ks);
// functions
function equalKs(k1, k2) {
var res = true;
k1.forEach(function(vec,i) {
vec.forEach(function(v,_i) {
if (k1[i][_i] !== k2[i][_i]) res = false;
});
});
return res;
}
function kMeans(ks, vectors) {
var clusters = [];
ks.forEach(function() { clusters.push([])})
vectors.forEach(function(v,i) {
var index = closestTo(v, ks);
clusters[index].push(v)
});
var new_ks = [];
ks.forEach(function(v,i) {
new_ks.push(geometricCenter(clusters[i]));
});
return new_ks;
}
function closestTo(vec, ks) {
var k_distances = [];
ks.forEach(function(v,i) {
k_distances.push(sumOfSquares(vec,v));
});
return k_distances.indexOf(Math.min.apply(Math, k_distances));
}
function geometricCenter(vs) {
var sums = [];
vs[0].forEach(function(v,i) {
var sum = 0;
vs.forEach(function(_v,_i) {
sum += vs[_i][i];
});
sums.push(sum);
});
var vec = [];
sums.forEach(function(v,i) {
var res = Math.round((v/vs.length)*1000)/1000
vec.push(res);
});
return vec;
}
function sumOfSquares(v1, v2) {
var sum = 0;
v1.forEach(function(v,i) {
sum += (v2[i] - v1[i])*(v2[i] - v1[i]);
})
return sum;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment