Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1951373
  • 博文数量: 261
  • 博客积分: 8073
  • 博客等级: 中将
  • 技术积分: 2363
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-10 15:23
文章分类

全部博文(261)

文章存档

2013年(1)

2012年(1)

2011年(50)

2010年(34)

2009年(4)

2008年(17)

2007年(55)

2006年(99)

分类:

2007-04-14 08:15:13

神经网络程序之一:HOPFIELD联想记忆。
 
本程序源自神经网络模式识别及其实现书后源码


#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;
}

阅读(915) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~