Basic k-nearest-neighbour
by Scott Kaye
JavaScript
// Small function to convert things like #ff00ff or #f0f to [255, 0, 255]
const hexToRgb = hex => {
hex = hex.replace(/#/,"");
if (!(hex.length - 3)) hex = [...hex].map(c => c + c).join("");
return hex
.match(/[a-f0-9]{2}/gi)
.map(n => parseInt(n, 16));
};
class KNN {
constructor() {
this.nodes = [];
};
normalize() {
let values = [];
// Load all values from each cell into an array
this.nodes.forEach(node => {
node.in.forEach((v, i) => {
if (!values[i]) values[i] = [];
values[i].push(v);
});
});
// Find maximum and minimum values in each cell
this.maxes = values.map(arr => Math.max.apply(Math.max, arr));
this.mins = values.map(arr => Math.min.apply(Math.min, arr));
// Normalize each cell in each node
this.nodes.forEach(node => {
node.normalized = node.in.map((v, i) => (v / this.maxes[i]) + this.mins[i]);
});
};
// Can call train([ array of objects with in and out keys ]) or train(input, output)
train(nodes, out) {
if (out === undefined) {
this.nodes.push.apply(this.nodes, nodes);
this.normalize();
}
else {
this.nodes.push({
in: nodes,
out: out
});
this.normalize();
}
};
solve(problem, sweetSpot = 0.15) {
// Normalize problem
let normalizedProblem = problem.map((v, i) => (v / this.maxes[i]) + this.mins[i]);
// Calculate match of normalized problem with each normalized node
// The "match" value here is an arbitrary meaningless score; higher number = better match
// A match of 0 means no points were lost, and is the highest score possible.
let newNodes = this.nodes.map(node => {
node.match = 0;
normalizedProblem.forEach((v, i) => {
let diff = node.normalized[i] - v;
node.match += diff < sweetSpot ? diff : -diff;
});
return node;
});
// Sort by match rating (higher is better)
newNodes.sort((a, b) => {
if...