使用Python构建Hopfield网络的教程


Posted in Python onApril 14, 2015

 热的东西显然会变凉。房间会会人沮丧地变得凌乱。几乎同样,消息会失真。逆转这些情况的短期策略分别是重新加热、 做卫生和使用 Hopfield 网络。本文向您介绍了三者中的最后一个,它是一个只需要特定的参数就可以消除噪声的算法。net.py 是一个特别简单的 Python 实现,将向您展示它的基本部分如何结合到一起,以及为何 Hopfield 网络有时可以自失真的图案中 重新得到原图案。尽管这个实现有局限性,不过仍然可以让您获得关于 Hopfield 网络的很多有益且有启发作用的经验。
您寻求的是什么?

我假定您是因为遇到了一些计算上的问题而来阅读本文。有人向您建议,一些神经网络算法可能会提供解决方案。具体说, 建议是说您可以使用一个 Hopfield 网络。我进一步假设您需要有一个大致的想法,以使得您可以决定那个建议是否切实 可行而且确保深入的研究。下面这个 Hopfield 网络的非常缩略的应用可能会引导您着手解决问题。

首先,您的问题有一组基本的用 -1 和 +1 编码的图案。如果需要,它们可以用 0 和 +1 编码。这些图案可以是邮票的规格化的 二进制图案(参阅 参考资料)。下一个要素是偏离这一基础的一组图案。您寻求的是创建代码,以 使得可以输入不正常的图案而输出应得的一个基本图案。因而您寻求的将是一个算法,可以输入一个对特定邮票的编码描述,然后 输出应得的一个基本邮票图案。您搜索不确定会成功。有可以接受的对您的计划产生负面影响的失败率。对您来说,会有一个不 会显著地影响您的项目的邮票误识别的比率。

如果这使您想起了您的问题,下面可能会是您的解决方案设计的开始。在结束之前,您最好应该能回答出基本的问题。 这个 Hopfield 是什么?它如何工作?它的局限性是什么?它可以为我做什么?我希望用更多的时间来研究它吗?

图案及其失真

让我们首先来看将会失真而随后被重新获得的五个任意图案。它们可以可视化地表示为 10 乘 10 的黑白方块矩阵。图 1 展示了第一个图案,p1。
图 1. p1 的可视化表示

使用Python构建Hopfield网络的教程

 点击 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,在节点数组中都有一个节点对象。

一个节点对象有三个主要属性:

  1.     一个节点对象有一个值,它是图案中的一个元素。
  2.     一个节点还有一个地址,也就是在数组中它的地址。
  3.     每个节点还有一个颜色,以使得它可以显示出来。

如前所述,Hopfield 的一个功能是消除噪声。为实现这一功能,需要有一种方法来给图案引入噪声。点击 Add Noise 恰好 可以完成此任务。向 p1 添加噪声生成了图 2。
图 2. 失真的 p1

使用Python构建Hopfield网络的教程

 为了给一个图案引入噪声,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. 权重数组的一种可视化表示

使用Python构建Hopfield网络的教程

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

使用Python构建Hopfield网络的教程

清单 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. 重构:不遗留任何节点

使用Python构建Hopfield网络的教程

清单 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 算法。如果它能满足您的需要,现在您已经明白了构建您自己的实现的上部构造。 这包括计算权重数组的算法、重构失真图案的方式以及计算图案的能量级别的算法。

Python 相关文章推荐
Python ORM框架SQLAlchemy学习笔记之数据添加和事务回滚介绍
Jun 10 Python
python实现在windows下操作word的方法
Apr 28 Python
python引用DLL文件的方法
May 11 Python
Python实现的端口扫描功能示例
Apr 08 Python
Python中判断输入是否为数字的实现代码
May 26 Python
Python爬虫框架Scrapy常用命令总结
Jul 26 Python
Python去除字符串前后空格的几种方法
Mar 04 Python
在python Numpy中求向量和矩阵的范数实例
Aug 26 Python
学python安装的软件总结
Oct 12 Python
python常用运维脚本实例小结
Feb 14 Python
python opencv人脸识别考勤系统的完整源码
Apr 26 Python
Python实现学生管理系统并生成exe可执行文件详解流程
Jan 22 Python
使用C语言扩展Python程序的简单入门指引
Apr 14 #Python
在Python中封装GObject模块进行图形化程序编程的教程
Apr 14 #Python
用PyQt进行Python图形界面的程序的开发的入门指引
Apr 14 #Python
使用C语言来扩展Python程序和Zope服务器的教程
Apr 14 #Python
用Python中的wxPython实现最基本的浏览器功能
Apr 14 #Python
Python中SOAP项目的介绍及其在web开发中的应用
Apr 14 #Python
Python中的XML库4Suite Server的介绍
Apr 14 #Python
You might like
php 如何获取数组第一个值
2013/08/06 PHP
ThinkPHP连接数据库及主从数据库的设置教程
2014/08/22 PHP
PHP+MySQL之Insert Into数据插入用法分析
2015/09/27 PHP
PHP并发多进程处理利器Gearman使用介绍
2016/05/16 PHP
用Javascript实现锚点(Anchor)间平滑跳转
2009/09/08 Javascript
jQuery模拟点击A标记示例参考
2014/04/17 Javascript
Javascript的闭包详解
2014/12/26 Javascript
如何屏蔽防止别的网站嵌入框架代码
2015/08/24 Javascript
jQuery简单实现title提示效果示例
2016/08/01 Javascript
JavaScript实现动态增删表格的方法
2017/03/09 Javascript
JS实现禁止用户使用Ctrl+鼠标滚轮缩放网页的方法
2017/04/28 Javascript
Jquery把获取到的input值转换成json
2017/05/15 jQuery
浅谈对Angular中的生命周期钩子的理解
2017/07/31 Javascript
JS中DOM元素的attribute与property属性示例详解
2018/09/04 Javascript
基于vue通用表单解决方案的思考与分析
2019/03/16 Javascript
vue实现购物车功能(商品分类)
2020/04/20 Javascript
实例讲解JavaScript 计时事件
2020/07/04 Javascript
JavaScript this指向相关原理及实例解析
2020/07/10 Javascript
typescript配置alias的详细步骤
2020/08/12 Javascript
[55:48]VGJ.S vs TNC Supermajor 败者组 BO3 第二场 6.6
2018/06/07 DOTA
python 中的列表解析和生成表达式
2011/03/10 Python
老生常谈python的私有公有属性(必看篇)
2017/06/09 Python
Python实现的直接插入排序算法示例
2018/04/29 Python
在django中图片上传的格式校验及大小方法
2019/07/28 Python
Python 函数用法简单示例【定义、参数、返回值、函数嵌套】
2019/09/20 Python
使用PyCharm安装pytest及requests的问题
2020/07/31 Python
联想墨西哥官方网站:Lenovo墨西哥
2016/08/17 全球购物
关于运动会的口号
2014/06/07 职场文书
感情真挚的毕业生求职信
2014/07/19 职场文书
社区法制宣传日活动总结
2015/05/05 职场文书
农村婚庆主持词
2015/06/29 职场文书
大学学习委员竞选稿
2015/11/20 职场文书
2016大学军训心得体会
2016/01/11 职场文书
2016年感恩母亲节活动总结
2016/04/01 职场文书
解析在浏览器地址栏输入一个URL后发生了什么
2021/06/21 Servers
Golang 切片(Slice)实现增删改查
2022/04/22 Golang