我假定您是因为遇到了一些计算上的问题而来阅读本文。有人向您建议,一些神经网络算法可能会提供解决方案。具体说, 建议是说您可以使用一个 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] ]
黑色和白色的方块分别对应于 -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,网络就将节点设置为 -1,如果它大于或等于 0,则网络将 节点的值设置为 +1。
图 5. 重构:不遗留任何节点
清单 3. 重构
For every node, N, in pattern P.
SUM = 0
For every node, A, in P:
W = weight between N and A
V = value of A
SUM += W * V
if SUM < 0:
set N's value to -1
else:
set N's value to +1
默认的更新是异步的,因为网络只是在确定的这个值应该是什么之后才去设置一个节点的值。如果网络在做出了所有判定 后再去设置节点的值,那么它就可以是同步的。在这种情况下,它将存储它的判定,然后在最后一个判定做出后更新数组的节点。 在 net.py(参见 参考资料)中,重构默认情况下异步进行的,不过要注意 同步重构 的选项。
当您体验 net.py,当重构成功时,Hopfield 网络的行为令人震惊。这种行为之一是,甚至当权重数组严重退化时,它仍可以 重构图案。我的简单实现的退化权重(Degrade Weights)会遍历权重数组并随机地将权重设置为 0。对权重数级的显示给出了 破坏程度的一个视图。在这里,正确的重构说明 Hopfield 网络的容错性远超过大脑。它是如何工作的?数学的描述不会短。取而 代之的,这里给出了一个结构简介。
发生了什么
Hopfield 网络的算法细节说明了为什么它有时可以消除噪声。和通常算法分析一样,最麻烦的部分是数学细节。在当前的例子中,这些 是难以描绘和想像的。幸运的是,有一些密切相关的现象,可以使 Hopfield 网络的工作原理清楚明白地显示出来。
当一个弹球掉入一个简单曲面构成的碗中时,它会滚到最低点。碗的曲率就像是一个规则,输入弹球的入口点,然后返回最低点, 即碗底。更为复杂的曲率将类似于一个函数,它输入一个入口点并返回几个局部最低点中的其中之一。
能量是这些简单现象的一个基本部分。不管是在简单的还是在复杂的例子中,进入的弹球都具有一定度量的能量。随时间的过去, 这个能量会减少。它最终会达到一个稳定状态,不能再变小。在复杂的例子中,可能会有一个更低的能量级别,但是弹球无法达到。
类似地,不管有没有失真,一个图案都可以被认为具有特定度量的能量。所以,图案 p1 到 p5 有能量级别。
图案能量级别
图案的能量级别的计算并不复杂。Hopfield 网络计算每一个可能的节点对的值与它们之间权重的乘积。图案的 能量级别是用负 2 去除这些乘积的和所得的结果。 Net.py 显示了任意给定图案或节点 数组的能量级别。当您重构图案时,我认为并希望您将能够看到图案能量级别的下降。
在重构中,网络基于其他节点的值及它们之间的权重的乘积的和做出翻转一个节点的判定。当和小于 0 时,节点设置为 -1,否则设置为 +1。当值与权重的乘积是正的时,它有助于促使和大于 0。不过这样会将网络推向将节点值设置为 +1 的趋势。当乘积是负的时,和被推进到或者小于 0。于是,网络被推向到将节点的设置为 -1 的趋势。权重的变化 会引起度量的变化以及网络进行判定过程中被推向的趋势的变化。图案可能会失真很严重,导致网络不会被推向到做出 正确判定的趋势。如果表述没有问题,网络在绝大部分时候会被推向正确的趋势。
如果您重构那五个图案中的任意一个,您将发现每个图案会重构到自身。它应该是这样,因为每个图案已经占据了一个 局部最低能量的点。没有重构过程可以再降低图案的能量级别。如果您成功地重构了一个失真的图案,Hopfield 就已经将 图案的能量级别降到了某个图案的级别。当失败时,它是已经将失真图案的能量级别降到了一个假的局部低点。在两种情况下, 能量级别都不能再有任何降低。换句话说,它已经达到了一种稳定状态。以能量的方式来描述 Hopfield 网络有着有趣而且 重要的意义。在此基础之上,它可以以数学的方式建立起来,以使得重复应用重构算法可以最终得到一个稳定的图案。(参阅 参考资料以获得详细资料。)
结束语
您应该意识到 Hopfield 网络的局限性。一个经常被提及的明显局限是,它的图案必须可以被编码为一个数组,这个数组或者由 -1 和 +1 构成,或者由 0 和 +1 构成。您已经知道,Hopfield 可能会稳定于一个假的局部低点。这个更为明显的局限在于,当图案 的数目超过节点数组中的节点数目的大约 14% 时,网络稳定于某个假的局部低点的概率会增加。也就是说,每增加一个基本图案, 就必须多大约 7 个节点。尽管有这样的局限性,但是,这里所讨论的图案重构还是有可能成为解决您特定计算问题的直观向导。 现在您已经大概了解了最初提及的 Hopfield 算法。如果它能满足您的需要,现在您已经明白了构建您自己的实现的上部构造。 这包括计算权重数组的算法、重构失真图案的方式以及计算图案的能量级别的算法。