【1】引言
前序学习进程中,除了对基本的神经网络知识举行了学习,还把握了SOM神经网络原理,文章链接包括且不限于:
神经网络|(十一)|神经元和神经网络-CSDN博客
神经网络|(十二)|常见激活函数-CSDN博客
神经网络|(十三)|SOM神经网络-CSDN博客
在此基础上,本篇文章学习一个新的神经网络:霍普菲尔德神经网络。
【2】霍普菲尔德神经网络原理
霍普菲尔德神经网络和SOM神经网络一样不走平常路,SOM神经网络着力于找出和输入最近的点,霍普菲尔德神经网络更关注两两元素之间成对的程度。
到这里可以直接进入代码学习,通过代码的设计来读懂霍普菲尔德神经网络的原理。
明白霍普菲尔德神经网络需要至少在神经网络算法和神经网络模子两个层面上完成明白。需要注意的是:神经网络算法是神经网络模子的练习手段,模子是大框架,算法是实行方法。
霍普菲尔德神经网络算法具体练习时有两种方法供选择,一种是Hebbian方法,另一种是Storkey方法。
【3】代码明白
【3.1】Hebbian方法练习霍普菲尔德神经网络
【3.1.1】预备工作
起首是完成预备工作,引入须要模块:
- import numpy as np #引入numpy模块
- import matplotlib.pyplot as plt #引入matplotlib模块
复制代码 【3.1.2】主函数
直接阅读主函数是我们链接整改步伐的关键,主函数通过把算法实施过程拆解为调用不同的子函数,直观表达了步伐运行框架。
- # 示例:创建一些简单的模式
- patterns = [
- np.array([1, 1, 1, -1, -1, -1]),
- np.array([-1, -1, -1, 1, 1, 1])
- ]
- # 初始化权重
- n_neurons = len(patterns[0])
- weights = initialize_weights(n_neurons)
- # 训练网络
- weights = train(weights, patterns)
- # 测试回忆功能
- initial_state = np.array([1, 1, 1, -1, -1, -1])
- recalled_pattern = recall(weights, initial_state)
复制代码 主函数直接调用了initialize_weights()、train()和recall()三个子函数,它们分别实行权重初始化、模子练习和测试回想功能,下一步即可对这些子函数举行学习。
【3.1.3】子函数
【3.1.3.1】initialize_weights()函数
- # 定义初始化函数
- def initialize_weights(n_neurons):
- """
- 初始化霍普菲尔德网络的权重矩阵
- :param n_neurons: 神经元的数量
- :return: 初始的权重矩阵
- """
- # 返回一个(n_neurons行, n_neurons列)纯0矩阵
- return np.zeros((n_neurons, n_neurons))
复制代码 initialize_weights()函数生成的是 (n_neurons行, n_neurons列)纯0矩阵,作为权重weights的初始值。
【3.1.3.2】train()函数
- # 训练模型传入的参数有weights和patterns
- def train(weights, patterns):
- """
- 使用 Hebbian 学习规则训练网络
- :param weights: 权重矩阵
- :param patterns: 训练模式的列表
- :return: 训练后的权重矩阵
- """
- for pattern in patterns:
- # 将pattern转化为一个列向量
- pattern = pattern.reshape(-1, 1)
- # weights是在自身的基础上叠加pattern自身的平方
- weights += np.dot(pattern, pattern.T)
- # 确保对角线元素为 0
- # 通过内置函数,让weights处于对角线上的元素都为0
- np.fill_diagonal(weights, 0)
- # 除以总模数,进行归一化操作
- weights /= len(patterns)
- return weights
复制代码 train()函数调用weights和patterns两个参数,先将patterns转置为纯列向量,然后自身和自身作矩阵点乘运算,点乘运算效果是一个 (n_neurons行, n_neurons列)矩阵,所以可以和weights矩阵按位置做加法。
由于霍普菲尔德神经网络以为元素两两之间有关系,但自己和自己不能用权重来权衡。
weights矩阵的对角线就代表了元素自己和自己的毗连权重,所以需要调用一个np.fill_diagonal()函数让新获得的weights矩阵对角线上的元素为0。
然后把weights做了归一化处置惩罚。
【3.1.3.3】recall()函数
- def recall(weights, initial_state, max_iterations=100):
- """
- 从初始状态回忆模式
- :param weights: 权重矩阵
- :param initial_state: 初始状态
- :param max_iterations: 最大迭代次数
- :return: 回忆出的模式
- """
- # state是对state的复制
- state = initial_state.copy()
- for _ in range(max_iterations):
- # 新的state通过update函数更新
- new_state = update(weights, state)
- if np.array_equal(new_state, state):
- break
- state = new_state
- return state
复制代码 recall()函数要求调用update()函数生成新状态,用新状态来覆盖旧状态。
【3.1.3.4】update()函数
- def update(weights, state):
- """
- 更新网络状态
- :param weights: 权重矩阵
- :param state: 当前网络状态
- :return: 更新后的网络状态
- """
- # state转化为列向量
- state = state.reshape(-1, 1)
- # 先用weights和state矩阵相乘,然后用np.sign()函数返回1,-1和0
- # np.sign()函数,参数为正返回1,参数为负返回-1,参数为0返回0
- new_state = np.sign(np.dot(weights, state))
- return new_state.flatten()
复制代码 代码运行获得的图像为:
图1 hebbian练习效果
此时的完整代码为:
- import numpy as np #引入numpy模块
- import matplotlib.pyplot as plt #引入matplotlib模块# 定义初始化函数
- def initialize_weights(n_neurons):
- """
- 初始化霍普菲尔德网络的权重矩阵
- :param n_neurons: 神经元的数量
- :return: 初始的权重矩阵
- """
- # 返回一个(n_neurons行, n_neurons列)纯0矩阵
- return np.zeros((n_neurons, n_neurons))# 训练模型传入的参数有weights和patterns
- def train(weights, patterns):
- """
- 使用 Hebbian 学习规则训练网络
- :param weights: 权重矩阵
- :param patterns: 训练模式的列表
- :return: 训练后的权重矩阵
- """
- for pattern in patterns:
- # 将pattern转化为一个列向量
- pattern = pattern.reshape(-1, 1)
- # weights是在自身的基础上叠加pattern自身的平方
- weights += np.dot(pattern, pattern.T)
- # 确保对角线元素为 0
- # 通过内置函数,让weights处于对角线上的元素都为0
- np.fill_diagonal(weights, 0)
- # 除以总模数,进行归一化操作
- weights /= len(patterns)
- return weightsdef update(weights, state):
- """
- 更新网络状态
- :param weights: 权重矩阵
- :param state: 当前网络状态
- :return: 更新后的网络状态
- """
- # state转化为列向量
- state = state.reshape(-1, 1)
- # 先用weights和state矩阵相乘,然后用np.sign()函数返回1,-1和0
- # np.sign()函数,参数为正返回1,参数为负返回-1,参数为0返回0
- new_state = np.sign(np.dot(weights, state))
- return new_state.flatten()def recall(weights, initial_state, max_iterations=100):
- """
- 从初始状态回忆模式
- :param weights: 权重矩阵
- :param initial_state: 初始状态
- :param max_iterations: 最大迭代次数
- :return: 回忆出的模式
- """
- # state是对state的复制
- state = initial_state.copy()
- for _ in range(max_iterations):
- # 新的state通过update函数更新
- new_state = update(weights, state)
- if np.array_equal(new_state, state):
- break
- state = new_state
- return state# 示例:创建一些简单的模式patterns = [ np.array([1, 1, 1, -1, -1, -1]), np.array([-1, -1, -1, 1, 1, 1])]# 初始化权重# 获得patterns第一个元素,也就是np.array([1, 1, 1, -1, -1, -1])中数字的数目n_neurons = len(patterns[0])weights = initialize_weights(n_neurons)# 练习网络weights = train(weights, patterns)# 测试回想功能initial_state = np.array([1, 1, 1, -1, -1, -1])recalled_pattern = recall(weights, initial_state)# 可视化效果plt.figure(figsize=(12, 4))plt.subplot(1, 3, 1)plt.imshow(initial_state.reshape(1, -1), cmap='gray')plt.title('Initial State')plt.subplot(1, 3, 2)plt.imshow(recalled_pattern.reshape(1, -1), cmap='BuGn')plt.title('Recalled Pattern')plt.subplot(1, 3, 3)plt.imshow(patterns[0].reshape(1, -1), cmap='Blues')plt.title('Original Pattern')plt.show()
复制代码 update()函数根据weights和state矩阵点乘的效果,调用内置函数np.sign()函数举行判断,当矩阵点乘的效果为正返回1,为负返回-1,为0返回0。
因为weights是一个(n_neurons行, n_neurons列)矩阵,state是一个(n_neurons行, 1列)矩阵,所以盘算获得的new_state是一个(n_neurons行, 1列)矩阵,update()函数返回的是(1行, n_neurons列)矩阵。
【3.1.4】综合分析
经过对主函数和子函数的阅读明白,可以发现,Hebbian方法的霍普菲尔德神经网路算法依照原则是:
如果元素构成为:X=[X1,X2,...,Xn],就可以按照这个大小生成一个nXn的权重矩阵weights;
让所有的元素两两相乘,也获得nXn的dot(X,XT)(XT是X的转置),再让dot(X,XT)和weights同一位置的元素相加,这样就获得新的权重。新的权重实际上叠加了元素相乘的积,所以权重本身含有元素的大小。
实际上到这一步,就已经完成了练习,下一步是测试功能,所以会有recall()函数来举行检验。
recall函数会要求先更新权重,这是因为练习过程中已经盘算出新权重,测试数据和原始数据已经不一样,所以要依据权重数据和测试数据的关系,对状态数据举行更新,更新后的状态数据会覆盖旧有的状态数据。
recall函数在新的状态下,成功探索出了原有状态。
【4】细节说明
对于weights矩阵的练习过程,有一个归一化的操作。
【5】总结
探索了霍普菲尔德神经网络的基本知识,基于python语言,调用hebbian方法对霍普菲尔德神经网络算法举行了初步练习和测试。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |