| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 | const	Distance = require("./distance.js"),	eudist = Distance.eudist,	dist = Distance.dist;module.exports = {	kmrand(data,k) {		var map = {}, ks = [], t = k<<2;		var len = data.length;		var multi = data[0].length>0;		while(ks.length<k && (t--)>0) {			let d = data[Math.floor(Math.random()*len)];			let key = multi? d.join("_") : `${d}`;			if(!map[key]) {				map[key] = true;				ks.push(d);			}		}		if(ks.length<k) throw new Error("Error initializating clusters");		else return ks;	},	/**	 * K-means++ initial centroid selection	 */	kmpp(data,k) {		var distance = data[0].length? eudist : dist;		var ks = [], len = data.length;		var multi = data[0].length>0;		var map = {};		// First random centroid		var c = data[Math.floor(Math.random()*len)];		var key = multi? c.join("_") : `${c}`;		ks.push(c);		map[key] = true;		// Retrieve next centroids		while(ks.length<k) {			// Min Distances between current centroids and data points			let dists = [], lk = ks.length;			let dsum = 0, prs = [];			for(let i=0;i<len;i++) {				let min = Infinity;				for(let j=0;j<lk;j++) {					let dist = distance(data[i],ks[j]);					if(dist<=min) min = dist;				}				dists[i] = min;			}			// Sum all min distances			for(let i=0;i<len;i++) {				dsum += dists[i]			}			// Probabilities and cummulative prob (cumsum)			for(let i=0;i<len;i++) {				prs[i] = {i:i, v:data[i],	pr:dists[i]/dsum, cs:0}			}			// Sort Probabilities			prs.sort((a,b)=>a.pr-b.pr);			// Cummulative Probabilities			prs[0].cs = prs[0].pr;			for(let i=1;i<len;i++) {				prs[i].cs = prs[i-1].cs + prs[i].pr;			}			// Randomize			let rnd = Math.random();			// Gets only the items whose cumsum >= rnd			let idx = 0;			while(idx<len-1 && prs[idx++].cs<rnd);			ks.push(prs[idx-1].v);			/*			let done = false;			while(!done) {				// this is our new centroid				c = prs[idx-1].v				key = multi? c.join("_") : `${c}`;				if(!map[key]) {					map[key] = true;					ks.push(c);					done = true;				}				else {					idx++;				}			}			*/		}		return ks;	}}
 |