Hopfield神經網絡+C代碼

Hopfield是一個具有記憶功能的神經網絡;通過網絡轉態的不斷變化,最後轉態會穩定下來,最終的狀態是與待測樣本向量X最接近的訓練樣本。所以Hopfield網絡的最終輸出就是待測樣本向量聯想結果。


Hopfield網絡學習算法如下:

1. 確定權重係數,計算公式如下:


2. 對待測樣本進行分類,對二值神經元,計算Hopfield網絡輸出:


可選用的階躍函數爲:


循環迭代步驟2,當網絡神經達到穩定時結束,即神經元不再改變。


C代碼如下:

測試樣本如下:



對前9個樣本的指標進行平均,得到3個等級評價指標:


對神經元進行編碼,編碼規則爲:大於或等於某個等級指標時,對應的神經元狀態設爲1,否則爲-1。

樣本編碼如下:

-1 -1 -1   -1 1 1   -1 -1 -1   1 1 1   -1 -1 -1   -1 -1 -1   1 1 1   -1 1 -1   1 1 1   -1 1 -1
-1 1 1  -1 1 1  -1 -1 1  1 1 1  -1 -1 -1  -1 -1 -1  1 1 1  -1 1 -1  1 1 1  -1 1 -1 
-1 -1 1   -1 1 1   -1 -1 1   1 1 1   -1 -1 -1   -1 -1 -1   1 1 1   1 1 1   -1 -1 -1   1 1 1
-1 -1 1   -1 1 1   -1 -1 1   1 1 1   1 1 1   1 -1 1   1 1 1   1 1 1   -1 1 -1   -1 1 -1
-1 -1 1   1 1 1   1 1 1   1 1 1   1 1 1   1 -1 1   1 1 1   1 1 1   1 1 1   1 1 1
1 1 1   -1 1 1   1 1 1   -1 -1 -1   -1 -1 -1   1 -1 1   1 1 1   1 1 1   1 1 1   -1 1 -1
1 1 1   1 1 1   1 1 1   1 1 1   1 1 1   1 -1 1   -1 -1 -1   1 1 -1   1 1 1   -1 1 -1
1 1 -1   -1 1 1   -1 1 1   1 1 1   1 1 1   1 1 1   1 1 1   -1 1 -1   -1 1 -1   -1 1 -1
-1 1 1   -1 1 1   1 1 1   1 1 1   1 1 1   1 -1 1   -1 -1 -1   -1 -1 -1   1 1 1   -1 1 -1
-1 -1 1   -1 1 1   1 1 1   1 1 1   -1 -1 -1   -1 -1 -1   -1 -1 -1   -1 1 -1   -1 1 -1   1 1 1


#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include "vector"
using namespace std;


#define nodeNum 10     //樣本節點數
#define velumeNum 3    //樣本容量
#define MAXITER 20000  //最大迭代次數


typedef vector<int> dim1vector;
typedef vector<dim1vector> dim2vector;
typedef vector<dim2vector> dim3vector;


dim3vector srcVector;   //輸入樣本
dim3vector Weight;   //權重矩陣
dim2vector outVector;  //輸出向量


bool Dirty[nodeNum][velumeNum];  //記錄修改的神經元
dim2vector Test;


void inFileInf(char *File);  //獲取輸入樣本
void StartTrainNet();   //網絡神經訓練
void useNet();   //使用神經網絡
int random();   //獲取隨機數
int updateNeuron(int m);  //更新第m個神經元
void SetAllDirty();   //初始化
bool QueryAllCean();  //檢查至少每個神經元都被選中過


void main()
{
char *File = "輸入樣本.txt";


inFileInf(File);  //獲取輸入樣本
StartTrainNet();   //開始訓練
useNet();
}


//使用神經網絡
void useNet()
{
Test = srcVector[4];
int i, j, k, m;
int Iter = 0;
int chngCount = 0;
bool flag = false;


while(!flag && Iter<MAXITER)
{
m = random();
chngCount += updateNeuron(m);  //更新神經元的總數

//記錄已選的神經元
for(k=0; k<velumeNum; k++)
Dirty[m][k] = true;


//檢查至少每個神經元都被選中過
if(QueryAllCean())
{
if(chngCount == 0) //網絡已經穩定
{
flag = true;


for(i=0; i<nodeNum; i++)
{
for(j=0; j<velumeNum; j++)
printf("%3d", Test[i][j]>0?1:0);
printf("\n");
}
printf("迭代次數:%d\n", Iter+1);


}


else
{
SetAllDirty();
chngCount = 0;
}
}
Iter++;
}


}




//初始化Dirty
void SetAllDirty()
{
int i, j;
for(i=0; i<nodeNum; i++)
for(j=0; j<velumeNum; j++)
Dirty[i][j] = false;
}




//檢查至少每個神經元都被選中過
bool QueryAllCean()
{
int i, j;
for(i=0; i<nodeNum; i++)
for(j=0; j<velumeNum; j++)
if(Dirty[i][j]==false)
return false;
return true;
}




//網絡神經訓練
void StartTrainNet()
{
dim1vector wTemp1(velumeNum, 0);
  dim2vector wTemp2(nodeNum, wTemp1);
  dim3vector wTemp3(nodeNum, wTemp2);


Weight = wTemp3;

int i, j , k, l;


for(i=0; i<nodeNum; i++)
for(j=0; j<nodeNum; j++)
for(l=0; l<velumeNum; l++)
for(k=0; k<srcVector.size(); k++)
Weight[i][j][l] += srcVector[k][i][l]*srcVector[k][j][l];


for(i=0; i<nodeNum; i++)
for(j=i; j<nodeNum; j++)
{
for(l=0; l<velumeNum; l++)
Weight[i][j][l] = 0;
break;
}


}




//更新第m個神經元
int updateNeuron(int m)
{
int i, k;
int sum[velumeNum] = {0};
int oldTest[velumeNum];


//保存舊的神經元
for(i=0; i<velumeNum; i++)
oldTest[i] = Test[m][i];


//計算當前Hopfield網絡輸出
for(k=0; k<velumeNum; k++)
for(i=0; i<nodeNum; i++)
sum[k] += Weight[m][i][k]*Test[i][k];


//更新神經元
for(k=0; k<velumeNum; k++)
{
if(sum[k]<0)
Test[m][k] = -1;
else
Test[m][k] = 1;
}


//神經元是否更新
for(k=0; k<velumeNum; k++)
if(Test[m][k] != oldTest[k])
return 1;
return 0;
}




//獲取隨機數
int random()
{
int x;
x = nodeNum*rand();
x = x/RAND_MAX;
return x;
}




//獲取輸入樣本
void inFileInf(char *File)
{
int i, j;
int num;
dim1vector temp1;
dim2vector temp2;


FILE *fp = fopen(File, "r");


if(fp==NULL)
{
printf("Open file error!!\n");
exit(0);
}


i = 1;
j = 1;
while(fscanf(fp, "%d", &num)!=EOF)
{
temp1.push_back(num);
if(i%velumeNum ==0)
{
temp2.push_back(temp1);
if(j%nodeNum ==0)
{
srcVector.push_back(temp2);
temp2.clear();
}


temp1.clear();
j++;
}


i++;
}


fclose(fp);


}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章