home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume14
/
back-prop
/
part03
/
io.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-09-15
|
24KB
|
774 lines
/* ************************************************ */
/* file io.c: contains most input/output functions */
/* */
/* Copyright (c) 1990 by Donald R. Tveter */
/* */
/* ************************************************ */
#include <stdio.h>
#ifdef INTEGER
#include "ibp.h"
#else
#include "rbp.h"
#endif
extern char buffer[buffsize];
extern int bufferend;
extern int bufferptr;
extern int ch;
extern FILE *data;
extern char datafilename[50];
extern int echo;
extern int format[maxformat];
extern LAYER *last;
extern int lastsave;
extern short nlayers;
extern char outformat;
extern WTTYPE qmark;
extern int readerror;
extern int readingpattern;
extern LAYER *start;
extern WTTYPE toler;
extern int totaliter;
extern char wtformat;
#ifdef INTEGER
short scale(x) /* returns x as a scaled 16-bit value */
double x;
{
short s;
if (x > 31.999 || x < -32.0)
{
printf("magnitude of %lf is too large for the integer",x);
printf(" representation\n",x);
readerror = 1;
return(0);
};
if (x > 0.0) s = x * 1024 + 0.5;
else s = x * 1024 - 0.5;
if (x != 0.0 && s == 0)
{
printf("warning: magnitude of %lf is too small for",x);
printf(" the integer representation\n");
return(0);
};
return(s);
}
double unscale(x) /* returns the double value of short x */
short x;
{
double temp;
temp = (double) x / 1024.0;
return(temp);
}
double unscaleint(x) /* returns the double value of int x */
int x;
{
double temp;
temp = (double) x / 1024.0;
return(temp);
}
#endif
int readch() /* returns the next character in the input buffer */
{
int i, ch2;
if (bufferptr > bufferend) /* then read next line into buffer */
{
ch2 = getc(data);
if (ch2 == EOF) return(ch2);
i = 0;
while(ch2 != '\n' && i < buffsize)
{
if (ch2 == 015) ch2 = ' '; /* filter out carriage returns */
buffer[i] = ch2;
i = i + 1;
ch2 = getc(data);
};
if (i == buffsize)
{
printf("line too long\n");
exit(4);
};
buffer[i] = '\n';
bufferend = i;
bufferptr = 0;
if (echo == 1)
for(i = 0; i <= bufferend; i++) putchar(buffer[i]);
}
ch2 = buffer[bufferptr];
bufferptr = bufferptr + 1;
return(ch2);
}
void texterror() /* handles errors in text */
{
printf("unexpected text: ");
bufferptr = bufferptr - 1;
ch = readch();
while (ch != '\n')
{
putchar(ch);
ch = readch();
};
putchar('\n');
bufferptr = bufferptr - 1;
}
int scanfordigit() /* used to scan for the leading */
{ /* digit of a number and trap mistakes */
int sign;
sign = 1;
restart:
ch = readch();
while (ch == ' ' || ch == '\n') ch = readch();
if (ch >= '0' && ch <= '9')
{
bufferptr = bufferptr - 1; /* unget the character */
return(sign);
};
if (ch >= 'h' && ch <= 'k')
{
bufferptr = bufferptr - 1; /* unget the character */
return(0);
};
switch (ch) {
case EOF: printf("unexpected EOF\n");
exit(2);
case '*': while (ch != '\n') ch = readch();
goto restart;
case '-': sign = -sign;
goto restart;
case '?': bufferptr = bufferptr - 1; /* unget the character */
return(0);
default: readerror = 1;
return(0);
}; /* end switch */
};
int readint(min,max,command)
int min, max; /* the minimum and maximum allowed values */
char command;
{
int sign, number;
readerror = 0;
sign = scanfordigit();
if (readerror == 1 || sign == 0)
{
readerror = 1;
texterror();
return(0);
};
number = 0;
ch = readch();
while (ch == ' ') ch = readch();
while (ch >= '0' && ch <= '9')
{
number = number * 10 + (ch - '0');
ch = readch();
};
bufferptr = bufferptr - 1; /* unget the character */
number = sign * number;
if (number < min || number > max)
{
printf("erroneous value: %d",number);
if (data == stdin) putchar('\n');
else printf(" in %c command\n",command);
readerror = 1;
};
return(number);
}
double readreal(op,min,command)
int op;
double min;
int command;
{
double number;
double fractpart, divisor, intpart, sign;
readerror = 0;
sign = (double) scanfordigit();
if (readerror == 1 || (sign == 0 && !readingpattern))
{
texterror();
return(0);
};
ch = readch();
if (ch == 'h' && readingpattern)
return(unscale(HCODE));
else if (ch == 'i' && readingpattern && nlayers >= 3)
return(unscale(ICODE));
else if (ch == 'j' && readingpattern && nlayers >= 4)
return(unscale(JCODE));
else if (ch == 'k' && readingpattern && nlayers >= 5)
return(unscale(KCODE));
else if (ch == '?' && readingpattern)
return(unscale(qmark));
intpart = 0.0;
while (ch >= '0' && ch <= '9')
{
intpart = 10.0 * intpart + (ch - '0');
ch = readch();
};
fractpart = 0.0;
divisor = 1.0;
if (ch == '.')
{
ch = readch();
while (ch >= '0' && ch <= '9')
{
fractpart = fractpart * 10.0 + (ch - '0');
divisor = divisor * 10.0;
ch = readch();
};
};
bufferptr = bufferptr - 1; /* unget the character */
number = sign * (((double) intpart) +
((double) fractpart) / ((double) divisor));
if (op == GT && number > min) return(number);
else if (op == GE && number >= min) return(number);
else
{
printf("erroneous value: %lf",number);
if (data == stdin) putchar('\n');
else printf(" in %c command\n",command);
readerror = 1;
return(0.0);
};
}
WTTYPE rdr(op,min,command) /* reads double real numbers and converts */
int op; /* them to 16-bit integers if necessary */
double min;
int command;
{
double x;
WTTYPE ix;
x = readreal(op,min,command);
if (readerror == 1) return(0);
ix = scale(x);
if (readerror == 1) return(0);
return(ix);
}
double readchar() /* reads data in compressed format */
{
readerror = 0;
ch = readch();
do {
switch (ch) {
case '\n':
case ' ': ch = readch();
break;
case '1': return(1.0);
case '0': return(0.0);
case '?': return(unscale(qmark));
case '*': do {ch = readch();} while(ch != '\n');
break;
case 'h': return(unscale(HCODE));
case 'i': if (nlayers >= 3) return(unscale(ICODE));
case 'j': if (nlayers >= 4) return(unscale(JCODE));
case 'k': if (nlayers >= 5) return(unscale(KCODE));
default: texterror();
readerror = 1;
return(0.0);
}; /* end switch */
} while (0 == 0);
}
void printoutunits(layer,printerr) /* prints values of units */
LAYER *layer;
int printerr;
{
double error, e;
int counter, i;
UNIT *u;
WTTYPE upper, middle, diff;
PATNODE *target;
upper = scale(1.0) - toler; /* compute whether needed or not */
middle = scale(0.5);
u = (UNIT *) layer->units;
if (layer == last) target = (PATNODE *) last->currentpat->pats;
counter = 0;
i = 1;
if (printerr == 0) printf(" ");
while (u != NULL)
{
counter = counter + 1;
if (outformat == 'r')
{
printf("%5.2lf ",unscale(u->oj));
if (format[i] == counter)
{
printf("\n ");
if (i < maxformat - 1) i = i + 1;
}
}
else if (outformat == 'a' && layer == last)
{
diff = target->val - u->oj;
if (diff < 0) diff = -diff;
if (diff < toler) putchar('c');
else if (u->oj > upper) putchar('1');
else if (u->oj < toler) putchar('0');
else if (u->oj > target->val) putchar('^');
else putchar('v');
if (format[i] == counter)
{
putchar(' ');
if (i < maxformat - 1) i = i + 1;
}
}
else
{
if (u->oj > upper) putchar('1');
else if (u->oj > middle) putchar('^');
else if (u->oj < toler) putchar('0');
else putchar('v');
if (format[i] == counter)
{
putchar(' ');
if (i < maxformat - 1) i = i + 1;
}
}
u = u->next;
if (layer == last) target = target->next;
};
if (printerr == 1)
{
error = 0.0;
u = (UNIT *) layer->units;
target = (PATNODE *) last->currentpat->pats;
while (u != NULL)
{
e = unscale(target->val - u->oj);
error = error + e * e;
u = u->next;
target = target->next;
};
printf(" (%7.5lf)",error);
};
printf("\n");
}
void wrb(wtfile,value,wtsize)
FILE *wtfile;
WTTYPE value;
int wtsize;
{
int i;
unsigned char *charptr, ch2;
charptr = (unsigned char *) &value;
for (i=1;i<=wtsize;i++)
{
ch2 = *charptr;
putc(ch2,wtfile);
charptr++;
};
}
void saveweights() /* saves weights on the file weights */
{
FILE *weights;
UNIT *u;
LAYER *layer;
WTNODE *w;
WTTYPE wvalue, evalue, dvalue;
weights = fopen("weights","w");
fprintf(weights,"%d%c",totaliter,wtformat);
if (wtformat == 'b' || wtformat == 'B') fprintf(weights,"%1d",WTSIZE);
fprintf(weights," file = %s\n",datafilename);
layer = start->next;
while (layer != NULL)
{
u = (UNIT *) layer->units;
while (u != NULL)
{
w = (WTNODE *) u->wtlist;
while (w != NULL)
{
#ifdef SYMMETRIC
wvalue = *(w->weight);
evalue = *(w->eta);
dvalue = *(w->olddw);
#else
wvalue = w->weight;
evalue = w->eta;
dvalue = w->olddw;
#endif
if (wtformat == 'r' || wtformat == 'R')
{
fprintf(weights,"%16.10lf",unscale(wvalue));
if (wtformat == 'R')
{
fprintf(weights," %16.10lf",unscale(evalue));
fprintf(weights," %16.10lf",unscale(dvalue));
};
putc('\n',weights);
}
else /* binary format; uses the least space */
{
wrb(weights,wvalue,WTSIZE);
if (wtformat == 'B')
{
wrb(weights,evalue,WTSIZE);
wrb(weights,dvalue,WTSIZE);
};
};
w = w->next;
};
u = u->next;
};
layer = layer->next;
};
fflush(weights);
close(weights);
lastsave = totaliter;
}
WTTYPE rdb(wtfile,wtsize) /* read binary and convert between sizes */
FILE *wtfile;
int wtsize;
{
int i;
double value;
short ivalue;
unsigned char *charptr;
if (wtsize == 2) charptr = (unsigned char *) &ivalue;
else charptr = (unsigned char *) &value;
for (i=1;i<=wtsize;i++)
{
*charptr = (unsigned char) getc(wtfile);
charptr++;
};
if (WTSIZE == 2 && wtsize == 2) return(ivalue);
else if (WTSIZE == 2 && wtsize == 8) return(scale(value));
else if (WTSIZE == 8 && wtsize == 8) return(value);
else if (WTSIZE == 8 && wtsize == 2) return(ivalue / 1024.0);
}
void restoreweights() /* restore weights from the file weights */
{
FILE *weights;
UNIT *u;
LAYER *layer;
WTNODE *w;
int ch2, fileformat;
WTTYPE wvalue, evalue, dvalue;
double temp;
int wtsize;
weights = fopen("weights","r");
if (weights == NULL)
{
printf("cannot open file weights\n");
return;
};
fscanf(weights,"%d",&totaliter);
fileformat = getc(weights);
if (fileformat != wtformat)
printf("caution: weight format mismatch\n");
if (fileformat == 'b' || fileformat == 'B')
{
wtsize = getc(weights) - '0';
if (WTSIZE != wtsize)
printf("caution: weight sizes mismatched\n");
}
else wtsize = WTSIZE;
ch2 = getc(weights); /* skip over the file name */
while (ch2 != '\n') ch2 = getc(weights);
layer = start->next;
while (layer != NULL)
{
u = (UNIT *) layer->units;
while (u != NULL)
{
w = (WTNODE *) u->wtlist;
while (w != NULL)
{
if (fileformat == 'r' || fileformat == 'R')
{
fscanf(weights,"%lf",&temp);
wvalue = scale(temp);
if (fileformat == 'R')
{
fscanf(weights,"%lf",&temp);
evalue = scale(temp);
fscanf(weights,"%lf",&temp);
dvalue = scale(temp);
};
}
else
{
wvalue = rdb(weights,wtsize);
if (fileformat == 'B')
{
evalue = rdb(weights,wtsize);
dvalue = rdb(weights,wtsize);
};
};
#ifdef SYMMETRIC
*(w->weight) = wvalue;
if (fileformat == 'R' || fileformat == 'B')
{
*(w->olddw) = dvalue;
*(w->eta) = evalue;
}
else *(w->olddw) = 0;
#else
w->weight = wvalue;
if (fileformat == 'R' || fileformat == 'B')
{
w->olddw = dvalue;
w->eta = evalue;
}
else w->olddw = 0;
#endif
w = w->next;
};
u = u->next;
};
layer = layer->next;
};
close(weights);
}
void printweights(u) /* print the weights leading into unit u */
UNIT *u;
{WTNODE *w;
UNIT *bunit;
WTTYPE value;
#ifdef INTEGER
int sum, input;
#else
double sum, input;
#endif
w = (WTNODE *) u->wtlist;
sum = 0;
printf("layer unit unit value weight input from unit\n");
while (w != NULL)
{
bunit = (UNIT *) w->backunit;
#ifdef SYMMETRIC
value = *(w->weight);
#else
value = w->weight;
#endif
input = value * bunit->oj;
#ifdef INTEGER
input = input / 1024;
#endif
sum = sum + input;
printf("%3d ",bunit->layernumber);
if (bunit->unitnumber == 32767) printf(" t ");
else printf("%4d ",bunit->unitnumber);
printf("%10.5lf %10.5lf ",unscale(bunit->oj),unscaleint(value));
printf("%18.5lf\n",unscaleint(input));
w = w->next;
};
printf(" ");
printf("sum = %9.5lf\n\n",unscaleint(sum));
}
void help()
{
printf("\n");
ch = readch();
while (ch == ' ' && ch != '\n') ch = readch();
switch(ch) {
default : printf("for help type h followed by letter of command\n");
break;
case '?': printf("? prints program status and parameters.\n");
break;
case '*': printf("* at the beginning of a line makes the line a");
printf(" comment.\n");
break;
case '!': printf("Enter UNIX commands after the !.\n");
break;
case 'A': printf("A is used to set the details of the algorithm. ");
printf("One or more\nof the following commands can go on ");
printf("the same line as the 'A':\n\n");
printf("a p sets the piecewise linear activation function\n");
printf("a s sets the smooth activation function (rbp only).");
printf("\n\nb + will backpropagate errors");
printf(" even when a unit is close to it's target.\n");
printf("b - will not backpropagate errors when a");
printf(" unit is close to it's target.\n\n");
printf("D <real> will set the sharpness of the sigmoid to");
printf(" <real>.\n\n");
printf("d d will use the derivative from the ");
printf("differential step size algorithm.\n");
printf("d f uses Fahlman's derivative.\n");
printf("d o uses the original derivative.\n\n");
printf("l <real> limits the weights to between +<real> ");
printf("and -<real>. The default\n is to not check");
printf(". To reset to not check, use l 0.\n\n");
printf("s <int> will skip patterns that have been learned");
printf(" for <int> iterations.\n\n");
printf("u c will use the continuous update method.\n");
printf("u C will use the continuous update method with the");
printf(" differential step size etas.\n");
printf("u d will use the differential step size update.\nu ");
printf("j will use Jacob's delta-bar delta update method.\n");
printf("u o will use the original weight update method.\n");
break;
case 'a': printf("a <real> sets the momentum parameter, alpha, to");
printf(" <real>.\n");
break;
case 'b': printf("b <int1> <int2> ... <int10> puts a carriage return");
printf(" after each <inti>\nvalues when the output format");
printf(" is real and inserts a blank after each <inti>\n");
printf("value if the format is condensed.\n");
break;
case 'C': printf("C clears the network and other relevant parameters");
printf(" so the problem can be re-run\nwith different");
printf(" initial weights. Added hidden units are not");
printf(" removed.\n");
break;
#ifndef SYMMETRIC
case 'c': printf("c <int1> <int2> <int3> <int4>\n");
printf("Adds a connection from layer <int1> unit <int2>\n");
printf("to layer <int3> unit <int4>.\n");
break;
#endif
case 'E': printf("E1 echos input; E0 turns off echo of input.\n");
break;
case 'e': printf("e <real1> <real2> sets eta, the learning rate, to");
printf(" <real1> and if\n");
printf("<real2> is present, eta2 of the differential");
printf(" step size algorithm\nis set to <real2>. If ");
printf("<real2> is not present, eta2 = eta / 10.\n");
break;
case 'f': printf("f is used to set the input and output formats for");
printf(" data.\nOne or more of the following commands can");
printf(" go on the line:\n\n");
printf("i c will read values in patterns as compressed.\n");
printf("i r will read values in patterns are reals.\n\n");
printf("o a will write node values as analog compressed.\n");
printf("o c will write node values as compressed.\n");
printf("o r will write node values as real.\n\n");
printf("s + will summarize learning status instead of");
printf(" listing each pattern.\n");
printf("s - will not summarize learning status and will");
printf(" list each pattern.\n\n");
printf("w b will write the weights to the file weights as");
printf(" binary values.\n");
printf("w B will write the weights and weight changes and");
printf(" etas as binary.\n");
printf("w r will write the weights to the file weights as");
printf(" real values.\n");
printf("w R will write the weights and weight changes and");
printf(" etas as real values.\n");
break;
#ifndef SYMMETRIC
case 'H': printf("H <int> <real> adds a hidden unit to layer <int>\n");
printf("Weights are initialized to between -<real> and");
printf(" <real>.\n");
break;
#endif
case 'h': printf("h <letter> gives help for command <letter>.\n");
break;
case 'i': printf("i <filename> takes commands from <filename>.\n");
break;
case 'j': printf("j is used to set parameters for Jacob's");
printf(" delta-bar-delta method.\nOne or more of the");
printf(" following commands can go on the line:\n\n");
printf("d <real> sets the decay factor to <real>.\n");
printf("e <real> sets the initial eta value to <real>.\n");
printf("k <real> sets kappa to <real>.\n");
printf("m <real> limits the maximum value of each eta to");
printf(" <real>.\nt <real> sets theta to <real>.\n");
break;
case 'k': printf("k <real1> <real2> decreases all the weights in the ");
printf("network whose values\nare greater than <real1> by a");
printf(" random amount between 0 and <real2>.\nWeights ");
printf("less than -<real1> are increased by an amount ");
printf("between 0 and <real2>.\nIf <real1> = 0.0, and a ");
printf("weight = 0.0 then the weight is changed to\na ");
printf("value between -<real2> and +<real2>.\n");
break;
case 'l': printf("l <int> prints values of nodes on layer <int>.\n");
break;
case 'm': printf("m <int1> <int2> ... <intn> makes a network with\n");
printf("<int1> units in the first layer, <int2> units in\n");
printf("the second layer, ... , <intn> units in the nth");
printf(" layer\n");
break;
case 'n': printf("n <int> <in1> <out1> ... <ini> <outi> ... <inN> ");
printf("<outN>\nreplaces all patterns with <int> new ones");
printf(".\n<ini> patterns go on the input units.\n");
printf("<outi> patterns go on the output units.\n");
break;
case 'o': printf("o a outputs node values in analog compressed form.");
printf("\no c outputs node values in compressed form.\n");
printf("o r outputs node values as double.\n");
break;
case 'P': printf("P lists the outputs for all patterns.\n");
printf("P <int> gives the output for pattern <int>.\n");
break;
case 'p': printf("p <pat> submits the pattern, <pat>, to the input");
printf(" units.\n");
break;
case 'Q': printf("Q <real> sets the value of ? in compressed input");
printf(" to be the value, <real>.\n");
break;
case 'q': printf("q ends the program.\n");
break;
case 'R': printf("R reloads weights from the file weights.\n");
break;
case 'r': printf("r <int1> <int2> runs <int1> iterations thru the ");
printf("patterns. If <int2> is\npresent, the patterns are ");
printf("printed (or summarized) every <int2> iterations.\n");
break;
case 'S': printf("S <int> saves the weights on the file ");
printf("weights every <int> iterations.\nS saves the ");
printf("weights immediately.\n");
break;
case 's': printf("s <int> sets the random number seed to <int>.\n");
break;
#ifdef SYMMETRIC
case 'T': printf("T <real> freezes all threshold weights at <real>.\n");
break;
#endif
case 't': printf("t <real> sets <real> as the tolerance used in ");
printf("printing compressed values\nand in checking for");
printf(" complete learning.\n");
break;
#ifndef SYMMETRIC
case 'W': printf("W <real> removes links whose weights are less than ");
printf("the absolute value\nof <real>, except links to ");
printf("threshold units are not removed.\n");
break;
#endif
case 'w': printf("w <int1> <int2> ");
printf("prints weights into unit <int2> in layer <int1>.\n");
break;
case 'x': printf("x <int1> <in1> <out1> ... <ini> <outi> ... <inN>");
printf(" <outN>\nadds the extra <int1> patterns.\n");
printf("<in1> patterns go on the input units.\n");
printf("<out1> patterns go on the output units.\n");
break;
}; /* end switch */
putchar('\n');
}