热的东西显然会变凉。房间会会人沮丧地变得凌乱。几乎同样,消息会失真。逆转这些情况的短期策略分别是重新加热、 做卫生和使用 Hopfield 网络。本文向您介绍了三者中的最后一个,它是一个只需要特定的参数就可以消除噪声的算法。net.py 是一个特别简单的 Python 实现,将向您展示它的基本部分如何结合到一起,以及为何 Hopfield 网络有时可以自失真的图案中 重新得到原图案。尽管这个实现有局限性,不过仍然可以让您获得关于 Hopfield 网络的很多有益且有启发作用的经验。
您寻求的是什么?
我假定您是因为遇到了一些计算上的问题而来阅读本文。有人向您建议,一些神经网络算法可能会提供解决方案。具体说, 建议是说您可以使用一个 Hopfield 网络。我进一步假设您需要有一个大致的想法,以使得您可以决定那个建议是否切实 可行而且确保深入的研究。下面这个 Hopfield 网络的非常缩略的应用可能会引导您着手解决问题。
首先,您的问题有一组基本的用 -1 和 +1 编码的图案。如果需要,它们可以用 0 和 +1 编码。这些图案可以是邮票的规格化的 二进制图案(参阅 参考资料)。下一个要素是偏离这一基础的一组图案。您寻求的是创建代码,以 使得可以输入不正常的图案而输出应得的一个基本图案。因而您寻求的将是一个算法,可以输入一个对特定邮票的编码描述,然后 输出应得的一个基本邮票图案。您搜索不确定会成功。有可以接受的对您的计划产生负面影响的失败率。对您来说,会有一个不 会显著地影响您的项目的邮票误识别的比率。
如果这使您想起了您的问题,下面可能会是您的解决方案设计的开始。在结束之前,您最好应该能回答出基本的问题。 这个 Hopfield 是什么?它如何工作?它的局限性是什么?它可以为我做什么?我希望用更多的时间来研究它吗?
图案及其失真
让我们首先来看将会失真而随后被重新获得的五个任意图案。它们可以可视化地表示为 10 乘 10 的黑白方块矩阵。图 1 展示了第一个图案,p1。
图 1. p1 的可视化表示

点击 net.py 中 p2到 p5 的任意一个,可以显示其他的图案。为了编码,这五个图案被初始描述为 Python 列表。 这样,举例来说,第一个图案的描述见清单 1。
清单 1. 图案 p1
p1 = [ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[-1, -1, -1, -1, -1, -1, -1, -1, 1, 1],
[-1, -1, -1, -1, -1, -1, -1, -1, 1, 1],
[-1, -1, -1, -1, -1, -1, -1, -1, 1, 1],
[-1, -1, -1, -1, -1, -1, -1, -1, 1, 1],
[-1, -1, -1, -1, -1, -1, -1, -1, 1, 1],
[-1, -1, -1, -1, -1, -1, -1, -1, 1, 1],
[-1, -1, -1, -1, -1, -1, -1, -1, 1, 1],
[-1, -1, -1, -1, -1, -1, -1, -1, 1, 1],
[-1, -1, -1, -1, -1, -1, -1, -1, 1, 1] ]
</div>
黑色和白色的方块分别对应于 -1 和 +1。这个列表随后被转化为一个数组。(请参阅 参考资料 ,获得 我使用的 Python 库的参考。)对应于这类图案中的每一个元素,-1 或者 +1,在节点数组中都有一个节点对象。
一个节点对象有三个主要属性:
- 一个节点对象有一个值,它是图案中的一个元素。
- 一个节点还有一个地址,也就是在数组中它的地址。
- 每个节点还有一个颜色,以使得它可以显示出来。
如前所述,Hopfield 的一个功能是消除噪声。为实现这一功能,需要有一种方法来给图案引入噪声。点击 Add Noise 恰好 可以完成此任务。向 p1 添加噪声生成了图 2。
图 2. 失真的 p1

为了给一个图案引入噪声,Hopfield 要访问节点数组中的每一个地址。然后它会在 [0,1) 中取一个随机数,也就是 0 到 1 之间 包括 0 但不包括 1。如果数字小于某个固定的标准,网络就会改变节点的值和颜色,否则就会保持不变。默认情况下,这个标准设置 为 0.20,这样任意给定的节点就有百分之二十的可能会改变其值和颜色。您可以用调节滑块来改变这个概率。调为 0% 时,不会有噪声, 调为 100% 时,节点数组会简单地反转。取这区间的值,会出现所有其他通常的可能。每个值都会给一个图案引入特定程度的噪声。由于 Hopfield 网络是一个消除噪声的算法,它可以输入一个如图 2 所示的失真的图案,然后输出图 1 中的原始图案。
尽管有时会因不合适的解释而变得晦涩,相关的算法实现起来还是相当简单的。接下来,我将向您完整地介绍算法的一个实现, 然后我将简短解释为什么这些算法可以消除噪声。
权重
如 David Mertz 和我在以前的一篇 developerWorks 文章 An introduction to neural nets 中所述, 人类的大脑由大约 1 千亿个神经元构成,平均每个神经元要连接到几千个其他神经元。神经元既接收也发送不同的能量。 神经元的一个重要特性是,它们接收到能量后不会马上反应。而是,它们积累所接收到的能量,只有当积累的能量达到一定临界 极限时,它们才会向其他神经元发送自己的能量。
当大脑在学习时,可以认为它是在调整这些连接的数目和强度。毫无疑问,这是一个极其简化的生物学事实。 在这个例子中,对于实现控制神经网络而言,简化可以是实用的,尤其是当它们被作为模型来使用时。从生物学到算法的转换是通过 将连接转化为权重来实现的。(感知器以一种不同的而且可能更为直观的方式来使用权重。阅读这里之前,您可能会希望再读一遍 An introduction to neural nets。)
权重对象主要封装一个表示一个节点与另一个节点之间的权重的数值。权重对象还有一个地址和一个颜色。地址是它在权重数组中的位置。 颜色用于显示。图 3 是权重数组的一种可能的表示。Net.py(请参阅 参考资料 中的链接)保持了对最低和最高 权重的追踪,它将权重显示中显示颜色数值的一个键。
图 3. 权重数组的一种可视化表示

在权重数组的每一行上,是一个给定节点与所有其他节点间权重的一个列表。Hopfield 网络有两种形式。一种形式的节点有一个到 自身的权重,另一种形式则没有。通过 net.py 获得的经验表明,当节点不是自权重(self-weighted)时,节点数组不会总是重构到自身。 选择 No Self Weight 选项,然后尝试重构 p3 或 p5。有一百个节点,所以有一万个通常冗余的权重。默认情况下,当节点是 自权重时,就会有 5050 个非冗余权重,否则就只有 4950 个。
图 4. 权重的起源

清单 2. 权重生成算法
PAT = { x: x is a RxC pattern }
WA = { x: x is a (R*C)x(R*C) weight array }
For all (i,j) and (a,b) in the range of R and C:
SUM = 0
for p in PAT:
SUM += p(i,j) * p(a,b)
WA( (R*i)+j, (C*a)+b ) = SUM
受生物学启发的概念是 1949 年 Donald Hebb 研究所得的 Hopfield 网络的基础。他假定如果一对节点同时向对方发送它们的能量, 那么它们之间的权重就要大于只有一个发送自己的能量的情况。他写道:“当细胞 A 的一个轴突距离 B 足够近以至于能刺激它,而且 能反复持久地参与对它的激发时,一个或者全部两个细胞中就会发生一些成长过程或新陈代谢的变化,这样,作为激发 B 的一个细胞, A 的功效就会增长”(参阅 参考资料 以获得详细资料)。就 Hopfield 网络来说,当一对节点有相同的 值时,换句话说是 -1 或 +1,它们之间的权重就更大。所有可能的节点对的值的乘积的和决定的权重数组的内容。当两个值相同时,它们 的乘积就是正的,和就会增加。在不同的值的情况下,这个和就会减小。
更详细地讲,权重是哪里来的?首先,Hopfield 网络必须可以访问一个库或者一组基本图案。在这里即 p1 到 p5。权重的生成首先由 Hopfield 网络在基本图案矩阵的界限内选择一对坐标。然后它访问每个图案中的对应节点。在每一步,它将节点值的乘积添加到一个 正在使用的和。(见图 4)。当网络访问过每一个图案后,它将一个权重对象的值设置为这个和。给出一对位于(i,j)和(a,b)的 节点,它会设置在权重数组中位于(i*10+j,a*10+b)的权重对象的值。
这就是权重如何构造的过程,不过,它如何作用于更大的 Hopfield 算法?它如何作用于图案的重构?
重构
如果在手边有一个权重数组和一个失真的或有噪声的图案,Hopfield 网络有时可以输出原始图案。没有保证,但是 网络正确次数的百分比高得惊人。它既可以同步完成,也可以异步完成。
如果是异步完成,网络会遍历失真的图案,在每一个节点 N,它会询问 N 的值应该设置为 -1 还是 +1。
要确定这一设置,网络会去遍历权重数组中包含 N 与其他节点间所有权重的的行。不要忘记,节点可能是也可能不是自权重的。
在第二次遍历的每一步,它会计算出(1)N 与另一个节点之间的权重与(2)另一个节点的值的乘积。正如您所预料的,网络会 保持这些乘积的一个使用中的计数器。
现在,网络就可以做出判定。至少在当前的实现中,如果这个和小于 0,网络就

