mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2025-07-08 12:22:49 +00:00
rogueviz::kohonen:: additional options (save/load classify in binary format, visualize edges
This commit is contained in:
parent
ddf3ca83cf
commit
6e1983baa9
@ -1,7 +1,7 @@
|
|||||||
// Hyperbolic Rogue
|
// Hyperbolic Rogue
|
||||||
// Copyright (C) 2011-2018 Zeno and Tehora Rogue, see 'hyper.cpp' for details
|
// Copyright (C) 2011-2018 Zeno and Tehora Rogue, see 'hyper.cpp' for details
|
||||||
|
|
||||||
// Kohonen's self-organizing networks.
|
// Kohonen's self-organizing maps.
|
||||||
// This is a part of RogueViz, not a part of HyperRogue.
|
// This is a part of RogueViz, not a part of HyperRogue.
|
||||||
|
|
||||||
namespace rogueviz { namespace kohonen {
|
namespace rogueviz { namespace kohonen {
|
||||||
@ -27,7 +27,8 @@ struct neuron {
|
|||||||
double udist;
|
double udist;
|
||||||
int lpbak;
|
int lpbak;
|
||||||
int col;
|
int col;
|
||||||
int samples, csample, bestsample;
|
int allsamples, drawn_samples, csample, bestsample;
|
||||||
|
neuron() { drawn_samples = allsamples = bestsample = 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
vector<string> colnames;
|
vector<string> colnames;
|
||||||
@ -182,7 +183,7 @@ void coloring() {
|
|||||||
vector<double> listing;
|
vector<double> listing;
|
||||||
for(neuron& n: net) switch(c) {
|
for(neuron& n: net) switch(c) {
|
||||||
case -4:
|
case -4:
|
||||||
listing.push_back(log(5+n.samples));
|
listing.push_back(log(5+n.allsamples));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case -3:
|
case -3:
|
||||||
@ -215,6 +216,32 @@ void coloring() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void distribute_neurons() {
|
||||||
|
whowon.resize(samples);
|
||||||
|
|
||||||
|
for(neuron& n: net) n.drawn_samples = 0;
|
||||||
|
|
||||||
|
for(int s: samples_shown) {
|
||||||
|
auto& w = winner(s);
|
||||||
|
whowon[s] = &w;
|
||||||
|
w.drawn_samples++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ld rad = .25 * scalef;
|
||||||
|
|
||||||
|
for(int id=0; id<isize(samples_shown); id++) {
|
||||||
|
int s = samples_shown[id];
|
||||||
|
auto& w = *whowon[s];
|
||||||
|
vdata[id].m->base = w.where;
|
||||||
|
vdata[id].m->at =
|
||||||
|
spin(2*M_PI*w.csample / w.drawn_samples) * xpush(rad * (w.drawn_samples-1) / w.drawn_samples);
|
||||||
|
w.csample++;
|
||||||
|
}
|
||||||
|
|
||||||
|
shmup::fixStorage();
|
||||||
|
setindex(false);
|
||||||
|
}
|
||||||
|
|
||||||
void analyze() {
|
void analyze() {
|
||||||
|
|
||||||
setindex(true);
|
setindex(true);
|
||||||
@ -233,31 +260,7 @@ void analyze() {
|
|||||||
maxudist = max(maxudist, n.udist);
|
maxudist = max(maxudist, n.udist);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!noshow) {
|
if(!noshow) distribute_neurons();
|
||||||
|
|
||||||
whowon.resize(samples);
|
|
||||||
|
|
||||||
for(neuron& n: net) n.samples = 0;
|
|
||||||
|
|
||||||
for(int id=0; id<isize(samples_shown); id++) {
|
|
||||||
int s = samples_shown[id];
|
|
||||||
auto& w = winner(s);
|
|
||||||
whowon[s] = &w;
|
|
||||||
w.samples++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int id=0; id<isize(samples_shown); id++) {
|
|
||||||
int s = samples_shown[id];
|
|
||||||
auto& w = *whowon[s];
|
|
||||||
vdata[id].m->base = w.where;
|
|
||||||
vdata[id].m->at =
|
|
||||||
spin(2*M_PI*w.csample / w.samples) * xpush(.25 * (w.samples-1) / w.samples);
|
|
||||||
w.csample++;
|
|
||||||
}
|
|
||||||
|
|
||||||
shmup::fixStorage();
|
|
||||||
setindex(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
coloring();
|
coloring();
|
||||||
}
|
}
|
||||||
@ -557,10 +560,29 @@ void uninit(int initto) {
|
|||||||
if(inited > initto) inited = initto;
|
if(inited > initto) inited = initto;
|
||||||
}
|
}
|
||||||
|
|
||||||
void showsample(int id) {
|
int max_group = 10;
|
||||||
for(int ii: samples_shown)
|
|
||||||
if(ii == id)
|
vector<double> bdiffs;
|
||||||
return;
|
vector<unsigned short> bids;
|
||||||
|
vector<double> bdiffn;
|
||||||
|
|
||||||
|
int showsample(int id) {
|
||||||
|
for(int i=0; i<isize(samples_shown); i++)
|
||||||
|
if(samples_shown[i] == id)
|
||||||
|
return i;
|
||||||
|
if(bids.size()) {
|
||||||
|
if(net[bids[id]].drawn_samples >= max_group) {
|
||||||
|
ld bdist = 1e18;
|
||||||
|
int whichid = -1;
|
||||||
|
for(int i=0; i<isize(samples_shown); i++)
|
||||||
|
if(bids[samples_shown[i]] == bids[id]) {
|
||||||
|
ld cdist = vnorm(data[samples_shown[i]].val, data[id].val);
|
||||||
|
if(cdist < bdist) bdist = cdist, whichid = i;
|
||||||
|
}
|
||||||
|
return whichid;
|
||||||
|
}
|
||||||
|
net[bids[id]].drawn_samples++;
|
||||||
|
}
|
||||||
int i = vdata.size();
|
int i = vdata.size();
|
||||||
samples_shown.push_back(id);
|
samples_shown.push_back(id);
|
||||||
vdata.emplace_back();
|
vdata.emplace_back();
|
||||||
@ -569,6 +591,7 @@ void showsample(int id) {
|
|||||||
v.cp = dftcolor;
|
v.cp = dftcolor;
|
||||||
createViz(i, cwt.c, Id);
|
createViz(i, cwt.c, Id);
|
||||||
v.m->store();
|
v.m->store();
|
||||||
|
return isize(samples_shown) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void showsample(string s) {
|
void showsample(string s) {
|
||||||
@ -584,13 +607,9 @@ void showsample(string s) {
|
|||||||
void showbestsamples() {
|
void showbestsamples() {
|
||||||
vector<int> samplesbak;
|
vector<int> samplesbak;
|
||||||
for(auto& n: net)
|
for(auto& n: net)
|
||||||
if(n.samples)
|
if(n.allsamples)
|
||||||
showsample(n.bestsample);
|
showsample(n.bestsample);
|
||||||
analyze();
|
analyze();
|
||||||
for(auto& n: net) n.samples = 0;
|
|
||||||
for(int i=0; i<samples; i++)
|
|
||||||
if(whowon[i])
|
|
||||||
whowon[i]->samples++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int kohrestrict = 1000000;
|
int kohrestrict = 1000000;
|
||||||
@ -685,7 +704,7 @@ void describe(cell *c) {
|
|||||||
if(cmode & sm::HELP) return;
|
if(cmode & sm::HELP) return;
|
||||||
neuron *n = getNeuronSlow(c);
|
neuron *n = getNeuronSlow(c);
|
||||||
if(!n) return;
|
if(!n) return;
|
||||||
help += "cell number: " + its(neuronId(*n)) + " (" + its(n->samples) + ")\n";
|
help += "cell number: " + its(neuronId(*n)) + " (" + its(n->allsamples) + ")\n";
|
||||||
help += "parameters:"; for(int k=0; k<cols; k++) help += " " + fts(n->net[k]);
|
help += "parameters:"; for(int k=0; k<cols; k++) help += " " + fts(n->net[k]);
|
||||||
help += ", u-matrix = " + fts(n->udist);
|
help += ", u-matrix = " + fts(n->udist);
|
||||||
help += "\n";
|
help += "\n";
|
||||||
@ -923,39 +942,66 @@ void progress(string s) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T> void save_raw(string fname, const vector<T>& v) {
|
||||||
|
FILE *f = fopen(fname.c_str(), "wb");
|
||||||
|
fwrite(&v[0], sizeof(v[0]), v.size(), f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> void load_raw(string fname, vector<T>& v) {
|
||||||
|
FILE *f = fopen(fname.c_str(), "rb");
|
||||||
|
if(!f) { fprintf(stderr, "file does not exist: %s\n", fname.c_str()); exit(1); }
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
auto s = ftell(f);
|
||||||
|
rewind(f);
|
||||||
|
v.resize(s / sizeof(v[0]));
|
||||||
|
fread(&v[0], sizeof(v[0]), v.size(), f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_classify() {
|
||||||
|
sominit(1);
|
||||||
|
if(bids.empty()) {
|
||||||
|
printf("Classifying...\n");
|
||||||
|
bids.resize(samples, 0);
|
||||||
|
bdiffs.resize(samples, 1e20);
|
||||||
|
for(int s=0; s<samples; s++) {
|
||||||
|
for(int n=0; n<cells; n++) {
|
||||||
|
double diff = vnorm(net[n].net, data[s].val);
|
||||||
|
if(diff < bdiffs[s]) bdiffs[s] = diff, bids[s] = n, whowon[s] = &net[n];
|
||||||
|
}
|
||||||
|
if(!(s % 128))
|
||||||
|
progress("Classifying: " + its(s) + "/" + its(samples));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(bdiffs.empty()) {
|
||||||
|
printf("Computing distances...\n");
|
||||||
|
bdiffs.resize(samples, 1e20);
|
||||||
|
for(int s=0; s<samples; s++)
|
||||||
|
bdiffs[s] = vnorm(net[bids[s]].net, data[s].val);
|
||||||
|
}
|
||||||
|
if(bdiffn.empty()) {
|
||||||
|
printf("Finding samples...\n");
|
||||||
|
bdiffn.resize(cells, 1e20);
|
||||||
|
for(int s=0; s<samples; s++) {
|
||||||
|
int n = bids[s];
|
||||||
|
double diff = bdiffs[s];
|
||||||
|
if(diff < bdiffn[n]) bdiffn[n] = diff, net[n].bestsample = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
whowon.resize(samples);
|
||||||
|
for(int i=0; i<samples; i++) whowon[i] = &net[bids[i]];
|
||||||
|
for(neuron& n: net) n.allsamples = 0;
|
||||||
|
for(int sn: bids) net[sn].allsamples++;
|
||||||
|
coloring();
|
||||||
|
}
|
||||||
|
|
||||||
void kclassify(const string& fname_classify) {
|
void kclassify(const string& fname_classify) {
|
||||||
|
|
||||||
sominit(1);
|
do_classify();
|
||||||
vector<double> bdiffs(samples, 1e20);
|
|
||||||
vector<int> bids(samples, 0);
|
|
||||||
|
|
||||||
printf("Classifying...\n");
|
|
||||||
|
|
||||||
for(neuron& n: net) n.samples = 0;
|
|
||||||
|
|
||||||
for(int s=0; s<samples; s++) {
|
|
||||||
for(int n=0; n<cells; n++) {
|
|
||||||
double diff = vnorm(net[n].net, data[s].val);
|
|
||||||
if(diff < bdiffs[s]) bdiffs[s] = diff, bids[s] = n, whowon[s] = &net[n];
|
|
||||||
}
|
|
||||||
if(!(s % 128))
|
|
||||||
progress("Classifying: " + its(s) + "/" + its(samples));
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<double> bdiffn(cells, 1e20);
|
|
||||||
|
|
||||||
printf("Finding samples...\n");
|
|
||||||
|
|
||||||
for(int s=0; s<samples; s++) {
|
|
||||||
int n = bids[s];
|
|
||||||
double diff = bdiffs[s];
|
|
||||||
if(diff < bdiffn[n]) bdiffn[n] = diff, net[n].bestsample = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int s=0; s<samples; s++) net[bids[s]].samples++;
|
|
||||||
|
|
||||||
if(fname_classify != "") {
|
if(fname_classify != "") {
|
||||||
printf("Listing classification...\n");
|
printf("Listing classification...\n");
|
||||||
FILE *f = fopen(fname_classify.c_str(), "wt");
|
FILE *f = fopen(fname_classify.c_str(), "wt");
|
||||||
if(!f) {
|
if(!f) {
|
||||||
printf("Failed to open file\n");
|
printf("Failed to open file\n");
|
||||||
@ -966,7 +1012,33 @@ void kclassify(const string& fname_classify) {
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
coloring();
|
}
|
||||||
|
|
||||||
|
void kclassify_save_raw(const string& fname_classify) {
|
||||||
|
do_classify();
|
||||||
|
save_raw(fname_classify, bids);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kclassify_load_raw(const string& fname_classify) {
|
||||||
|
load_raw(fname_classify, bids);
|
||||||
|
do_classify();
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_edges(const string& fname_edges, int pick = 0) {
|
||||||
|
do_classify();
|
||||||
|
vector<pair<int, int>> edgedata;
|
||||||
|
load_raw(fname_edges, edgedata);
|
||||||
|
int N = isize(edgedata);
|
||||||
|
if(pick > 0 && pick < N) {
|
||||||
|
for(int i=1; i<N; i++) swap(edgedata[i], edgedata[hrand(i+1)]);
|
||||||
|
edgedata.resize(N = pick);
|
||||||
|
}
|
||||||
|
vector<pair<int, int>> edgedata2;
|
||||||
|
for(auto p: edgedata)
|
||||||
|
edgedata2.emplace_back(showsample(p.first), showsample(p.second));
|
||||||
|
distribute_neurons();
|
||||||
|
for(auto p: edgedata2)
|
||||||
|
addedge(p.first, p.second, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void klistsamples(const string& fname_samples, bool best, bool colorformat) {
|
void klistsamples(const string& fname_samples, bool best, bool colorformat) {
|
||||||
@ -990,7 +1062,7 @@ void klistsamples(const string& fname_samples, bool best, bool colorformat) {
|
|||||||
if(!colorformat) fprintf(f, "%d\n", cols);
|
if(!colorformat) fprintf(f, "%d\n", cols);
|
||||||
if(best)
|
if(best)
|
||||||
for(int n=0; n<cells; n++) {
|
for(int n=0; n<cells; n++) {
|
||||||
if(!net[n].samples) { if(!colorformat) fprintf(f, "\n"); continue; }
|
if(!net[n].allsamples && !net[n].drawn_samples) { if(!colorformat) fprintf(f, "\n"); continue; }
|
||||||
klistsample(net[n].bestsample, n);
|
klistsample(net[n].bestsample, n);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1156,10 +1228,22 @@ int readArgs() {
|
|||||||
PHASE(3);
|
PHASE(3);
|
||||||
shift(); kohonen::kloadw(args());
|
shift(); kohonen::kloadw(args());
|
||||||
}
|
}
|
||||||
|
else if(argis("-somclassify0")) {
|
||||||
|
PHASE(3);
|
||||||
|
shift(); kohonen::do_classify();
|
||||||
|
}
|
||||||
else if(argis("-somclassify")) {
|
else if(argis("-somclassify")) {
|
||||||
PHASE(3);
|
PHASE(3);
|
||||||
shift(); kohonen::kclassify(args());
|
shift(); kohonen::kclassify(args());
|
||||||
}
|
}
|
||||||
|
else if(argis("-somclassify-sr")) {
|
||||||
|
PHASE(3);
|
||||||
|
shift(); kohonen::kclassify_save_raw(args());
|
||||||
|
}
|
||||||
|
else if(argis("-somclassify-lr")) {
|
||||||
|
PHASE(3);
|
||||||
|
shift(); kohonen::kclassify_load_raw(args());
|
||||||
|
}
|
||||||
else if(argis("-somlistshown")) {
|
else if(argis("-somlistshown")) {
|
||||||
PHASE(3);
|
PHASE(3);
|
||||||
shift(); kohonen::klistsamples(args(), false, false);
|
shift(); kohonen::klistsamples(args(), false, false);
|
||||||
@ -1186,6 +1270,16 @@ int readArgs() {
|
|||||||
else if(argis("-somrestrict")) {
|
else if(argis("-somrestrict")) {
|
||||||
shift(); kohrestrict = argi();
|
shift(); kohrestrict = argi();
|
||||||
}
|
}
|
||||||
|
else if(argis("-som_maxgroup")) {
|
||||||
|
shift(); max_group = argi();
|
||||||
|
}
|
||||||
|
else if(argis("-som_load_edges")) {
|
||||||
|
shift(); kohonen::load_edges(args(), 0);
|
||||||
|
}
|
||||||
|
else if(argis("-som_load_n_edges")) {
|
||||||
|
shift(); int n = argi();
|
||||||
|
shift(); kohonen::load_edges(args(), n);
|
||||||
|
}
|
||||||
|
|
||||||
else return 1;
|
else return 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -76,7 +76,7 @@ namespace rogueviz {
|
|||||||
|
|
||||||
namespace kohonen {
|
namespace kohonen {
|
||||||
extern int samples;
|
extern int samples;
|
||||||
void showsample(int id);
|
int showsample(int id);
|
||||||
void showsample(string id);
|
void showsample(string id);
|
||||||
void describe(cell *c);
|
void describe(cell *c);
|
||||||
void steps();
|
void steps();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user