Hopfield网络及C#实现
时间:2010-10-17 来源:基础软件
最近在看一本书, Introduction to Neural Networks for CSharp。其中有一章介绍了Hopfield网络。这章对于Hopfield的介绍很简单,其运行过程用C#来实现也很容易,只是没有介绍网络运行的原理、数学证明,程序即使运行出来了,也是知其然不知其所以然。我从网上查了一些资料,期望找到Hopfied网络的数学理论基础和训练方法有效性的数学证明,但是暂时没有找到和书上所说的训练方法一致的相关内容,却意外发现另外一个问题对:大家对Hopfield网络模型以及训练的描述都有一些差异,没有完全一致的定义。看来以后还要多看各种资料,自己消化理解,对别人所说的做出甄别。
不管怎么说,书上介绍的内容简单实用,按照书上的训练方法能够识别一些简单的模式。这篇文章把书中讲的Hopfield网络训练和识别方法做一归纳总结。
书中定义的Hopfield网络是一种单层全互连自动联想网络(fully connected single layer autoassociative network)。书中所讲的Hopfield网络有以下几个特点: (1)网络有N个神经元,则权值矩阵W为N*N的方阵。权值矩阵W为对称阵,且对角线元素为0.即神经元到自身的权值为0。
(2)神经元输入为二值(即0、1或者-1、1),书中采用0和1.
(3)神经元输出为二值(即0、1或者-1、1),书中采用0和1.
训练过程如下:
(1)初始化权值矩阵为0.
(2)输入下一个模式P,P为N维向量(p1,p2,p3...pn)。
(3)将p乘以p的转置得到一个N*N的方阵A。
(4)将第3步的方阵A对角线元素设置为0.
(5)将方阵A回到权值矩阵W上。
(6)如果有更多的模式,则转到第2步。
(7)训练结束。 训练结束后,可以用Hopfield网络识别前面的训练模式,或者与它们相近的模式,这体现了Hopfield的联想功能。Hopfield能够自动识别与其训练模式相反的模式,例如训练模式为[0,1,1,0],则训练后,网络也能识别[1,0,0,1]。
利用Hopfield网络可以实现简单的图形识别,如数字识别。把图形拆成点阵,形成一个二维矩阵,把矩阵拉成一维的向量,这就是Hopfield网络要识别的模式了。将这个模式输入给Hopfield网络训练即可。
Hopfield网络的C#代码实现如下。这里先给出网络代码,以后有时间再把数字识别的例子写出来。

/// <summary>
/// Hopfield网络,单层全互联自动联想网络,输入为二值。
/// </summary>
/// <remarks>
/// 孙继磊,2010-10-18
/// [email protected]
/// </remarks>
public class HopfieldNetwork
{
#region 属性和字段
private Matrix weightMatrix;
/// <summary>
/// 权值矩阵
/// </summary>
public Matrix weight
{
get
{
return weightMatrix;
}
}
/// <summary>
/// 神经元数量
/// </summary>
public int size
{
get
{
return weightMatrix.rowNum;
}
}
#endregion
#region 构造函数
/// <summary>
/// 构造一个指定大小的Hopfield网络
/// </summary>
/// <param name="size">神经元数量</param>
public HopfieldNetwork(int size)
{
this.weightMatrix = new Matrix(size, size);
}
#endregion
/// <summary>
/// 输入一个模式计算得到输出(输入输出都是二值向量)
/// </summary>
/// <param name="pattern">输入的模式</param>
/// <returns>输出结果</returns>
public bool[] Present(bool[] pattern)
{
bool[] output = new bool[pattern.Length];
//将模式转换为矩阵(行向量)
Matrix row = new Matrix(BipolarUtil.Bipolar2double(pattern));
//计算输出
for (int c = 0; c < pattern.Length; c++)
{
Matrix column = weightMatrix.getColumn(c);
double dotProduct = (row * column)[0,0];
output[c] = dotProduct > 0;
}
return output;
}
/// <summary>
/// 针对某一模式进行训练
/// </summary>
/// <param name="pattern">要训练的模式</param>
public void Train(bool[] pattern)
{
if (pattern.Length != weightMatrix.rowNum)
throw new AnnException("输入模式维数与Hopfield神经元数量不匹配。");
// 将输入模式转换为行向量
Matrix input = new Matrix(BipolarUtil.Bipolar2double(pattern));
// 输入行向量转置得到列向量
Matrix inpute2 = Matrix.transpose(input);
//输入行向量与转置相乘,得到矩阵后,对角线设置为0
Matrix t = inpute2 * input;
for (int i = 0; i < input.columnNum; i++)
t[i, i] = 0;
//将前面计算得到的矩阵回到原来的权值矩阵
weightMatrix = weightMatrix + t;
}
}