UNPKG

als-statistics

Version:

Modular JS statistics toolkit for Node.js and the browser: descriptive stats, correlations (Pearson/Spearman/Kendall), t-tests & ANOVA (Student/Welch), reliability (Cronbach’s alpha), regression (linear/logistic), clustering (DBSCAN/HDBSCAN), and table/co

49 lines (46 loc) 1.89 kB
// Предполагаемый интерфейс: new DBSCAN(points, eps, minPts).run() // Возвращает массив меток кластеров длины points.length, где -1 = шум import DBSCAN from '../../../lib/analyze/dbscan/dbscan.js'; import { makeRng } from '../_rng.js'; function blobs(R, cfg) { const { centers, nPer, sigma } = cfg; const pts = {}; centers.forEach(([cx, cy],i) => { const xs = R.normal(cx, sigma, nPer); const ys = R.normal(cy, sigma, nPer); for (let i=0;i<nPer;i++) pts[`v${i}`] = [xs[i], ys[i]]; }); return pts; } export const dbscanTool = { id: 'dbscan', cases: 5, gen(seed, i) { const R = makeRng(`${seed}/db/${i}`); const cfg = { centers: [[0,0],[6,0],[0,6]], nPer: 40 + 5*(i%3), sigma: 0.6 + 0.1*(i%2) }; const pts = blobs(R, cfg); // eps выбираем заметно меньше межкластерного расстояния const eps = 1.2, minPts = 5; return { pts, eps, minPts }; }, compute({pts, eps, minPts}) { const {labels} = new DBSCAN(pts,{eps, minPts}); // метрики, устойчивые к переименованию кластеров: const k = new Set(labels.filter(l => l>=0)).size; const sizes = Object.values(labels.reduce((m,l)=>{ if (l>=0) m[l]=(m[l]||0)+1; return m; },{})).sort((a,b)=>b-a); const noise = labels.filter(l=>l<0).length / labels.length; return { k, sizes, noise }; }, compare(exp, got, approx) { if (got.k !== exp.k) throw new Error(`clusters k ${got.k} != ${exp.k}`); if (got.sizes.length !== exp.sizes.length) throw new Error('sizes length mismatch'); for (let i=0;i<exp.sizes.length;i++) if (got.sizes[i]!==exp.sizes[i]) throw new Error(`size[${i}] mismatch`); approx(got.noise, exp.noise); }, };