Hopfield网络(Hopfield Network)

Hopfield神经网络是一种递归神经网络,由约翰·霍普菲尔德在1982年发明。Hopfield网络是一种结合存储系统和二元系统的神经网络。它保证了向局部极小的收敛,但收敛到错误的局部极小值(local minimum),而非全局极小(global minimum)的情况也可能发生。Hopfield网络也提供了模拟人类记忆的模型。

Hopfield提出了连续和离散的Hopfield神经网络模型,并采用全互联型神经网络尝试对非多项式复杂度的旅行商问题(Travelling Salesman Problem,TSP)进行了求解,促进神经网络的研究再次进入了蓬勃发展的时期。

Hopfield强调工程实践的重要性,他利用电阻、电容和运算放大器等元件组成的模拟电路实现了对网络神经元的描述,把最优化问题的目标函数转换成Hopfield神经网络的能量函数,通过网络能量函数最小化来寻找对应问题的最优解.Hopfield网络是一种循环神经网络,从输出到输入有反馈连接,典型的Hopfield神经网络模型如图所示.

在图中每组运算放大器及其相关的电阻、电容组成的网络代表一个神经元。每个神经元有两组输入,一组是恒定的外部电流,另一组是来自其他运算放大器输出的正向或反向的反馈连接。假设第i个神经元的内部膜电位为Ui(i=1,2,…,n),细胞膜的输入电容和传递电阻分别为Ci和Ri,神经元的输出电位为Vi,外部输入电流为Ii,并用电阻Rij(i,j=1,2,…,n)来模拟第i个和第j个神经元之间的突触特性。由基尔霍夫电流定律(Kirchhoff’s Cureent Law ,KCL)可知,放大器输入节点处的流入电流和流出电流保持平衡,亦即有下式成立:

同时,每一个运算放大器模拟了神经元输入和输出之间的非线性特性,即有

其中,fi代表了第i个神经元的传递函数,并定义W=Rij-1 (i,j=1,2,…,n)为网络的权系数矩阵.为证明连续型网络的稳定性,Hopfield定义了如下的能量函数:

其中,f-1为神经元传递函数的反函数.经过推导后得出以下两点结论:一是对于具有单调递增传递函数且对称权系数矩阵的网络来说,其能量会随着时间的变化而趋于稳定;二是当且仅当网络中所有神经元的输出不再随时间变化时,则可以认为网络的能量保持不变。在将网络用于求解诸如旅行商的组合优化问题时,Hopfield将优化的目标函数转化为网络的能量函数,对应地将待求解问题的变量用网络中神经元的状态来表示。由这样的表示方式可知当网络的能量衰减到稳定值时,问题的最优解也随之求出。

Hopfield网络按网络输入和输出的数字形式不同可分为离散型和连续型两种网络,即:离散型Hopfield神经网络----DHNN(Discrete Hopfield Neural Network);连续型Hopfield神经网络----CHNN(ContinuesHopfield Neural Network)。

DHNN结构:它是一种单层全反馈网络,共有n个神经元。每个神经元都通过连接权接收所有其它神经元输出反馈来的信息,其目的是为了让任一神经元的输出能接受所有神经元输出的控制,从而使各神经元能相互制约。

DHNN的设计原则:吸引子的分布是由网络的权值(包括阀值)决定的,设计吸引子的核心就是如何设计一组合适的权值。为了使所设计的权值满足要求,权值矩阵应符合以下要求:(1)为保证异步方式工作时网络收敛,W应为对称阵;(2)为保证同步方式工作时网络收敛,W应为非负定对称阵;(3)保证给定的样本是网络的吸引子,并且要有一定的吸引域。

具体设计时,可以采用不同的方法:(1)联立方程法;(2)外积和法。

CHNN:在连续型Hopfield神经网络中,所有神经元都随时间t并行更新,网络状态随时间连续改变。

优缺点

Hopfield网络是一种非线性的动力网络,可通过反复的网络动态迭代来求解问题,这是符号逻辑方法所不具有的特性。在求解某些问题时,其求解问题的方法与人类求解问题的方法很相似,虽然所求得的解不是最佳解,但其求解速度快,更符合人们日常解决问题的策略。

Hopfield神经网络的提出就是与其实际应用密切相关。具有联系记忆的功能,具体为:

联想记忆:输入–输出模式的各元素之间,并不存在一对一的映射关系,输入–输出模式的维数也不要求相同;联想记忆时,只给出输入模式部分信息,就能联想出完整的输出模式。即具有容错性。

应用领域

import numpy as np
from random import randint, shuffle

class InvalidWeightsException(Exception):
pass


class InvalidNetworkInputException(Exception):
pass

class HopfieldNetwork(object):
def __init__(self, num_inputs):
self._num_inputs = num_inputs
self._weights = np.random.uniform(-1.0, 1.0, (num_inputs, num_inputs))

def set_weights(self, weights):
"""Update the weights array"""
if weights.shape != (self._num_inputs, self._num_inputs):
raise InvalidWeightsException()

self._weights = weights

def get_weights(self):
"""Return the weights array"""
return self._weights

def calculate_neuron_output(self, neuron, input_pattern):
"""Calculate the output of the given neuron"""
num_neurons = len(input_pattern)

s = 0.0

for j in range(num_neurons):
s += self._weights[neuron][j] * input_pattern[j]

return 1.0 if s > 0.0 else -1.0

def run_once(self, update_list, input_pattern):
"""Iterate over every neuron and update it's output"""
result = input_pattern.copy()

changed = False
for neuron in update_list:
neuron_output = self.calculate_neuron_output(neuron, result)

if neuron_output != result[neuron]:
result[neuron] = neuron_output
changed = True

return changed, result

def run(self, input_pattern, max_iterations=10):
"""Run the network using the input data until the output state doesn't change
or a maximum number of iteration has been reached."""
iteration_count = 0

result = input_pattern.copy()

while True:
update_list = range(self._num_inputs)
shuffle(update_list)

changed, result = self.run_once(update_list, result)

iteration_count += 1

if not changed or iteration_count == max_iterations:
return result

原文:https://github.com/KeKe-Li/tutorial