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