#include #include #include #include #include
//----------------------------------------------------------------------------
// DEFINES #define MAXNEURONS 64 #define MAXPATTERNS 10 #define MAXITER 600000 #define TRUE 1 #define FALSE 0 //#undef SIDESHOW #define SIDESHOW char *TRAINFILE = "H7X8N4.TRN"; char *TESTFILE = "H7X8D5.TST"; //---------------------------------------------------------------------------- // FUNCTION PROTOTYPES
// network fns void InitNetRand(void); // 随机初始化用户数据 void LoadTrainingSet(char *Fname); // 从文件加载训练数据 void TrainNet(); // 训练NN void RunNet(void); // 联想记忆 int UpdateNeuron(int j); // 更新神经元,如果状态改变了返回true
void LoadUserPattern(char *Fname); int QueryAllClean(void); // 如果所有神经元至少被访问一次,返回true void SetAllToDirty(void); // 设置所有神经元为未被访问
void Initialize(int cnt, char *Name); // 初始化数据 void DisplayPatVect(int V[MAXNEURONS]); // 显示模式向量 void SavePatVect(int V[MAXNEURONS], // 将模式向量保存于文件中 char *txt, int i); void DisplayWeights(void); // 显示权重向量 void DisplayPatterns(void); // 显示所有训练模式 int QueryUserInt(char *msg); void KeyWait(void); void KeyWait2(char *txt); int random(int N); //----------------------------------------------------------------------------
// GLOBALS int PatVec[MAXNEURONS]; // 模式向量(缓存) int PatMatrix[MAXPATTERNS][MAXNEURONS]; // 模式向量 int NEURON[MAXNEURONS]; // NN int T[MAXNEURONS][MAXNEURONS]; // 权重矩阵 int NumNeurons; // 神经元数量 int NumPatterns; // 模式数量 int PatternX; // 显示维数x int PatternY; // 显示维数y int Dirty[MAXNEURONS]; // 如果神经元未被更新则返回true
FILE *ARCHIVE;
//----------------------------------------------------------------------------
int random(int N){ int x; x=N*rand(); return (x/RAND_MAX); }
void DisplayPatVect(int V[MAXNEURONS]){ int x,y,indx; indx=0; for (y=0; y for (x=0; x if (V[indx]==1) { printf("X"); } else { printf("."); } /* endif */ indx++; } /* endfor */ printf("\n"); } /* endfor */ printf("\n"); }
void SavePatVect(int V[MAXNEURONS], char *txt, int i) { int x,y,indx; indx=0; fprintf(ARCHIVE,"\n"); for (y=0; y for (x=0; x if (V[indx]==1) { fprintf(ARCHIVE,"X"); } else { fprintf(ARCHIVE,"."); } /* endif */ indx++; } /* endfor */ fprintf(ARCHIVE,"\n"); } /* endfor */ fprintf(ARCHIVE,"\n%s ",txt); if (i>=0) fprintf(ARCHIVE,"%d ",i); fprintf(ARCHIVE,"\n\n "); }
void DisplayWeights(){ int i,j; fprintf(ARCHIVE,"WEIGHTS:\n"); for (i=0; i fprintf(ARCHIVE,"["); for (j=0; j fprintf(ARCHIVE, " %d",T[j][i]); } /* endfor */ fprintf(ARCHIVE,"]\n"); } /* endfor */ }
void DisplayPatterns() { int i,p; for (p=0; p for (i=0; i PatVec[i] =PatMatrix[p][i]; } /* endfor */ DisplayPatVect(PatVec); // show 1st training pattern SavePatVect(PatVec, "训练模式", p+1); printf("\n\n训练模式 %d of %d\n\n",p+1,NumPatterns); KeyWait(); } /* endfor */ }
int QueryUserInt(char *msg){ int rv; printf("Enter %s ==> ",msg); scanf("%d",&rv); return rv; }
void KeyWait(void){ printf("Press any key to continue.\n"); while (!kbhit()) { } /* endwhile */ getch(); system("cls"); }
void KeyWait2(char *txt){ printf("\n\n%s\n",txt); KeyWait(); }
void InitNetRand() { int i,r;
fprintf(ARCHIVE,"随机创建用户模式\n"); srand(5);
for (i=0; i r=random(100); if (r >= 50) { NEURON[i]=0; } else { NEURON[i]=1; } /* endif */ } /* endfor */
}
void LoadTrainingSet(char *Fname) { int pat,j, InVal; FILE *PATTERNFILE;
printf("从文件: %s 加载训练模式\n",Fname); fprintf(ARCHIVE,"从文件: %s 加载训练模式\n",Fname); PATTERNFILE = fopen(Fname,"r"); if (PATTERNFILE==NULL){ printf("不能打开训练模式文件: %s",Fname); exit(0); }
fscanf(PATTERNFILE,"%d",&NumNeurons); // 获得神经元数 fscanf(PATTERNFILE,"%d",&NumPatterns); // 获得模式数 fscanf(PATTERNFILE,"%d",&PatternX); // 矩阵宽度 fscanf(PATTERNFILE,"%d",&PatternY); // 矩阵长度 printf("%d 模式被加载\n",NumPatterns); fprintf(ARCHIVE,"%d 模式被加载\n",NumPatterns); for (pat=0; pat for (j=0; j fscanf(PATTERNFILE,"%d",&InVal); PatMatrix[pat][j] =InVal; } // endfor } // endfor fclose(PATTERNFILE); }
void LoadUserPattern(char *Fname) { int j, InVal; FILE *PATTERNFILE;
printf("从文件: %s 加载用户模式\n", Fname); fprintf(ARCHIVE,"从文件: %s 加载用户模式\n", Fname); PATTERNFILE = fopen(Fname,"r"); if (PATTERNFILE==NULL){ printf("不能打开用户模式文件: %s",Fname); exit(0); }
printf("\n"); for (j=0; j fscanf(PATTERNFILE,"%d",&InVal); NEURON[j] =InVal; } // endfor fclose(PATTERNFILE); }
void TrainNet(){ int i,j,pat; int Sum; printf("训练开始。。。\n"); for (i=0; i for (j=0; j Sum=0; for (pat=0; pat Sum += (2*PatMatrix[pat][i]-1) * (2*PatMatrix[pat][j]-1); } /* endfor */ T[j][i] = T[i][j] = Sum; } /* endfor */ } /* endfor */ for (i=0; i T[i][i]=0; } /* endfor */ printf("训练结束。。。"); }
int QueryAllClean() { int i; for (i=0; i if (Dirty[i]==TRUE) return FALSE; } // endfor return TRUE; }
void SetAllToDirty() { int i; for (i=0; i Dirty[i]=TRUE; } // endfor }
int UpdateNeuron(int j) { int i; int Sum = 0; int OldState = NEURON[j]; for (i=0; i Sum += T[j][i] * NEURON[i]; } /* endfor */
if (Sum < 0) { NEURON[j] = 0; } else { if (Sum>0) NEURON[j] = 1; } /* endif */
if (NEURON[j] == OldState) { return 0; } else { return 1; } /* endif */ }
void RunNet(void) { int j; int Converged = FALSE; int ChngCount = 0; unsigned long int IterCount = 0; int ArchCnt=0; SetAllToDirty(); while ( (!Converged) && (IterCount < MAXITER) ) { j = random(NumNeurons); ChngCount += UpdateNeuron(j); // 如果神经元被改变则被改变的神经元数量加1 DisplayPatVect(NEURON); printf("运行... 次数=%d \n",IterCount); if (ArchCnt>=9) { SavePatVect(NEURON, "NN 输出 =", IterCount+1); ArchCnt=0; } else { ArchCnt++; } /* endif */ Dirty[j] = FALSE; // 记录此神经元被访问
if (QueryAllClean()) { //测试时候所有神经元被访问 // 如果每个神经元至少被访问一次 if (ChngCount == 0) { // 测试本次循环是否有神经元被更新 // 没有被更新的神经元 Converged = TRUE; printf("\n识别结束"); SavePatVect(NEURON, "识别结束于次数=", IterCount); } else { // 如果有被更新的神经元,则进行新的循环 SetAllToDirty(); ChngCount=0; } /* endif */ } /* endif */ IterCount++; } /* endwhile */ }
void Initialize(char *Name1, char *Name2) { char TrnName[50]; char TstName[50];
ARCHIVE = fopen("HOPFIELD.RST","w"); if (ARCHIVE==NULL){ printf("不能打开默认归档文件: HOPFIELD.RST"); exit(0); } strcpy(TrnName,Name1); strcpy(TstName,Name2); LoadTrainingSet(TrnName); if (strcmpi("RANDOM",TstName) ) LoadUserPattern(TstName); else InitNetRand(); // 随机产生用户模式
KeyWait(); }
int main(int argc, char *argv[]) {
int i; char *f1, *f2; if(argc == 3){ TRAINFILE = argv[1]; TESTFILE = argv[2]; } Initialize(TRAINFILE, TESTFILE); DisplayPatVect(NEURON); // 显示网络用来测试 SavePatVect(NEURON, "用户模式", -1); KeyWait2("用户模式"); DisplayPatterns(); TrainNet(); DisplayWeights(); RunNet(); fclose(ARCHIVE); return 0; }
|