神经网络|(十五)|霍普菲尔德神经网络-Storkey 训练

【1】引言

前序学习进程中,对霍普菲尔德神经网络有了初步认识,使用Hebbian方法测试了霍普菲尔德神经网络算法。相关学习文章链接为:

神经网络|(十四)|霍普菲尔德神经网络-CSDN博客

在此基础上,尝试探索使用Storkey方法对霍普菲尔德神经网络算法进行测试。

【2】代码测试

和Hebbian训练方法一样,Storkey训练方法需要提前完成准备工作,定义子函数和主函数,完成实际效果测试。

【2.1】准备工作

准备工作需要引入必要模块:

import numpy as np #引入numpy模块
import matplotlib.pyplot as plt #引入nmatplotlib模块

【2.2】主函数

主函数通过把算法实施过程拆解为调用不同的子函数,直观表达了程序运行框架。

# 示例:创建一些简单的模式
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()

主函数直接调用了initialize_weights()、train()和recall()三个子函数,它们分别执行权重初始化、模型训练和测试回忆功能,下一步即可对这些子函数进行学习。

【2.3】子函数

【2.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的初始值。

【2.3.2】train()函数
# 训练模型传入的参数有weights和patterns
def train(weights, patterns):
    """
    使用 Storkey 学习规则训练网络
    :param weights: 权重矩阵
    :param patterns: 训练模式的列表
    :return: 训练后的权重矩阵
    """
    for pattern in patterns:
        # 将pattern转化为列向量
        # 由于每个pattern中有n_neurons个元素,所以pattern转化后的列向量有n_neurons行
        pattern = pattern.reshape(-1, 1)
        # n获取pattern向量的行数,n=n_neurons
        n = len(pattern)
        for i in range(n):
            for j in range(n):
                if i != j:
                    # 让不同的pattern元素彼此相乘
                    term1 = pattern[i] * pattern[j]
                    # 初始值赋值0
                    term2 = 0
                    # 初始值赋值0
                    term3 = 0
                    for k in range(n):
                        if k != i and k != j:
                            # weights矩阵的结构是(n_neurons行,n_neurons列)
                            # term2考虑了第k和第j个pattern元素对i行k列权重的影响
                            term2 += weights[i, k] * pattern[k] * pattern[j]
                            # term3考虑了第k和第j个pattern元素对j行k列权重的影响
                            term3 += weights[j, k] * pattern[k] * pattern[i]
                    # 3个term进行了综合
                    delta_w = term1 - term2 - term3
                    # 确保 delta_w 是标量
                    weights[i, j] += delta_w.item()
    # 确保对角线元素为 0
    np.fill_diagonal(weights, 0)
    # 除以总模数,进行归一化操作
    weights /= len(patterns)
    return weights

Storkey方法的train()函数和Hebbian方法有显著不同,Storkey方法获得weights的过程更为复杂,考虑了综合影响。

Hebbian方法Storkey方法
# 训练模型传入的参数有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
# 训练模型传入的参数有weights和patterns
def train(weights, patterns):
    """
    使用 Storkey 学习规则训练网络
    :param weights: 权重矩阵
    :param patterns: 训练模式的列表
    :return: 训练后的权重矩阵
    """
    for pattern in patterns:
        # 将pattern转化为列向量
        # 由于每个pattern中有n_neurons个元素,所以pattern转化后的列向量有n_neurons行
        pattern = pattern.reshape(-1, 1)
        # n获取pattern向量的行数,n=n_neurons
        n = len(pattern)
       
for i in range(n):
            for j in range(n):
                if i != j:
                    # 让不同的pattern元素彼此相乘
                    term1 = pattern[i] * pattern[j]
                    # 初始值赋值0
                    term2 = 0
                    # 初始值赋值0
                    term3 = 0
                    for k in range(n):
                        if k != i and k != j:
                            # weights矩阵的结构是(n_neurons行,n_neurons列)
                            # term2考虑了第k和第j个pattern元素对i行k列权重的影响
                            term2 += weights[i, k] * pattern[k] * pattern[j]
                            # term3考虑了第k和第j个pattern元素对j行k列权重的影响
                            term3 += weights[j, k] * pattern[k] * pattern[i]
                    # 3个term进行了综合
                    delta_w = term1 - term2 - term3
                    # 确保 delta_w 是标量
                    weights[i, j] += delta_w.item()

    # 确保对角线元素为 0
    np.fill_diagonal(weights, 0)
    # 除以总模数,进行归一化操作
    weights /= len(patterns)
    return weights

Storkey方法相对Hebbian方法,更多地考虑了交叉影响。

【2.3.3】recall()函数
def recall(weights, initial_state, max_iterations=100):
    """
    从初始状态回忆模式
    :param weights: 权重矩阵
    :param initial_state: 初始状态
    :param max_iterations: 最大迭代次数
    :return: 回忆出的模式
    """
    state = initial_state.copy()
    for _ in range(max_iterations):
        new_state = update(weights, state)
        if np.array_equal(new_state, state):
            break
        state = new_state
    return state

recall()函数要求调用update()函数生成新状态,用新状态来覆盖旧状态。

【2.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 Storkey训练效果  

此时的完整代码为:

import numpy as np #引入numpy模块
import matplotlib.pyplot as plt #引入nmatplotlib模块

# 定义初始化函数
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):
    """
    使用 Storkey 学习规则训练网络
    :param weights: 权重矩阵
    :param patterns: 训练模式的列表
    :return: 训练后的权重矩阵
    """
    for pattern in patterns:
        # 将pattern转化为列向量
        # 由于每个pattern中有n_neurons个元素,所以pattern转化后的列向量有n_neurons行
        pattern = pattern.reshape(-1, 1)
        # n获取pattern向量的行数,n=n_neurons
        n = len(pattern)
        for i in range(n):
            for j in range(n):
                if i != j:
                    # 让不同的pattern元素彼此相乘
                    term1 = pattern[i] * pattern[j]
                    # 初始值赋值0
                    term2 = 0
                    # 初始值赋值0
                    term3 = 0
                    for k in range(n):
                        if k != i and k != j:
                            # weights矩阵的结构是(n_neurons行,n_neurons列)
                            # term2考虑了第k和第j个pattern元素对i行k列权重的影响
                            term2 += weights[i, k] * pattern[k] * pattern[j]
                            # term3考虑了第k和第j个pattern元素对j行k列权重的影响
                            term3 += weights[j, k] * pattern[k] * pattern[i]
                    # 3个term进行了综合
                    delta_w = term1 - term2 - term3
                    # 确保 delta_w 是标量
                    weights[i, j] += delta_w.item()
    # 确保对角线元素为 0
    np.fill_diagonal(weights, 0)
    # 除以总模数,进行归一化操作
    weights /= len(patterns)
    return weights

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()

def recall(weights, initial_state, max_iterations=100):
    """
    从初始状态回忆模式
    :param weights: 权重矩阵
    :param initial_state: 初始状态
    :param max_iterations: 最大迭代次数
    :return: 回忆出的模式
    """
    state = initial_state.copy()
    for _ in range(max_iterations):
        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()

【3】分析

Storkey训练方法考察的关联影响更为丰富,但是记得运行效果显示:recall pattern并且和origin pattern保持完全一致。所以,实际的训练过程还未达到最佳效果。

【4】细节说明

Storkey训练方法相对于Hebbian训练方法知识train()函数发生变化。

回执图像时,因为initial_state和patterns[0]一致,所以对比图像origin pattern选择了patterns[0]。

【5】总结

探索了霍普菲尔德神经网络的基本知识,基于python语言,调用Storkey方法对霍普菲尔德神经网络算法进行了初步训练和测试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/983620.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法006——和为S 的两个数

力扣——查找总价格为目标值的两个商品点击跳转 注意题目中的关键信息升序 我们利用双指针&#xff0c;不管 target 是多少&#xff0c;让一个指针指向最小值&#xff0c;让一个指针指向最大 那么&#xff0c;共有三种情况 我们首先遇到的是第二种情况 sum < target left …

【推荐项目】039-酒店预定系统

039-酒店预定系统 介绍 Java ssm 酒店预定管理系统 针对您提出的酒店预定系统&#xff0c;以下是一个基于SSM&#xff08;Spring Spring MVC MyBatis&#xff09;框架与JSP技术的功能结构整理&#xff0c;该系统分为管理端与用户端两大模块&#xff1a; 一、管理端功能 个…

从0开始,手搓Tomcat

一、什么是Tomcat Tomcat 是一款开源的、轻量级的 Web 服务器&#xff0c;它不仅能够提供 HTTP 服务&#xff0c;还能够运行 Java Servlet 和 JavaServer Pages&#xff08;JSP&#xff09;。对于许多开发者来说&#xff0c;理解 Tomcat 的目录结构以及如何在该结构中组织应用…

Ubuntu虚拟机中使用QEMU搭建ARM64环境

Ubuntu虚拟机中使用QEMU搭建ARM64环境 通过本实验学习如何编译一个 ARM64 版本的内核 image&#xff0c;并且在QEMU 上运行起来。 文章目录 Ubuntu虚拟机中使用QEMU搭建ARM64环境一、安装aarch64交叉编译工具二、安装QEMU三、制作根文件系统1、根文件系统简介2、BusyBox构建根…

java 重点知识 — JVM存储模块与类加载器

1 jvm主要模块 方法区 存储了由类加载器从.class文件中解析的类的元数据&#xff08;类型信息、域信息、方法信息&#xff09;及运行时常量池&#xff08;引用符号及字面量&#xff09;。 所有线程共享&#xff1b;内存不要求连续&#xff0c;可扩展&#xff0c;可能发生垃圾回…

Windows 如何开启和使用FTP服务

在Windows 系统开启FTP的服务方式有很多种&#xff0c;最快速的就是使用Windows自身的FTP服务了。 Windows 搭建FTP服务的方式 在Windows 中搭建FTP的方式有很多种&#xff0c;有商用收费的&#xff0c;也有开源免费的&#xff0c;除此之外&#xff0c; Windows本身也内置了F…

ASP.NET Core 6 MVC 文件上传

概述 应用程序中的文件上传是一项功能&#xff0c;用户可以使用该功能将用户本地系统或网络上的文件上传到 Web 应用程序。Web 应用程序将处理该文件&#xff0c;然后根据需要对文件进行一些验证&#xff0c;最后根据要求将该文件存储在系统中配置的用于保存文件的存储中&#…

计算机毕业设计SpringBoot+Vue.js制造装备物联及生产管理ERP系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

yoloV5训练visDrone2019-Det无人机视觉下目标检测

一、visDrone2019数据集详解 visDrone2019数据集是无人机视角下最具挑战性的目标检测基准数据集之一&#xff0c;由天津大学机器学习与数据挖掘实验室联合其他研究机构共同构建。该数据集采集自中国14个不同城市&#xff0c;覆盖复杂城市场景、交通枢纽、密集人群等多种环境。…

Unity开发——CanvasGroup组件介绍和应用

CanvasGroup是Unity中用于控制UI的透明度、交互性和渲染顺序的组件。 一、常用属性的解释 1、alpha&#xff1a;控制UI的透明度 类型&#xff1a;float&#xff0c;0.0 ~1.0&#xff0c; 其中 0.0 完全透明&#xff0c;1.0 完全不透明。 通过调整alpha值可以实现UI的淡入淡…

C语言学习笔记-进阶(7)字符串函数3

1. strstr的使用和模拟实现 char * strstr ( const char * str1, const char * str2); Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1. &#xff08;函数返回字符串str2在字符串str1中第⼀次出现的位置&#x…

如何利用数字校园平台提升职业竞争力

现在我们来探讨如何借助数字校园平台来增强自身的职业竞争力。当今之时代&#xff0c;技术与数据堪称热门领域&#xff0c;略懂编程语言及数据分析&#xff0c;于求职之际&#xff0c;实能增添诸多优势&#xff01; 首先&#xff0c;咱们得说说编程语言。现在很多学校都有提供在…

使用 Arduino 的 WiFi 控制机器人

使用 Arduino 的 WiFi 控制机器人 这次我们将使用 Arduino 和 Blynk 应用程序制作一个 Wi-Fi 控制的机器人。这款基于 Arduino 的机器人可以使用任何支持 Wi-Fi 的 Android 智能手机进行无线控制。 为了演示 Wi-Fi 控制机器人,我们使用了一个名为“Blynk”的 Android 移动应…

动态ip和静态ip适用于哪个场景?有何区别

在数字化浪潮席卷全球的今天&#xff0c;IP地址作为网络世界的“门牌号”&#xff0c;其重要性不言而喻。然而&#xff0c;面对动态IP与静态IP这两种截然不同的IP分配方式&#xff0c;许多用户往往感到困惑&#xff1a;它们究竟有何区别&#xff1f;又分别适用于哪些场景呢&…

求最大公约数【C/C++】

大家好啊&#xff0c;欢迎来到本博客( •̀ ω •́ )✧&#xff0c;我将带领大家详细的了解最大公约数的思想与解法。 一、什么是公约数 公约数&#xff0c;也称为公因数&#xff0c;是指两个或多个整数共有的因数。具体来说&#xff0c;如果一个整数能被两个或多个整数整除&…

conda 配置新环境时package will be install 和 package will be download 的区别

install 和 download 的区别 package will be downloaded下的包&#xff1a;这一类显示的是需要从 conda 仓库或其他指定的源下载的软件包。这些软件包通常是 .tar.bz2、.tar.xz 或 .conda 格式的压缩包。这些包会被下载到本地缓存目录&#xff08;通常是 ~/.conda 或 C:\Users…

【2025小黑课堂】计算机二级WPS精选系列20G内容(可下载:真题+预测卷+软件+选择题)

2025年3月全国计算机等级考试即将于3月29日至31日举行。为了帮助广大考生高效备考&#xff0c;小编特意收集并整理了最新版&#xff08;备考2025年3月&#xff09;的小黑课堂计算机二级WPS 电脑题库软件&#xff0c;助力考生在考试中游刃有余&#xff0c;轻松通关&#xff01; …

C++编写Redis客户端

目录 安装redis-plus-plus库 ​编辑 编译Credis客户端 redis的通用命令使用 get/set exists del keys expire /ttl type string类型核心操作 set和get set带有超时时间 set带有NX string带有XX mset mget getrange和setrange incr和decr list类型核心操作…

①EtherCAT转Modbus485RTU网关多路同步高速采集无需编程串口服务器

EtherCAT转Modbus485RTU网关多路同步高速采集无需编程串口服务器https://item.taobao.com/item.htm?ftt&id798036415719 型号 1路总线EC网关 MS-A2-1011 2路总线EC网关 MS-A2-1021 4路总线EC网关 MS-A2-1041 EtherCAT 串口网关 EtherCAT 转 RS485 技术规格 …

C++ Primer 交换操作

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…