home *** CD-ROM | disk | FTP | other *** search
- /* **************************************************** */
- /* file misc.c: contains pattern manipulation routines */
- /* and miscellaneous other functions. */
- /* */
- /* Copyright (c) 1991 by Donald R. Tveter */
- /* */
- /* **************************************************** */
-
- #include <stdio.h>
-
- #ifdef UNIX
- #include <malloc.h>
- #else
- #include <stdlib.h>
- #include <conio.h>
- #endif
-
- #ifdef INTEGER
- #include "ibp.h"
- #else
- #include "rbp.h"
- #endif
-
- /* an addition for large data sets */
-
- extern INT32 g;
-
- /* built-in function */
-
- extern int rand();
-
- /* homemade functions */
-
- #ifdef INTEGER
- extern REAL unscale(), unscaleint();
- extern WTTYPE scale();
- #endif
-
- extern short backoutput(), cbackoutput();
- extern void backinner(), cbackinner(), saveweights();
- extern WTTYPE rdr();
- extern void dbd_update(), periodic_update(), qp_update(), supersab();
- extern REAL readchar();
-
- extern char backprop,emptystring,informat,outstr[],patform,ringbell;
- extern char summary, *testfile, update, up_to_date_stats, wtlimithit;
- extern int bad, benchmark,bufferptr,lastprint,lastsave,npats;
- extern int prevnpats,readerror,readingpattern,right,saverate,testpat;
- extern int totaliter,unlearned,wrong,wttotal;
- extern WTTYPE dbdeta, error, initialkick, toler, toosmall;
- extern REAL errorperunit, pct_right;
- extern UNIT *hlayer, *ilayer, *jlayer, *klayer;
- extern LAYER *last, *start;
- extern short skiprate;
- #ifdef INTEGER
- extern INT32 totaldiff;
- #else
- extern REAL totaldiff;
- #endif
-
- void nullpatterns() /* dispose of any patterns before reading more */
- {
- PATLIST *pl, *nextpl;
- WTTYPE *p;
-
- if (start->patstart != NULL)
- {
- pl = start->patstart;
- while (pl != NULL)
- {
- nextpl = pl->next;
- p = pl->pats;
- free(p);
- pl = nextpl;
- };
- pl = last->patstart;
- while (pl != NULL)
- {
- nextpl = pl->next;
- p = pl->pats;
- free(p);
- pl = nextpl;
- };
- };
- start->patstart = NULL;
- last->patstart = NULL;
- npats = 0;
- prevnpats = 0;
- }
-
- void resetpats()
- {
- start->currentpat = NULL;
- last->currentpat = NULL;
- }
-
- void findendofpats(layer) /* purpose is to set all layer->currentpat */
- LAYER *layer; /* fields to end of pattern list so more */
- { /* patterns can be added at the end. */
- PATLIST *pl;
- pl = (PATLIST *) layer->patstart;
- while (pl->next != NULL) pl = pl->next;
- layer->currentpat = pl;
- }
-
- int copyhidden(u,hidden,layerno)
- UNIT *u, **hidden;
- int layerno;
- {
- if (hidden == NULL)
- {
- sprintf(outstr,"ran out of hidden units in layer %d\n",layerno);
- pg(outstr);
- return(0);
- }
- u->oj = (*hidden)->oj;
- *hidden = (*hidden)->next;
- return(1);
- }
-
- int loadpat(command)
- char command;
- {
- UNIT *u, *hunit, *iunit, *junit, *kunit;
- hunit = hlayer;
- iunit = ilayer;
- junit = jlayer;
- kunit = klayer;
- readingpattern = 1;
- u = (UNIT *) start->units;
- while (u != NULL)
- {
- if (informat == 'r') u->oj = rdr(GE,(REAL) HCODE,command);
- else u->oj = scale(readchar());
- if (readerror) goto errorexit;
- if (u->oj <= KCODE)
- {
- if (u->oj == HCODE)
- {if (!copyhidden(u,&hunit,2)) goto errorexit;}
- else if (u->oj == ICODE)
- {if (!copyhidden(u,&iunit,3)) goto errorexit;}
- else if (u->oj == JCODE)
- {if (!copyhidden(u,&junit,4)) goto errorexit;}
- else if (!copyhidden(u,&kunit,5)) goto errorexit;
- };
- u = u->next;
- };
- readingpattern = 0;
- forward();
- return(1);
-
- errorexit:
- readingpattern = 0;
- return(0);
- }
-
- void nextpat()
- {
- if (start->currentpat == NULL)
- {
- start->currentpat = start->patstart;
- last->currentpat = last->patstart;
- }
- else
- {
- start->currentpat = (start->currentpat)->next;
- last->currentpat = (last->currentpat)->next;
- };
- }
-
- void setoutputpat()
- {
- register WTTYPE *p;
- register UNIT *u;
- register short i, answer;
- PATLIST *pl;
-
- if (patform == 'c' || patform == 'C')
- {
- pl = last->currentpat;
- p = pl->pats;
- answer = *p;
- u = (UNIT *) last->units;
- for (i=1;i<=last->unitcount;i++)
- {
- if (i == answer) u->tj = scale(1.0); else u->tj = scale(0.0);
- u = u->next;
- };
- }
- else
- {
- pl = last->currentpat;
- p = pl->pats;
- u = (UNIT *) last->units;
- while (u != NULL)
- {
- u->tj = *p++;
- u = u->next;
- };
- }
- }
-
- void setinputpat()
- {
- register WTTYPE *p;
- register UNIT *u;
- UNIT *hunit, *iunit, *junit, *kunit;
- PATLIST *pl;
-
- hunit = hlayer;
- iunit = ilayer;
- junit = jlayer;
- kunit = klayer;
- pl = start->currentpat;
- p = pl->pats;
- u = (UNIT *) start->units;
- while (u != NULL)
- {
- if (*p > KCODE) u->oj = *p++;
- else if (*p++ == HCODE)
- {if (!copyhidden(u,&hunit,2)) return;}
- else if (*p++ == ICODE)
- {if (!copyhidden(u,&iunit,3)) return;}
- else if (*p++ == JCODE)
- {if (!copyhidden(u,&junit,4)) return;}
- else if (!copyhidden(u,&kunit,5)) {p++; return;};
- u = u->next;
- };
- }
-
- void setonepat() /* set input and output patterns */
- {
- register UNIT *u;
- register LAYER *innerlayers;
-
- setinputpat();
- setoutputpat();
- innerlayers = start->next;
- while (innerlayers->next != NULL)
- { /* set errors on the inner layer units to 0 */
- u = (UNIT *) innerlayers->units;
- while (u != NULL)
- {
- u->error = 0;
- u = u->next;
- };
- innerlayers = innerlayers->next;
- };
- }
-
- void clear()
- {
- LAYER *p;
- UNIT *u;
- WTNODE *w;
- int i;
-
- if (toosmall != -1)
- {
- pg("cannot restart with the weights removed\n");
- return;
- };
- right = 0;
- wrong = npats;
- pct_right = 0.0;
- unlearned = npats;
- wtlimithit = 0;
- totaliter = 0;
- lastsave = 0;
- initialkick = -1;
- lastprint = 0;
- resetpats();
- for (i=1;i<=npats;i++)
- {
- nextpat();
- if (last->currentpat->bypass > 0) last->currentpat->bypass = 0;
- else if (last->currentpat->bypass < 0) last->currentpat->bypass = -1;
- };
- p = start->next;
- while (p != NULL)
- {
- u = (UNIT *) p->units;
- while (u != NULL)
- {
- w = (WTNODE *) u->wtlist;
- while (w != NULL)
- {
- #ifdef SYMMETRIC
- if (w->next != NULL)
- { /* skip threshold weight */
- *(w->weight) = 0;
- *(w->olddw) = 0;
- *(w->eta) = dbdeta;
- };
- #else
- w->weight = 0;
- w->olddw = 0;
- w->eta = dbdeta;
- w->slope = 0;
- #endif
- w = w->next;
- };
- u = u->next;
- };
- p = p->next;
- };
- }
-
- #ifndef SYMMETRIC
-
- void whittle(amount) /* removes weights whose absolute */
- WTTYPE amount; /* value is less than amount */
- {LAYER *layer;
- UNIT *u;
- WTNODE *w, *wprev;
-
- layer = start->next;
- while (layer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- w = (WTNODE *) u->wtlist;
- wprev = (WTNODE *) NULL;
- while (w->next != (WTNODE *) NULL)
- {
- if ((w->weight) < amount && (w->weight) > -amount)
- {
- if (wprev == NULL) (WTNODE *) u->wtlist = w->next;
- else (WTNODE *) wprev->next = w->next;
- wttotal = wttotal - 1;
- }
- else wprev = w;
- w = w->next;
- }
- u = u->next;
- }
- layer = layer->next;
- }
- }
-
- #endif
-
- void testcheck() /* checks the testfile */
- {
- int class, best, count, tcright, tcwrong, testcount, printing;
- int tright, twrong, ch2;
- REAL pct, testerr, eperunit;
- WTTYPE max;
- UNIT *u;
-
- pushfile(testfile);
- testerr = 0.0;
- testcount = 0;
- tcright = 0;
- tcwrong = 0;
- tright = 0;
- twrong = 0;
- if (patform == 'c' || patform == 'g') printing = 0; else printing = 1;
- ch2 = readch();
- while (ch2 != EOF)
- {
- bufferptr = bufferptr - 1;
- if (!loadpat('t')) if (readerror == 2) goto summarize; else goto exit;
- class = 0;
- if (patform == 'c' || patform == 'C')
- {
- class = readint(1,last->unitcount,'t');
- if (readerror) goto exit;
- count = 0;
- max = -MAXINT;
- best = 0;
- };
- u = (UNIT *) last->units;
- while (u != NULL)
- {
- if (class)
- {
- count = count + 1;
- if (u->oj > max)
- {
- max = u->oj;
- best = count;
- }
- if (count == class) u->tj = scale(1.0); else u->tj = scale(0.0);
- }
- else
- {
- u->tj = rdr(GT,(REAL) KCODE,'t');
- if (readerror) goto exit;
- };
- u = u->next;
- };
- testcount = testcount + 1;
- if (class)
- if (best == class) tcright = tcright + 1; else tcwrong = tcwrong + 1;
- if (printing)
- {
- sprintf(outstr,"%5d",testcount);
- pg(outstr);
- };
- if (printoutunits(printing,last,1))
- {
- popfile();
- return;
- };
- testerr = testerr + unscale(error);
- if (bad) twrong = twrong + 1; else tright = tright + 1;
- do ch2 = readch(); while (ch2 != '\n');
- ch2 = readch();
- };
-
- summarize:
- pct = 100.0 * (REAL) tright / (REAL) testcount;
- if (pg("based on tolerance:\n")) return;
- sprintf(outstr," %6.2f%%, (%d right, %d wrong)",pct,tright,twrong);
- pg(outstr);
- eperunit = testerr / (REAL) (last->unitcount * testcount);
- sprintf(outstr," %7.5f error/unit\n",eperunit); pg(outstr);
- if (patform == 'c' || patform == 'C')
- {
- pct = 100.0 * (REAL) tcright / (REAL) testcount;
- if (pg("based on maximum value:\n")) return;
- sprintf(outstr," %6.2f%%, %d right, %d wrong\n",pct,tcright,tcwrong);
- pg(outstr);
- };
- popfile();
- return;
-
- exit:
- sprintf(outstr,"error while reading pattern %d\n",testcount+1);
- pg(outstr);
- popfile();
- }
-
- void stats(callfromrun)
- int callfromrun;
- {
- if (callfromrun) wrong = unlearned;
- right = npats - wrong;
- if (testpat) right = right - 1;
- errorperunit =
- unscaleint(totaldiff) / (REAL) ((right + wrong) * last->unitcount);
- pct_right = 100.0 * (REAL) right / (REAL) (right + wrong);
- }
-
- int patcheck(first,finish,printoutputs,printerrors,sumup,printsumup,skip)
- int first,finish,printoutputs,printerrors,sumup,printsumup,skip;
- {
- int i;
-
- if (skip && printoutputs == 0) goto shortcut;
- if (sumup)
- {
- totaldiff = 0;
- wrong = 0;
- };
- resetpats();
- for (i=1;i<first;i++) nextpat();
- for (i=first;i<=finish;i++)
- {
- nextpat();
- setonepat();
- forward();
- if (printoutputs) {sprintf(outstr,"%3d ",i); pg(outstr);};
- if (printoutunits(printoutputs,last,printerrors)) return(1);
- if (i != testpat && sumup)
- {
- wrong = wrong + bad;
- totaldiff = totaldiff + error;
- };
- };
- if (printoutputs) lastprint = totaliter;
- if (sumup) stats(0);
-
- shortcut:
- if (printsumup)
- {
- sprintf(outstr,"%5d iterations ",totaliter); pg(outstr);
- sprintf(outstr,"%6.2f%% right ",pct_right); pg(outstr);
- sprintf(outstr,"(%1d right ",right); pg(outstr);
- sprintf(outstr," %1d wrong) ",wrong); pg(outstr);
- sprintf(outstr,"%7.5f error/unit\n",errorperunit);
- if (pg(outstr)) return(1);
- }
- return(0);
- }
-
- void oneset() /* go through the patterns once and update weights */
- {
- int i;
- LAYER *layer;
- register UNIT *u;
- register WTNODE *w;
- short numbernotclose, attempted, passed;
-
- layer = last; /* make all b->totals = 0 */
- while (layer->backlayer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- w = (WTNODE *) u->wtlist;
- while (w != NULL)
- {
- #ifdef SYMMETRIC
- *(w->total) = 0;
- #else
- w->total = 0;
- #endif
- w = w->next;
- };
- u = u->next;
- };
- layer = layer->backlayer;
- };
- attempted = 0;
- passed = 0;
- if (testpat) unlearned = npats - 1; else unlearned = npats;
- resetpats();
- for(i=1;i<=npats;i++)
- {
- nextpat();
- if (last->currentpat->bypass == 0)
- {
- setonepat();
- forward();
- attempted = attempted + 1;
- if (update == 'c') numbernotclose = cbackoutput();
- else numbernotclose = backoutput();
- if (numbernotclose != 0)
- {
- #ifndef SYMMETRIC
- if (update == 'c') cbackinner(); else backinner();
- #endif
- }
- else /* this one pattern has been learned */
- {
- passed = passed + 1;
- unlearned = unlearned - 1;
- last->currentpat->bypass = skiprate;
- #ifndef SYMMETRIC
- if (backprop) if (update == 'c') cbackinner(); else backinner();
- #endif
- }
- }
- else last->currentpat->bypass = last->currentpat->bypass - 1;
- };
- if (update == 'c') totaliter = totaliter + 1;
- if (up_to_date_stats == '+' && update == 'c') patcheck(1,npats,0,0,1,0,0);
- if (unlearned == 0) return;
- if (skiprate && (attempted == passed))
- {
- resetpats();
- for (i=1;i<=npats;i++)
- {
- nextpat();
- if (last->currentpat->bypass > 0) last->currentpat->bypass = 0;
- };
- };
- if (update == 'c') return;
- else if (update == 'd') dbd_update();
- else if (update == 'p') periodic_update();
- else if (update == 'q') qp_update();
- else if (update == 's') supersab();
- if (up_to_date_stats == '+') patcheck(1,npats,0,0,1,0,0);
- totaliter = totaliter + 1;
- }
-
- void kick(size,amount) /* give the network a kick */
- WTTYPE size, amount;
- {
- LAYER *layer;
- UNIT *u;
- WTNODE *w;
- WTTYPE value;
- WTTYPE delta;
- int sign;
-
- layer = start->next;
- while (layer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- w = (WTNODE *) u->wtlist;
- while (w != NULL)
- {
- #ifdef SYMMETRIC
- value = *(w->weight);
- #else
- value = w->weight;
- #endif
- if (value != 0) sign = 1;
- else if ((rand() & 32767) > 16383) sign = -1;
- else sign = 1;
- delta = (INT32) sign * amount * (rand() & 32767) / 32768;
- if (value >= size) value = value - delta;
- else if (value < -size) value = value + delta;
- #ifdef SYMMETRIC
- if (((UNIT *) w->backunit)->unitnumber != u->unitnumber &&
- w->next != NULL)
- *(w->weight) = value;
- #else
- w->weight = value;
- #endif
- w = w->next;
- }
- u = u->next;
- }
- layer = layer->next;
- }
- }
-
- void newoneset() /* go through the patterns once and update weights */
- { int i;
- LAYER *layer;
- register UNIT *u;
- register WTNODE *w;
- short numbernotclose, attempted, passed;
-
- begin:
- layer = last; /* make all b->totals = 0 */
- while (layer->backlayer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- w = (WTNODE *) u->wtlist;
- while (w != NULL)
- {
- #ifdef SYMMETRIC
- *(w->total) = 0;
- #else
- w->total = 0;
- #endif
- w = w->next;
- };
- u = u->next;
- };
- layer = layer->backlayer;
- };
- attempted = 0;
- passed = 0;
- unlearned = npats;
- resetpats();
- for(i=1;i<=npats;i++)
- {
- nextpat();
- if (last->currentpat->bypass == 0)
- {
- setonepat();
- forward();
- attempted = attempted + 1;
- if (update == 'c') numbernotclose = cbackoutput();
- else numbernotclose = backoutput();
- if (numbernotclose != 0)
- {
- #ifndef SYMMETRIC
- if (update == 'c') cbackinner(); else backinner();
- #endif
- }
- else /* this one pattern has been learned */
- {
- passed = passed + 1;
- unlearned = unlearned - 1;
- last->currentpat->bypass = skiprate;
- #ifndef SYMMETRIC
- if (backprop) if (update == 'c') cbackinner(); else backinner();
- #endif
- }
- }
- else last->currentpat->bypass = last->currentpat->bypass - 1;
- if (g && (i % g == 0 || i == npats))
- {
- if (update == 'd') dbd_update();
- else if (update == 'p') periodic_update();
- layer = last; /* make all b->totals = 0 */
- while (layer->backlayer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- w = (WTNODE *) u->wtlist;
- while (w != NULL)
- {
- w->total = 0;
- w = w->next;
- };
- u = u->next;
- };
- layer = layer->backlayer;
- }; /* end while */
- }; /* end if g */
- }; /* end for i */
- if (update == 'c'|| g != 0) totaliter = totaliter + 1;
- if (up_to_date_stats == '+' && update == 'c') patcheck(1,npats,0,0,1,0,0);
- if (unlearned == 0) return;
- if (skiprate && (attempted == passed))
- {
- resetpats();
- for (i=1;i<=npats;i++)
- {
- nextpat();
- last->currentpat->bypass = 0;
- };
- goto begin;
- };
- if (g == 0)
- {
- if (update == 'c') return;
- else if (update == 'd') dbd_update();
- else if (update == 'p') periodic_update();
- else if (update == 'q') qp_update();
- else if (update == 's') supersab();
- };
- if (up_to_date_stats == '+') patcheck(1,npats,0,0,1,0,0);
- if (g == 0) totaliter = totaliter + 1;
- }
-
- int run(n,prpatsrate)
- int n; /* the number of iterations to run */
- int prpatsrate; /* rate at which to print output patterns */
- {
- int i, wtlimitbefore;
- #ifndef UNIX
- int chx;
- #endif
-
- if (pg("running . . .\n")) return(1);
- for (i=1;i<=n;i++)
- {
- totaldiff = 0;
- wtlimitbefore = wtlimithit;
- if (g == 0) oneset(); else newoneset();
- stats(1);
- if (wtlimitbefore == 0 && wtlimithit == 1)
- {
- sprintf(outstr,">>>>> WEIGHT LIMIT HIT <<<<< at %d\n",totaliter);
- if (pg(outstr)) return(1);
- };
- if (unlearned == 0) /* training finished */
- {
- if (benchmark && testpat)
- {
- sprintf(outstr,"S %d iterations",totaliter); pg(outstr);
- sprintf(outstr," %9.5f error/unit\n",errorperunit); pg(outstr);
- if (patcheck(testpat,testpat,1,1,0,0,0)) return(1);
- };
- if ((prpatsrate > 0 && lastprint != totaliter))
- if (patcheck(1,npats,summary == '-',summary == '-',1,1,0)) return(1);
- sprintf(outstr,"patterns learned to within %4.2f",unscale(toler));
- pg(outstr);
- pg(" at iteration");
- if (ringbell == '+') putchar(7);
- sprintf(outstr," %d\n",totaliter);
- if (pg(outstr)) return(1);
- if (benchmark && *testfile != emptystring) testcheck();
- return(0);
- };
- if (benchmark && testpat && (prpatsrate > 0 && i % prpatsrate == 0))
- {
- if (unlearned == 1) pg("S"); else pg("F");
- sprintf(outstr," %d iterations",totaliter); pg(outstr);
- sprintf(outstr," %7.5f error/unit\n",errorperunit);
- if (pg(outstr)) return(1);
- if (patcheck(testpat,testpat,1,1,0,0,0)) return(1);
- }
- if (totaliter % saverate == 0) saveweights();
- if ((prpatsrate > 0) && ((i % prpatsrate == 0) || (i == n)))
- {
- if (patcheck(1,npats,summary == '-',summary == '-',1,1,
- up_to_date_stats == '-')) return(1);
- if (benchmark && (*testfile != emptystring)) testcheck();
- };
- #ifndef UNIX
- if (kbhit() && getch() == 27 /* escape key */) return(1);
- #endif
- };
- return(0);
- }
-