/* ExtRec.c * Experimental Character Recognition Program * Using Neural Nets and Subsumption * (c) Logan Kearsley */ #include #include #include #include #include #include "mlayer.h" #define ROWS 10 #define COLS 8 #define CHARS 95 //WINDOW *scrn; typedef struct charnet { neuro_t* w; char id; struct charnet* next; } cdata; cdata* Nbase; void cteol(){while(getchar()!='\n');} void load(neuro_t* w, char* ftrn, float ls, float m){ FILE* f; setLearningSpeed(w,ls); if(m!=0){ momentumOn(w); setMomentum(w,m); } f=fopen(ftrn,"rb"); bldnet(f,w); fclose(f); } void init_neuro(){ char t; char ln[10]; cdata* net; FILE* nlist = fopen("chars.config", "r"); fscanf(nlist,"%c",&t); fscanf(nlist,"%s",ln); Nbase = (cdata*)malloc(sizeof(cdata)); mknet(Nbase->w); load(Nbase->w,ln,0.7,0.2); Nbase->id = t; net = Nbase; //printf("Loaded net for character '%c'\n", t); while(fscanf(nlist,"\n%c",&t) != EOF) {// read one character from the pipe net->next = (cdata*)malloc(sizeof(cdata)); net = net->next; fscanf(nlist,"%s",ln); mknet(net->w); load(net->w,ln,0.7,0.2); net->id = t; net->next = NULL; //printf("Loaded net for character '%c'\n", t); } close(nlist); } void save_neuro(){ int i=0; cdata* net; char fname[10]; FILE* f; FILE* conf = fopen("chars.config","w"); net = Nbase; while(net->next!=NULL){ sprintf(fname,"%d",i); strcat(fname,".net"); f=fopen(fname,"w"); bsvnet(f,net->w); fclose(f); fprintf(conf,"%c %s\n",net->id,fname); net = net->next; } fclose(conf); } char recChar(float* img){ cdata* c; cdata* net; float p=0,t; net = Nbase; while(net->next!=NULL){ loadInput(net->w,img); mquery(net->w); t = getOutput(net->w)[0]; if(t>p){ p=t; c=net; } net = net->next; } return c->id; } void addChar(cdata* N, char t, float* bit){ int d[] = {81,40,20,10,5,1}; float e; int i; float one=1; N->next = (cdata*)malloc(sizeof(cdata)); N = N->next; mknet(N->w); mrndnet(N->w,d,5); printf("New character '%c'...\n", t); loadInput(N->w, bit); loadTarget(N->w, &one); for(i=0,e=1.0;e>0.1&&i<1000;i++) mquery(N->w),e=backprop(N->w); //printf("training took %d epochs\n", epochs); N->id = t; N->next = NULL; } void comp(){ int i,l=0,p=0,s=500,cyc=0; float one=1,zero=0,acc=0,oldacc=0,avrg=0,e=1; float bit[81]; char comp_c, rec_c; char c[82]; char infile[20]; char compfile[20]; char* text = (char*)malloc(sizeof(char)*500); FILE* tf; FILE* cf; cdata* net; cdata* net_2; printf("Text Image to Recognize: "); scanf("%s",infile); tf = fopen(infile,"r"); printf("Comparison File: "); scanf("%s",compfile); cf = fopen(compfile,"r"); while(1){ while(1){ if(fscanf(tf,"%s\n",c)==EOF) break; for(i=0;i<81;i++) bit[i]=(c[i]=='1'?1.0:0.0); //refresh(); rec_c=recChar(bit); l++; if(l>=s) text = (char*)realloc(text,sizeof(char)*(s+=500)); text[l-1]=rec_c; text[l]='\0'; comp_c=fgetc(cf); net=Nbase; if(comp_c==rec_c){ p++; while(net->id != comp_c) net=net->next; loadInput(net->w, bit); //should've been taken care of in recChar, but just in case.... loadTarget(net->w,&one); for(i=0;i<10;i++) mquery(net->w),backprop(net->w); //reinforce it to avoid backsliding } else{ while(net->id != rec_c) net=net->next; //e=1.0; //for(i=0,e=1.0;e>0.1&&i<1000;i++) mquery(net->w),e=backprop(net->w); net_2=Nbase; while(net_2->id != comp_c){ if(net_2->next==NULL) break; else net_2=net_2->next; } if(net_2->id != comp_c){ addChar(net_2, comp_c, bit),net_2=net_2->next; } //not a good way to test; keep as a back-up only loadInput(net->w, bit); loadInput(net_2->w, bit); loadTarget(net->w,&zero); loadTarget(net_2->w,&one); mquery(net->w); mquery(net_2->w); e=backprop(net->w); e+=backprop(net_2->w); if(e/2<.2){ for(i=0;getOutput(net->w)[0] > getOutput(net_2->w)[0] && i<1000;i++){ mquery(net->w); mquery(net_2->w); backprop(net->w); backprop(net_2->w); } }else{ for(i=0;e/2 > .2 && i<1000;i++){ mquery(net->w); mquery(net_2->w); e=backprop(net->w); e+=backprop(net_2->w); } } } } printf("\n%s\n",text); acc=(float)p/l*100.0; if(acc>85){ printf("Accuracy: %f\%\n(%f Improvement)\nRerun [y/n]?",acc,acc-oldacc); while((rec_c=getchar())!='y' && rec_c!='n'); if(rec_c=='n') break; } else{ avrg=(avrg*cyc+acc-oldacc)/(cyc+1); //move(10,0); printf("Accuracy: %f\%\n(%f Improvement)\t Trend: %f\n",acc,acc-oldacc,avrg); } oldacc=acc; rewind(cf); rewind(tf); l=0; p=0; cyc++; } close(tf); close(cf); save_neuro(); } int main(int argc, char *argv[]){ init_neuro(); comp(); return 0; }