diff --git a/kohonen.cpp b/kohonen.cpp index 3579b9d2..bf324605 100644 --- a/kohonen.cpp +++ b/kohonen.cpp @@ -17,6 +17,8 @@ struct sample { vector data; +vector samples_shown; + int whattodraw[3]; struct neuron { @@ -32,6 +34,8 @@ kohvec weights; vector net; +int neuronId(neuron& n) { return &n - &(net[0]); } + void alloc(kohvec& k) { k.resize(cols); } bool neurons_indexed = false; @@ -67,6 +71,7 @@ void loadsamples(const char *fname) { if(fscanf(f, "%d", &cols) != 1) { fclose(f); return; } while(true) { sample s; + bool shown = false; alloc(s.val); if(feof(f)) break; for(int i=0; ilandparam, n.where->landparam = (&n - &net[0]); + for(neuron& n: net) n.lpbak = n.where->landparam, n.where->landparam = neuronId(n); } else { for(neuron& n: net) n.where->landparam = n.lpbak; @@ -144,6 +151,10 @@ void coloring() { int c = whattodraw[pid]; vector listing; for(neuron& n: net) switch(c) { + case -4: + listing.push_back(n.samples); + break; + case -3: if(distfrom) listing.push_back(vnorm(n.net, distfrom->net)); @@ -195,14 +206,16 @@ void analyze() { for(neuron& n: net) n.samples = 0; - for(int id=0; idbase = w.where; vdata[id].m->at = spin(2*M_PI*w.csample / w.samples) * xpush(.25 * (w.samples-1) / w.samples); @@ -262,26 +275,119 @@ struct cellcrawler { } }; -cellcrawler s0, s1; // hex and non-hex +// traditionally Gaussian blur is used in the Kohonen algoritm +// but it does not seem to make much sense in hyperbolic geometry +// especially wrapped one. +// GAUSSIAN==1: use the Gaussian blur +// GAUSSIAN==0: simulate the dispersion on our network + +#ifndef GAUSSIAN +#define GAUSSIAN 0 +#endif + +cellcrawler scc[2]; // hex and non-hex + +#if GAUSSIAN==0 +double dispersion_precision = .0001; +int dispersion_each = 1; + +vector> dispersion[2]; + +int dispersion_count; +#endif void buildcellcrawler(cell *c) { - (c->type == 6 ? s0 : s1).build(cellwalker(c,0)); + int sccid = c->type != 6; + + cellcrawler& cr = scc[sccid]; + cr.build(cellwalker(c,0)); + +#if GAUSSIAN==0 + vector curtemp; + vector newtemp; + vector qty; + vector > pairs; + int N = size(net); + + curtemp.resize(N, 0); + newtemp.resize(N, 0); + qty.resize(N, 0); + + for(int i=0; i vmin * 1.5; iter++) { + if(iter % dispersion_each == 0) { + d.emplace_back(N); + auto& dispvec = d.back(); + for(int i=0; i vmax) vmax = curtemp[i]; + } + + dispersion_count = size(d); + printf("Dispersion count = %d\n", dispersion_count); +#endif } bool finished() { return t == 0; } void step() { - double sigma = maxdist * t / (perdist*(double) mul); + if(t == 0) return; + +#if GAUSSIAN==1 + double sigma = maxdist * t / (perdist*(double) mul); +#else + int dispid = int(dispersion_count * (t-1.) / tmax); +#endif + // double sigma = maxdist * exp(-t / t1); int pct = (int) (100 * ((t*(double) mul) / perdist)); if(pct != lpct) { lpct = pct; analyze(); +#if GAUSSIAN==1 printf("t = %6d/%2dx%6d pct = %3d sigma=%10.7lf maxudist=%10.7lf\n", t, mul, perdist, pct, sigma, maxudist); +#else + printf("t = %6d/%2dx%6d pct = %3d dispid=%5d maxudist=%10.7lf\n", t, mul, perdist, pct, dispid, maxudist); +#endif } int id = hrand(samples); neuron& n = winner(id); + whowon[id] = &n; + /* for(neuron& n2: net) { @@ -294,13 +400,22 @@ void step() { n2.net[k] += nu * (irisdata[id][k] - n2.net[k]); } */ - cellcrawler& s = n.where->type == 6 ? s0 : s1; + int sccid = n.where->type != 6; + cellcrawler& s = scc[sccid]; s.sprawl(cellwalker(n.where, 0)); + +#if GAUSSIAN==0 + auto it = dispersion[sccid][dispid].begin(); +#endif for(auto& sd: s.data) { neuron *n2 = getNeuron(sd.target.c); if(!n2) continue; double nu = maxfac; +#if GAUSSIAN==0 + nu *= *(it++); +#else nu *= exp(-sqr(sd.dist/sigma)); +#endif for(int k=0; knet[k] += nu * (data[id].val[k] - n2->net[k]); } @@ -347,6 +462,9 @@ void run(const char *fname, int _perdist, double _maxfac) { printf("samples = %d cells = %d maxdist = %d\n", samples, cells, maxdist); +#if GAUSSIAN==0 + dispersion_count = 0; +#endif c1 = currentmap->gamestart(); cell *c2 = createMov(c1, 0); buildcellcrawler(c1); @@ -354,7 +472,7 @@ void run(const char *fname, int _perdist, double _maxfac) { lpct = -46130; mul = 1; - t = perdist*mul; + tmax = t = perdist*mul; step(); for(int i=0; i<3; i++) whattodraw[i] = -2; analyze(); @@ -364,14 +482,16 @@ void describe(cell *c) { if(cmode & sm::HELP) return; neuron *n = getNeuronSlow(c); if(!n) return; - help += "cell number: " + its(n - &net[0]) + "\n"; + help += "cell number: " + its(neuronId(*n)) + "\n"; help += "parameters:"; for(int k=0; knet[k]); help += ", u-matrix = " + fts(n->udist); help += "\n"; + int qty = 0; for(int s=0; s= 20) break; } } @@ -402,6 +522,20 @@ void kload(const char *fname) { analyze(); } +void kclassify(const char *fname) { + for(neuron& n: net) n.samples = 0; + + FILE *f = fopen(fname, "wt"); + for(int id=0; id= '1' && uni <= '3') { int i = uni - '1'; whattodraw[i]++; - if(whattodraw[i] == cols) whattodraw[i] = -3; + if(whattodraw[i] == cols) whattodraw[i] = -4; coloring(); return true; } diff --git a/rogueviz.cpp b/rogueviz.cpp index a07aa485..2d13cac9 100644 --- a/rogueviz.cpp +++ b/rogueviz.cpp @@ -1699,6 +1699,11 @@ int readArgs() { while(!kohonen::finished()) kohonen::step(); shift(); kohonen::ksave(args()); } + else if(argis("-somclassify")) { + PHASE(3); + while(!kohonen::finished()) kohonen::step(); + shift(); kohonen::kclassify(args()); + } else if(argis("-somload")) { PHASE(3); shift(); kohonen::kload(args());