Hopfield神经网络是一种递归神经网络,由约翰·霍普菲尔德在1982年发明。Hopfield网络是一种结合存储系统和二元系统的神经网络。它保证了向局部极小的收敛,但收敛到错误的局部极小值(local minimum),而非全局极小(global minimum)的情况也可能发生。Hopfield网络也提供了模拟人类记忆的模型。
离散Hopfield网络是一个单层网络,有n个神经元节点,每个神经元的输出均接到其它神经元的输入。各节点没有自反馈。每个节点都可处于一种可能的状态(1或-1),即当该神经元所受的刺激超过其阀值时,神经元就处于一种状态(比如1),否则神经元就始终处于另一状态(比如 -1)。 整个网络有两种工作方式:即异步方式和同步方式。
联想记忆功能是离散Hopfield网络的一个重要应用范围。要想实现联想记忆,反馈网络必须具有两个基本条件:
① 网络能收敛到稳定的平衡状态,并以其作为样本的记忆信息;
② 具有回忆能力,能够从某一残缺的信息回忆起所属的完整的记忆信息。 离散Hopfield网络实现联想记忆的过程分为两个阶段:学习记忆阶段和联想回忆阶段。在学习记忆阶段中,设计者通过某一设计方法确定一组合适的权值,使网络记忆期望的稳定平衡点。联想回忆阶段则是网络的工作过程。
离散Hopfield网络用于联想记忆有两个突出的特点:即记忆是分布式的,而联想是动态的。 离散Hopfield网络局限性,主要表现在以下几点:
① 记忆容量的有限性;
② 伪稳定点的联想与记忆;
③ 当记忆样本较接近时,网络不能始终回忆出正确的记忆等。另外网络的平衡稳定点并不可以任意设置的,也没有一个通用的方式来事先知道平衡稳定点。
Hopfield 神经网络除了有离散型,还有连续型,在连续型 Hopfield 神经网络中引入暂态混沌和时变增益构造的混沌神经网络定义如下:

式中的 z(t)(x(t) - I0) 与自抑制反馈有关,是 产生混沌的主要原因。随 着 z(t) 和 ε(t) 在时间上的不断衰减,通过一个倍周期倒分叉的连续混沌分叉过程,网络将逐渐趋近于一个稳定的平衡点。变量 z(t) 和 ε(t) 对应着常规随机模拟退火中的温度,它按指数变化控制着网络的混沌收敛行为和倒分叉的速度。
为了更好地分析上述模型的运行机理,以单个神经元为例(令α=0),分析混沌 Hopfield 神经网络的动力学特性。
我们选取的激活函数为sigmoid函数,就是上式中的 f(y(t))

设置网络参数分别为:
β = 0.001
γ = 0.001
k = 1.0
I_0 = 0.65
z_0 = 0.8
ε_0 = 20
y_0 = 0.5
则网络的输出 V(t)、退温函数z(t)、ε(t) 的演化过程分别如下图所示。由图,该网络具有暂态混沌动力学行为,随 着z(t) 和 ε(t) 的 不断衰减,通过一个倍周期逆分岔的连续混沌分岔过程,网络将逐渐趋近于一个稳定的平衡点。


当我们选取的激活函数为tanh函数时,该系统的混沌系统为更加明显
tanh
x
=
e
x
−
e
−
x
e
x
+
e
−
x
\tanh x=\frac{e^x-e^{-x}}{e^x+e^{-x}}
tanhx=ex+e−xex−e−x

大家可以试试其他激活函数,比如softPlus、arcTan、softsign、bent_identity、symmetrical_sigmoid、log_log、gauss、Morlet、ReLU、P-ReLU、Leaky-ReLU、Maxout 等等
import numpy as np
import matplotlib.pyplot as plt
def sigmoid(x):
return 1./(1+np.exp(-x))
def hopfield(y_t0,z0,r0):
x_t = sigmoid(((y_t0)*(1 + r0)))
y_t = k * y_t0 - z0 * (x_t - I0)
z_t = (1 - b) * z0
r_t = (1 - c) * r0
list_xt.append(x_t)
return y_t, z_t, r_t
if __name__ == '__main__':
list_xt = []
list_yt = []
list_I0 = []
list_zt = []
list_rt = []
listi = []
b = 0.001 # 0
c = 0.001 # 0
k = 1.0 # 0<=k<=1
I0 = 0.65
z0 = 0.8 # z(t)>=0
r0 = 20 # r(t)>0
y_t0 = 0.5
for i in range(1500):
y_t1, z1, r1 = hopfield(y_t0, z0, r0)
y_t0 = y_t1
z0 = z1
r0 = r1
list_I0.append(I0)
list_yt.append(y_t0)
list_zt.append(z0)
list_rt.append(r0)
listi.append(i)
plt.figure()
plt.title('Hopfield Bifurcation--activation:sigmoid')
plt.tick_params(labelsize=15)
plt.xlabel('迭代次数', fontsize=15)
plt.ylabel('V(t)', fontsize=15)
plt.grid(True, color='c', linestyle='--', linewidth='1')
plt.scatter(listi, list_yt, c='r', marker='.', s=1)
plt.figure()
plt.subplot(2, 1, 1)
plt.tick_params(labelsize=15)
plt.ylabel('z(t)', fontsize=15)
plt.grid(True, color='c',linestyle='--',linewidth='1')
plt.scatter(listi, list_zt, c='r',marker='.', s=1)
plt.subplot(2, 1, 2)
plt.tick_params(labelsize=15)
plt.xlabel('迭代次数', fontsize=15)
plt.ylabel('ε(t)', fontsize=15)
plt.grid(True, color='c',linestyle='--',linewidth='1')
plt.scatter(listi, list_rt, c='r',marker='.', s=1)
plt.show()