Hopfield神经网络是一种比较特殊的网络,它不像一般的神经网络那样有输入层和输出层,并且通过训练来改变神经网络中的参数,最终实现预测、识别等功能。Hopfield网络只有一群神经元节点,所有节点之间相互连接,形式如下:

虽然有些文章会画出像深度神经网络那样有输入输出的图,并且输出后又返回输入,但本质上就是多个节点之间的全连接,也就是上面的图形。Hopfield神经网络主要有两个应用:一是起到类似储存器的作用,也就是我们把多个序列或图片输入这个网络,最终这个网络会以神经元之间连接权重的形式储存这些信息,当我们再次往这个网络输入相同或有些破损部分的原来的一个输入序列/图像,它能够把序列/图像还原(恢复)回来;另一个应用就是求解TSP问题,也就是寻找最优解。

基本原理

我们先以一个简单的,只有三个神经元的Hopfield网络为例,令这三个神经元为A,B,C,其图形如下所示:

其中箭头表示从一个神经元到另一个神经元相连,每个箭头都表示相应的权重,为一个数,可以用Wij来表示。神经元自己和自己也有连接,只不过数值始终是0,所有这里没有画出。

这样我们就可以用一个矩阵来表示各个神经元之间的连接了。

A B C
A 0
B 0
C 0

所以,Hopfield关键还是在于求权重矩阵,针对两种问题,兔兔在下面分别讨论。

基本原理与算法实现

(1)储存信息

对于储存信息,例如几个长度为n的序列,那么我们就需要一个有n个节点的神经元的神经网络来储存;如果是几个nxn维的图像矩阵,我们可以把矩阵展开成长度为的序列,再输入到神经网络中。兔兔下面以储存两个6x6维的图像为例。

第一个图像矩阵为:

0 0 1 1 0 0
0 0 1 1 0 0
1 1 1 1 1 1
1 1 1 1 1 1
0 0 1 1 0 0
0 0 1 1 0 0

图像为:

第二个图像矩阵为:

0 0 1 1 0 0
0 1 0 0 1 0
1 0 0 0 0 1
1 0 0 0 0 1
0 1 0 0 1 0
0 0 1 1 0 0

图像为:

我们把第一个矩阵展开成序列,按行按列都是可以的,不过需要统一。兔兔这里按行展开,得序列1为:[0,0,1,1,0,0,0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,0,0,1,1,0,0],序列2为[0,0,1,1,0,0,0,1,0,0,1,0,1,0,0,0,0,1,1,0,0,0,0,1,0,1,0,0,1,0,0,0,1,1,0,0]。这样我们便需要一个有36个节点的神经网络来储存这两个图片,权重矩阵为36x36维。

更新网络权值矩阵公式为:

其中k表示需要储存的k个序列,这里k=2;表示第s个序列,表示第s个序列的第i、第j个元素,对应就是第i、j个节点,所以说序列是通过神经元输入网络的。代表权值矩阵的第i行j列。所以算法实现时可以用三层循环来实现:第一层循环是依次输入各个序列,二、三层循环用来计算权重矩阵i行j列。

(对于上面第一行的公式,更一般的形式应该可以把2改成α,1改成β,即这里α=2,β=1是一种特殊情况,换成其它参数应该也是可以的,甚至V也可以不止是1次方,也可能是其它是数)

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
a=np.array([[0,0,1,1,0,0],[0,0,1,1,0,0],[1,1,1,1,1,1],[1,1,1,1,1,1],[0,0,1,1,0,0],[0,0,1,1,0,0]])
b=np.array([[0,0,1,1,0,0],[0,1,0,0,1,0],[1,0,0,0,0,1],[1,0,0,0,0,1],[0,1,0,0,1,0],[0,0,1,1,0,0]])
array_a=a.flatten() #把矩阵变成序列
array_b=b.flatten()
input_array=[array_a,array_b]
w=np.zeros((36,36)) #初始权值矩阵
for s in input_array:w0=np.zeros((36,36))for i in range(36):for j in range(36):if i==j:w0[i,j]=0else:w0[i,j]=(2*s[i]-1)*(2*s[j]-1)w+=w0
w=w*300 #为了以图片方式展示
w=Image.fromarray(w)
plt.imshow(w)
plt.show()

最终我们得到了权值矩阵w,把权值矩阵按照图片方式展示,图像如下:

我们可以把这个权值矩阵看成是这两个输入图片的叠加后,以权值矩阵形式储存在神经网络中。那么。之后如果我们有一个新的相同维度的图片,但是有一部分模糊了,就可以利用这个神经网络还原成原来的图像。例如,对于下面这样的图像:

我们把它还原回之前的形状。我们把这个图像矩阵按行展开成序列,该序列还是用V表示,序列处理后还原成新的序列用Y表示。实现过程为

上面两个过程是循环操作的。开始输入V初始序列,Vj表示序列第j个元素,wij表示权值矩阵第i行j列,即矩阵第j列所有元素与V中所有元素对应相乘(除了i=j这个元素不操作)并求和得Yj,如果Yj小于零,新的序列第j个元素就是0,否则是1。操作一遍后得到的V再输入到第一个式子处理,循环多次,最终结果会趋于稳定,此时得到就是还原后的序列。如果是矩阵的话,把序列再按照原来展开方式堆叠回去就可以了。

在每一次循环中,更新节点j的顺序不同,对最终结果也是有一定影响的。比如一个序列[1,0,0,0,1],我们可以按顺序更新,即j=1,然后依次是2,3,4,5,下一次循环也是1,2,3,4,5。但是也可以是:2,1,3,5,4,  2,1,3,5 ,4...... 这样顺序来更新。

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
a=np.array([[0,0,1,1,0,0],[0,0,1,1,0,0],[1,1,1,1,1,1],[1,1,1,1,1,1],[0,0,1,1,0,0],[0,0,1,1,0,0]])
b=np.array([[0,0,1,1,0,0],[0,1,0,0,1,0],[1,0,0,0,0,1],[1,0,0,0,0,1],[0,1,0,0,1,0],[0,0,1,1,0,0]])
c=np.array([[0,0,1,1,0,0],[0,0,1,1,0,0],[1,1,1,1,1,1],[1,1,1,1,1,1],[1,0,0,1,0,0],[0,0,1,1,0,0]])
array_a=a.flatten()
array_b=b.flatten()
input_array=[array_a,array_b]
w=np.zeros((36,36))
for s in input_array:w0=np.zeros((36,36))for i in range(36):for j in range(36):if i==j:w0[i,j]=0else:w0[i,j]=(2*s[i]-1)*(2*s[j]-1)w+=w0
c=c.flatten()
v0=c
Y=np.zeros(36)
for t in range(10):v1 = np.zeros(36)for j in range(36):for i in range(36):if i==j:v1[j]+=0else:v1[j]+=w[i,j]*v0[i]if v1[j]<0:Y[j]=0else:Y[j]=1v0=Y
result=np.array(v0).reshape(6,6)
p=Image.fromarray(result*600)
plt.imshow(p)
plt.show()

最终结果为:

我们发现最终确实还原回去了,效果比较好,但是Hopfield网络也是有一定缺点的。Hopfield缺点有:记忆容量有限,伪稳定点的联想与记忆,当记忆样本比较相近,就不能会议正确的记忆等等。

(2)TSP问题求解

针对TSP问题,其实是有非常多的算法,例如蚁群算法、遗传算法、模拟退火等一系列算法。TSP问题是不重复地走遍所有城市并返回起始城市,使得整个路径最短。对于n个城市,我们通常用nxn维距离矩阵 D来表示各个城市之间的距离。矩阵x行y列表示城市x与城市y之间的距离,即,对角线元素为0,因为距离是对称的,所以距离阵是对称阵。

TSP目的是寻找最短路线,那么我们可以用神经网络的节点来表示路线。对于访问顺序,我们可以用换位矩阵 V表示。例如对于四个城市A,B,C,D,其中一种走法表示为:

A 1 0 0 0
B 0 0 1 0
C 0 1 0 0
D 0 0 0 1

它表示的路线是A ->  C-> B -> D -> A 。并且我们发现,换位矩阵每一行和每一列只能有一个元素为1,其它为0。

对于n个城市,我们用节点个数为的网络,每个节点为(换位矩阵的x行i列),表示第x个城市第i步,如果为0,就是第i步不在城市x;如果为1,就是在所以每个节点为0或1。

(注意:在这里一定要注意各个符号的表示意义,本文这里x、y始终表示的是城市,i、j始终表示第i、j步,表示城市x和y之间的距离,数值为0或1,表示第i步是否在城市x)。

对于这样的神经网络,此时权值矩阵的固定的(这一点与上一个应用是截然不同的,前面的是往节点输入数据,通过网络权值起到保存数据的作用;这里权值矩阵与城市距离阵有关,距离阵固定下来,权值阵便固定下来了,变化的是网络是节点数值,最终网络稳定时节点的结果就是最终换位矩阵,表示求得的路线)。之后需要的就是多次迭代,改变节点的状态,找到最终的结果。

迭代过程需要引入Uxi这个中间量。U与换位矩阵V维数相同,U0这里可以为0.2。A、D是常数,这里分别为1.5、1;t用来表示第几次迭代次数,那么就可以表示第t次迭代时换位矩阵x行i列的数,也是如此,表示第t次时的矩阵。

运算步骤:

(1)初始时t=0,随机初始化矩阵,U中每个数在0附近。

(2)计算V:

(3)根据得到的V,计算:

其中n为城市数,也就是矩阵V、U的维数。

(4)计算

为步长,类似于学习率,一般为0.1左右。

(5)新的U在回到的(2)步,多次循环,重复步骤(2)(4),最终的矩阵V就是结果。

在上面步骤中,计算矩阵V、U时是按照矩阵中逐个元素计算的,即一一对应(如都是矩阵的x行i列元素),最终得到这个矩阵的结果。我们注意到(3)中,当累加过程中,当i=n时,最后一项中是不存在的,V矩阵没有第n+1列的,兔兔认为这种情况下用就可以了。

关于整个循环过程中每次循环后效果如何,也就是路径是否变短,也可以用网络能量来侧面反映,因为Hopfield网络求TSP问题的思想就是由节点的状态来判断网络的能量,并且随着网络能量的降低逐渐收敛到结果,前面的所有公式也是由网络能量函数推导出来的。

根据每次循环得到的U,V代入上式即可求出此时网络的能量。关于此式最后一项超出维数的问题,和上面处理方法相同。

import numpy as np
class Hopfield:def __init__(self,city_position,circle=50,T=0.1,A=1.5,D=2):self.city_position=city_position #城市位置坐标self.n=len(city_position) #城市个数self.circle=circle #循环次数self.T=T #delta_tself.d=self.d() #距离矩阵self.v=self.v() #换位矩阵self.u0=0.2self.A=Aself.D=Ddef d(self):'''求距离阵'''d=np.zeros((self.n,self.n))for i in range(self.n):for j in range(self.n):if i==j:d[i,j]=0else:d[i,j]=np.sqrt((self.city_position[i,0]-self.city_position[j,0])**2+(self.city_position[i,1]-self.city_position[j,1])**2)return ddef tanh(self,x):return 2/(1+np.exp(-2*x))-1def v(self):'''初始化换位矩阵'''a=np.arange(0,self.n)np.random.shuffle(a)v=np.zeros((self.n,self.n))for i in range(self.n):v[a[i],i]=1return vdef cal_du_dt(self,v):'''计算dU/dt'''du_dt=np.zeros((self.n,self.n))for x in range(self.n):for i in range(self.n):p1=0;p2=0;p3=0for j in range(self.n):p1+=v[x,j]for y in range(self.n):p2+=v[y,i]if i<self.n-1:p3+=self.d[x,y]*v[y,i+1]else:p3+=self.d[x,y]*v[y,0]du_dt[x,i]=-self.A*(p1-1)-self.A*(p2-1)-self.D*p3return du_dtdef update_u(self,ut,du_dt):'''更新矩阵U'''u=ut+du_dt*self.Treturn udef update_v(self,u):'''更新换位矩阵'''return (1+self.tanh(u/self.u0))/2def energy(self,v,u):'''网络能量函数,计算网络能量'''p1=0;p2=0;p3=0for x in range(self.n):a=0for i in range(self.n):a+=v[x,i]p1+=(a-1)**2for i in range(self.n):a=0for x in range(self.n):a+=v[x,i]p2+=(a-1)**2for x in range(self.n):for y in range(self.n):for i in range(self.n):if i<self.n-1:p3+=v[x,i]*self.d[x,y]*v[x,i]*v[y,i+1]else:p3 += v[x, i] * self.d[x, y] * v[x, i] * v[y,0]e=self.A*p1/2+self.A*p2/2+self.D*p3/2return edef hopfield(self):'''主程序'''v_0=self.vu_0=np.random.normal(size=(self.n,self.n)) #初始化V、UE=[] #记录循环过程中网络能量变化for t in range(self.circle):du_dt = self.cal_du_dt(v_0)u=self.update_u(u_0,du_dt)v=self.update_v(u)u_0=uv_0=ve=self.energy(u=u,v=v)E.append(e)result=v_0return result,E
if __name__=='__main__':city_position=np.array([[0,0],[1,4],[5,5],[3,3],[5,2]])hopfield=Hopfield(city_position=city_position)r,e=hopfield.hopfield()

最终我们发现能量变化为:

我们发现能量的确是下降了,说明最终是可以收敛到比较短的路径的结果。但是结果却不是很合理,因为我们要求交换矩阵每一行每一列只能有一个元素为1,其它的为0,但是该程序运行后大部分数很小以至于接近0,其它的比较大的数认为是1,会出现某一行中有多个1,但这是不合理的,偶尔可能会得到比较合理的结果。事实上,用hopfield求解TSP问题本身效果也不是很好,一方面计算速度与其它算法相比较慢,并且会出现陷入局部解的情况,此时虽然网络能量很低,但求得的路径长度还不是比较短的路径。

总结

关于hopfield神经网络,主要用于数据储存恢复以及求解TSP问题,其中主要用途还是用于数据存储与恢复,它或许有些类似大脑存储信息的模式,也有待于深入的研究;而对于求解TSP问题,事实证明效果并不是很好,但是基于网络能量并用微分方程等数学方法以及电路的方法对网络进行分析却是值得深入研究的。本文关于两种方法仅给出了计算方法,而关于这个网络的理论基础以及这些计算公式推导方法,还是需要很大的篇幅,兔兔之后会在另外的文章中探讨。

Hopfield神经网络(HNN)详解相关推荐

  1. Hopfield神经网络实验详解(MATLAB实现)

    前言 分享第二弹,一份神经网络课上布置的实验报告.参数什么的可能在不同电脑上需要有所调整,还望用餐愉快.在此之前会简要介绍一下Hopfield神经网络的知识点. Hopfield网络(离散型) Hop ...

  2. 神经网络算法详解 04:反馈神经网络(Hopfield、BAM、BM、RBM)

    本文介绍了反馈神经网络,包括Hopfield网络,离散Hopfield网络(DHNN),连续Hopfield网络(CHNN),双向联想记忆网络(BAM),玻尔兹曼机(BM),受限玻尔兹曼机(RBM). ...

  3. 神经网络算法详解 01:人工神经网络基础

    本文介绍了人工智能的发展历史,基本概念,应用领域:神经元模型,神经元的学习规则以及神经网络工作原理.本系列文章来自阿里云大学人工智能学习路线中的<神经网络概览及神经网络算法详解>课程. 系 ...

  4. 神经网络的函数表达式,神经网络公式详解pdf

    1.神经网络的准确率是怎么计算的? 其实神经网络的准确率的标准是自己定义的. 我把你的例子赋予某种意义讲解: 1,期望输出[1 0 0 1],每个元素代表一个属性是否存在.像着4个元素分别表示:是否肺 ...

  5. DL之HNN:Hopfield神经网络(HNN之DHNN、CHNN)的相关论文、简介、使用案例之详细攻略

    DL之HNN:Hopfield神经网络(HNN之DHNN.CHNN)的相关论文.简介.使用案例之详细攻略 导读:Hopfield神经网络(HNN)是一种具有循环.递归特性,结合存储和二元系统的神经网络 ...

  6. python神经网络算法pdf_Python与机器学习实战 决策树、集成学习、支持向量机与神经网络算法详解及编程实现.pdf...

    作 者 :何宇健 出版发行 : 北京:电子工业出版社 , 2017.06 ISBN号 :978-7-121-31720-0 页 数 : 315 原书定价 : 69.00 主题词 : 软件工具-程序设计 ...

  7. Siamese网络(孪生神经网络)详解

    SiameseFC Siamese网络(孪生神经网络) 本文参考文章: Siamese背景 Siamese网络解决的问题 要解决什么问题? 用了什么方法解决? 应用的场景: Siamese的创新 Si ...

  8. 使用GPU进行神经网络计算详解

    Pytorch学习笔记(六):使用GPU的简单LeNet网络模型中也提到了如何实现GPU上的运算,虽然不详细,但是也足够. 总结:(如果对于总结知识已经比较熟悉,那么下面的详解可以不用看) 默认CPU ...

  9. 卷积神经网络CNNs详解参考----MNIST

    mnist实例--卷积神经网络(CNN) 使用TensorFlow编写识别数字的CNN训练程序详解 深度学习之卷积神经网络CNN及tensorflow代码实现示例 CNN笔记:通俗理解卷积神经网络

  10. 卷积神经网络(CNN)详解与代码实现

    目录 1.应用场景 2.卷积神经网络结构 2.1 卷积(convelution) 2.2 Relu激活函数 2.3 池化(pool) 2.4 全连接(full connection) 2.5 损失函数 ...

最新文章

  1. java的静态内部类
  2. 全面讲解Python列表数组(四)什么是元组?元组跟列表数组的差异?元组的特征符号是啥子?
  3. 复习java的java.io.File类,深入理解并熟练使用
  4. 告别加班:一个让你不再重复工作的技能
  5. JS最新的身份证验证代码
  6. JQuery:JQuery遍历详解
  7. nginx学习文档之一 安装nginx-Linux下安装nginx
  8. TTL电平与CMOS电平
  9. C.One Piece
  10. 阿里线上bug排查命令
  11. 你我的父母,都在被互联网“割韭菜”
  12. ScheduledThreadPoolExecutor之scheduleWithFixedDelay和scheduleAtFixedRate的区别
  13. 使用Python写登录京东商城购物,加入购物车的脚本
  14. 某运动APP登录协议分析
  15. 文曲星猜数字游戏java代码_Python版的文曲星猜数字游戏代码
  16. 哪个软件能做英语测试,英语考试软件哪个好用 英语考试软件神器推荐
  17. WebSocket实战之一
  18. 哈工大计算机学院崔启航,2014-2015年度哈尔滨工业大学学生先进集体及先进个人评选结果公示...
  19. Docker基本概念
  20. Mac 下使用ISIS 处理数据 -CTX,HiRISE,LRO

热门文章

  1. 有趣的纯CSS实现动态晴阴雨雪
  2. 数据化运营19 传播(上):如何打造千万级的私域运营体系?
  3. 2019年-APP测试流程整理
  4. vijos P1571 笨笨的导弹攻击
  5. Stata+R:一文读懂精确断点回归-RDD
  6. 应届毕业生就不能当总监么?
  7. 百丽季燕利:从补货场景,看企业协同在线|数字思考者50人
  8. IIS无法访问aspx文件的解决方法
  9. python-snap7开发笔记
  10. 互联网金融违约和个人信用的个人理解