在看随机神经网络的时候,发现许多都提到了玻尔兹曼机。Hopfield神经网络是玻尔兹曼机的基础。所以来学习了H网络。Hopfield网络是最早被提出具有稳定性的反馈网络之一,对后来的工作有很大的影响,例如Hinton就受此启发提出了玻尔兹曼机(听这名字就知道也是跟物理学有关系)。本篇文章非原创
Hopfield神经网络是个老古董了,它把生物的联想记忆用物理意义非常直观的方式表示出来,从物理学的角度对记忆和学习给出了有意思的解释,其背后蕴藏的思想深远,称得上是经典或者说里程碑。最原始的Hopfield神经网络是个全连接网络,即网络中任意两个神经元之间都有连接,在数学上这叫完全图(complete graph)。实际大脑中的神经网络是局部连接的网络而不是全连接网络,否则连接数量会爆炸式增长,现在的神经网络一般也不采用这种全连接网络了,因为参数多不好训练,很多连接都被删掉了,变成了一层一层的形状。
任何一种神经网络都可以从两个方面来分析它,一个是全局的,即神经元之间是如何连接的,或者说网络的结构是什么样的;一个是局部的,即 单个神经元是什么样的,它有什么输入输出特性。Hopfield网络也不例外,它具有以下特点: 1 全局特点:最原始的Hopfield神经网络是个全连接网络,即网络中任意两个神经元之间都有连接,在数学上这叫完全图(complete graph),如下图左所示的8个神经元的例子。你可以认为Hopfield网络里的神经元都是社交高手,跟谁都是朋友。连接的权重根据Hebb法则设计。 实际大脑中的神经网络是局部连接的网络而不是全连接网络,否则连接数量会爆炸式增长,现在的神经网络一般也不采用这种全连接网络了,因为参数多不好训练,很多连接都被删掉了,变成了一层一层的形状。 2 局部特点:最原始的Hopfield神经网络中的神经元非常简单,与比它更古老的感知机一样:神经元对输入线性加权求和之后通过激活函数得到输出,采用的激活函数就是阈值函数,如下图右所示。输出被限制为离散的两个值:不是0就是1,这可能也是为了与Ising模型做类比,最简单的Ising模型中spin的状态也是只有两种:不是向上就是向下。后来Hopfield把采用的神经元推广到连续变化的类型,现在的深度学习模型也不再用这种过于简单的离散激活函数,一般用ReLU或者Tanh等连续函数。
Hopfield神经网络是个全连接网络,没有像前馈网络中前后层的概念,每个神经元既可以看成输入也可以看成输出。所以Hopfield神经网络也可以看成反馈神经网络,即输出又会反馈回输入,从而形成一个信号环路,这与前馈神经网络(比如卷积神经网络)不同,这也是Hopfield神经网络最大的价值,此前人们研究比较多的是前馈网络,对反馈网络了解不多,Hopfield网络是个突破。它们最主要区别就是:反馈神经网络是动态系统(随时间变化),而前馈神经网络是静态系统(输出只取决于输入,跟时间没关系)。反馈神经网络是一个动力系统,人们提到动力系统首先关心的就是它的稳定性,因为一个不稳定的网络除了崩溃也没什么用,所以反馈神经网络的稳定性是经常被研究的课题。反之,前馈神经网络就是一个大函数,从输入到输出很直接,不存在稳定性的问题,所以不需要研究前馈神经网络的稳定性。Hopfield神经网络如此有名就是因为Hopfield给出了稳定性的证明,系统演化总是向着稳定点前进直到到达稳定点后不再变化。 笔者认为Hopfield最大的创新就是利用Lyapunov方法证明了按照Hebb法则设计权重的神经网络的稳定性,在这以前人们不知道怎么分析反馈神经网络的稳定性,Hopfield开了个头,后人才能蜂拥而上。我猜Hopfield本人可能也没有意识到自己的工作能引起这么大的反响,Hopfield后来也在继续研究神经网络(老爷子80多了),但是好像没有能超越Hopfield网络的工作了。
以上来源于 https://blog.csdn.net/robinvista/article/details/106862794
DHNN网络中的每个神经元都有相同的功能,其输出称为状态,用x_j表示,所有神经元状态构成的反馈网络的状态 X = [ x 1 , x 2 , . . . . , x n ] T X = [x_1,x_2,....,x_n]^T X=[x1,x2,....,xn]T,反馈网络的初始状态为输入表示为 X ( 0 ) = [ x 1 ( 0 ) , x 2 ( 0 ) , . . . , x n ( 0 ) ] T X(0) = [x_1(0),x_2(0),...,x_n(0)]^T X(0)=[x1(0),x2(0),...,xn(0)]T,一旦初始值给定后,网络就开始进行动态演变,网络中的每个神经元的状态在不断的变化,变化规律如下: x j = f ( n e t j ) j = 1 , 2 , 3 , . . . , n x_j = f(net_j) \quad j = 1,2,3,...,n xj=f(netj)j=1,2,3,...,n 式中, f ( ⋅ ) f(\cdot ) f(⋅)为激活函数(转移函数),通常为符号函数:
x j = s g n ( n e t j ) = { 1 , n e t j ≥ 0 j = 1 , 2 , 3 , . . , n − 1 , n e t j < 0 ( 1 ) x_j = sgn(net_j) = \left\{\begin{matrix} 1, net_j\geq 0 & \\ &\quad j = 1,2,3,..,n\\ & \\ -1,net_j< 0& \end{matrix}\right. (1) xj=sgn(netj)=⎩⎪⎪⎨⎪⎪⎧1,netj≥0−1,netj<0j=1,2,3,..,n(1) 输入 n e t j net_j netj为;
n e t j = ∑ i = 1 n ( w i j x i − T j ) j = 1 , 2 , 3 , . . . , n net_j = \sum_{i=1}^{n}(w_{ij}x_i - T_j) \quad j=1,2,3,...,n netj=i=1∑n(wijxi−Tj)j=1,2,3,...,n
对于DHNN网络,一般有 w i i = 0 , w i j = w j i . w_{ii}=0,w_{ij}=w_{ji}. wii=0,wij=wji.
当网络的每个神经元的状态都不在改变时,此时的转态就是网络的输出转态,表示为: lim t → ∞ x ( t ) \lim_{t\rightarrow \infty }x(t) t→∞limx(t)
网络达到稳定时的状态x,称为网络的吸引子。一个动力学的系统的最终行为是由他的吸引子决定的,若把需要记忆的样本信息存储于不同的吸引子中,当输入含有部分记忆信息的样本时,网络的演变过程便是从部分信息寻找全部信息,即联想回忆的过程。 下面给出DHNN网络的吸引子的定义和定理:
1. 若网络状态x满足x = f(W^Tx - T) ,则称x为网络的吸引子 2.对于DHNN网络,若按照异步方式调整网络的状态,且连接权矩阵w为对称阵,则对于任意的初态,网络都最终收敛到一个吸引子中。下面通过能量函数对对定理1进行证明:
定义网络的能量函数为:
E ( t ) = − 1 2 X T ( t ) W X ( t ) + X T ( t ) X ( 2 ) E(t) = -\frac{1}{2}X^T(t)WX(t) + X^T(t)X \qquad (2) E(t)=−21XT(t)WX(t)+XT(t)X(2)
这个函数是根据动力学来的,来源我也不是很清楚,我们只需接受即可。
令网络能量的改变量为 Δ E \Delta E ΔE,网络状态的改变量为 Δ x \Delta x Δx,则: Δ E ( t ) = E ( t + 1 ) − E ( t ) ( 3 ) \Delta E(t) = E(t+1) - E(t) \qquad (3) ΔE(t)=E(t+1)−E(t)(3) Δ x ( t ) = x ( t + 1 ) − x ( t ) ( 4 ) \Delta x(t) = x(t+1) - x(t) \qquad (4) Δx(t)=x(t+1)−x(t)(4)
将(3)、(4)两式代入(2)式得:
Δ E ( t ) = E ( t + 1 ) − E ( t ) \Delta E(t) = E(t+1) - E(t) ΔE(t)=E(t+1)−E(t)
= − Δ x T ( t ) [ w x ( t ) − T ] − 1 2 Δ x T ( t ) w Δ x ( t ) = -\Delta x^T(t)[wx(t)-T] - \frac{1}{2}\Delta x^T(t)w\Delta x(t) =−ΔxT(t)[wx(t)−T]−21ΔxT(t)wΔx(t)
按照上面的异步工作方式,第t个时刻只有一个神经元调整状态,设该神经元为j,将 Δ x ( t ) = [ 0 , 0 , . . . , Δ x j ( t ) , 0 , . . . , 0 ] \Delta x(t) = [0,0,...,\Delta x_j(t),0,...,0] Δx(t)=[0,0,...,Δxj(t),0,...,0]代入上式,并考虑w为对称矩阵: Δ E ( t ) = − Δ x j ( t ) [ ∑ i = 1 n ( w i j − T j ) ] − 1 2 Δ x j 2 ( t ) w i j \Delta E(t) = -\Delta x_j(t)[\sum_{i=1}^{n}(w_{ij} - T_j)] - \frac{1}{2}\Delta x_j^2(t)w_{ij} ΔE(t)=−Δxj(t)[i=1∑n(wij−Tj)]−21Δxj2(t)wij
因为各自神经元不存在自反馈,所以, w i i = 0 w_{ii} = 0 wii=0,并将上式化简为: Δ E ( t ) = − Δ x j ( t ) n e t j ( t ) ( 5 ) \Delta E(t) = -\Delta x_j(t)net_j(t) \quad (5) ΔE(t)=−Δxj(t)netj(t)(5)
下面我们就要针对 Δ E \Delta E ΔE进行讨论:
情况1. x j ( t ) = − 1 , x j ( t + 1 ) = 1 x_j(t) = -1, x_j(t+1) = 1 xj(t)=−1,xj(t+1)=1即输入输出为异号时,根据(4)式得到\Delta x_j(t) = 2,因此net_j\geq 0,代入(5)式得 到: Δ E ( t ) ≤ 0. \Delta E(t)\leq 0. ΔE(t)≤0.
注:这里解释一下,因为 x j ( t ) = − 1 x_j(t) = -1 xj(t)=−1,而经过sgn(net_j)后 x j ( t + 1 ) = 1 x_j(t+1) = 1 xj(t+1)=1,说明 n e t j = 0 net_j= 0 netj=0,否则得不到 x j ( t + 1 ) = 1 x_j(t+1) = 1 xj(t+1)=1,因为符号函数要想得到1,输入必须大于等于0,下面一样的思考。
情况2. x j ( t ) = 1 , x j ( t + 1 ) = − 1 x_j(t) = 1, x_j(t+1) = -1 xj(t)=1,xj(t+1)=−1,即输入输出为同号时,根据(4)式得到\Delta x_j(t) =- 2,因此net_j< 0,代入5式得 到:
\Delta E(t)< 0.情况3. x_j(t) = x_j(t+1),所以\Delta x_j(t)=0,从而得到: Δ E ( t ) = 0 \Delta E(t)= 0 ΔE(t)=0
下面继续讨论E(t)收敛于常数时,是否对应于网络的稳态,当E(t)收敛与常数时,此时的\Delta E(t)= 0,此时对应两种情况:
情况1, x j ( t ) = x j ( t + 1 ) = 1 x_j(t) = x_j(t+1) = 1 xj(t)=xj(t+1)=1或者 x j ( t ) = x j ( t + 1 ) = − 1 x_j(t) = x_j(t+1) = -1 xj(t)=xj(t+1)=−1,这种情况下,神经元的状态不在改变,表明已经达到稳态了,此时对应的网络状态为吸引子状态。
情况2, x j ( t ) = − 1 , x j ( t + 1 ) = 1 , n e t j ( t ) = 0 x_{j} (t) =-1,x_j(t+1) =1,net_j(t) = 0 xj(t)=−1,xj(t+1)=1,netj(t)=0,这种情况下网络继续演变时, x j = 1 x_j = 1 xj=1将不会在变化,如果x_j由1变化为-1,此时 Δ E ( t ) < 1 \Delta E(t)< 1 ΔE(t)<1,因此和收敛常数相矛盾。 综上所述,当网络工作方式和权值满足定理时则一定收敛到一个吸引子。
以上文章来自https://blog.csdn.net/weixin_42398658/article/details/83991773
所谓联想和记忆,就是将一幅有噪声的图转化为无噪声的图。
算法步骤: 输入无噪声样本(input the sample)构建图及其权重在构建好的图中输入有噪声样本,数据像涟漪一样在图中震荡(就是循环多次) #1.根据Hebb学习规则计算神经元之间的连接权值 def calcWeight(savedsample): N = len(savedsample[0]) P = len(savedsample) mat = [0]*N returnMat = [] for i in range(N): m = mat[:] returnMat.append(m) for i in range(N): for j in range(N): if i==j: continue sum = 0 for u in range(P): sum += savedsample[u][i] * savedsample[u][j] returnMat[i][j] = sum/float(N) return returnMat # 2.根据神经元的输入计算神经元的输出(静态突触) def calcXi(inMat , weighMat): returnMat = inMat choose = [] for i in range(len(inMat)/5): #随机改变N/5个神经元的值,该参数可调,也可同时改变所有神经元的值 choose.append(random.randint(0,len(inMat)-1)) for i in choose: sum = 0 for j in range(len(inMat)): sum += weighMat[i][j] * inMat[j] if sum>=0: returnMat[i] = 1 else: returnMat[i] = -1 return returnMat # 加噪函数,在记忆样本的基础上增加30%的噪声: def addnoise(mytest_data,n): for x in range(n): for y in range(n): if random.randint(0, 10) > 7: mytest_data[x * n + y] = -mytest_data[x * n + y] return mytest_data # 标准输出函数: def regularout(data,N): for j in range(N): ch = "" for i in range(N): ch += " " if data[j*N+i] == -1 else "X" print ch # 记忆样本,4个5x5的矩阵(来源于网络,分别表示字母N,E,R,0): sample = [[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]] # 测试代码及结果: weightMat = calcWeight(sample) regularout(sample[1],5) test = addnoise(sample[1],5) regularout(test,5) for i in range(2000): test = calcXi(test,weightMat) regularout(test,5)从上到下,第一张为记忆样本、第二张为加噪的记忆样本、第三张为循环2000次后回忆出的结果
代码来自https://blog.csdn.net/chenge_j/article/details/71663026?utm_medium=distribute.pc_relevant.none-task-blog-title-4&spm=1001.2101.3001.4242