@thi.ng/k-means
Version:
k-means & k-medians with customizable distance functions and centroid initializations for n-D vectors
45 lines (44 loc) • 1.31 kB
JavaScript
import { mean, vmean } from "@thi.ng/vectors/mean";
import { vmedian } from "@thi.ng/vectors/median";
const meanCut = (k, samples) => computeCutWith(vmean, samples, samples[0].length, k).map(
(x) => mean([], x)
);
const medianCut = (k, samples) => computeCutWith(vmedian, samples, samples[0].length, k).map(
(x) => mean([], x)
);
const computeCutWith = (cut, samples, dim, depth) => {
if (!samples.length) return [];
if (depth <= 1) return [samples];
const channels = new Array(dim);
let maxRange = 0, maxRangeID = 0, i = 0, j, n = samples.length, min, max, value, range, channel;
for (; i < dim; i++) {
channel = channels[i] = new Array(n);
min = Infinity;
max = -Infinity;
for (j = 0; j < n; j++) {
value = channel[j] = samples[j][i];
if (value < min) min = value;
if (value > max) max = value;
}
range = max - min;
if (range > maxRange) {
maxRange = range;
maxRangeID = i;
}
}
channel = channels[maxRangeID];
const split = cut(channel);
const lo = [];
const hi = [];
for (j = 0; j < n; j++) {
(channel[j] <= split ? lo : hi).push(samples[j]);
}
return computeCutWith(cut, lo, dim, depth >> 1).concat(
computeCutWith(cut, hi, dim, depth + 1 >> 1)
);
};
export {
computeCutWith,
meanCut,
medianCut
};