当前位置: 首页 > news >正文

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

【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处于对角线上的元素都为0np.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):breakstate = new_statereturn 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返回0new_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处于对角线上的元素都为0np.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返回0new_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):breakstate = new_statereturn 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矩阵的训练过程,有一个归一化的操作。

weights /= len(patterns)

【5】总结

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

相关文章:

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

【1】引言 前序学习进程中,除了对基本的神经网络知识进行了学习,还掌握了SOM神经网络原理,文章链接包括且不限于: 神经网络|(十一)|神经元和神经网络-CSDN博客 神经网络|(十二)|常见激活函数-CSDN博客 神经网络|(十三)|SOM神经…...

【JAVA架构师成长之路】【Redis】第13集:Redis缓存击穿原理、规避、解决方案

30分钟自学教程:Redis缓存击穿原理与解决方案 目标 理解缓存击穿的定义及核心原因。掌握互斥锁、逻辑过期时间等预防技术。能够通过代码实现高并发场景下的缓存保护。学会熔断降级、热点探测等应急方案。 教程内容 0~2分钟:缓存击穿的定义与典型场景 …...

preloaded-classes裁剪

系统预加载了哪些class类?system/etc/preloaded-classes 修改源代码? frameworks\base\config\preloaded-classes 默认位置,如果改了不生效,可能有其它模块的mk文件指定了preloaded-classes覆盖了framework模块,例如…...

爬虫案例五多进程与多线程爬取斗图网

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、多进程与多线程爬取斗图网总结 前言 提示:这里可以添加本文要记录的大概内容: 爬取斗图网 提示:以下是本篇文章正文内…...

Redis的CPU高达90%时如何处理

Redis的CPU高达90%时如何处理 1. 分析和优化2. 扩展和分片3. 缓存策略调整4. 资源提升5. 负载均衡6. 进程调整7. 代码层面改进8. 其他 当Redis的CPU使用率高达90%时,说明Redis服务器可能处于过载状态,这可能会导致响应时间变长甚至服务中断。要处理这种…...

计算机视觉之dlib人脸关键点绘制及微笑测试

dlib人脸关键点绘制及微笑测试 目录 dlib人脸关键点绘制及微笑测试1 dlib人脸关键点1.1 dlib1.2 人脸关键点检测1.3 检测模型1.4 凸包1.5 笑容检测1.6 函数 2 人脸检测代码2.1 关键点绘制2.2 关键点连线2.3 微笑检测 1 dlib人脸关键点 1.1 dlib dlib 是一个强大的机器学习库&a…...

FPGA时序约束的几种方法

一,时钟约束 时钟约束是最基本的一个约束,因为FPGA工具是不知道你要跑多高的频率的,你必要要告诉工具你要跑的时钟频率。时钟约束也就是经常看到的Fmax,因为Fmax是针对“最差劲路径”,也就是说,如果该“最差劲路径”得到好成绩,那些不是最差劲的路径的成绩当然比…...

【0013】Python数据类型-列表类型详解

如果你觉得我的文章写的不错,请关注我哟,请点赞、评论,收藏此文章,谢谢! 本文内容体系结构如下: Python列表,作为编程中的基础数据结构,扮演着至关重要的角色。它不仅能够存储一系…...

10.RabbitMQ集群

十、集群与高可用 RabbitMQ 的集群分两种模式,一种是默认集群模式,一种是镜像集群模式; 在RabbitMQ集群中所有的节点(一个节点就是一个RabbitMQ的broker服务器) 被归为两类:一类是磁盘节点,一类是内存节点; 磁盘节点会把集群的所有信息(比如交换机、绑…...

Web网页开发——水果忍者

1.介绍 复刻经典小游戏——水果忍者 2.预览 3.代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title&…...

信息安全访问控制、抗攻击技术、安全体系和评估(高软42)

系列文章目录 信息安全访问控制、抗攻击技术、安全体系和评估 文章目录 系列文章目录前言一、信息安全技术1.访问控制2.抗攻击技术 二、欺骗技术1.ARP欺骗2.DNS欺骗3.IP欺骗 三、抗攻击技术1.端口扫描2.强化TCP/IP堆栈 四、保证体系和评估1.保证体系2.安全风险管理 五、真题在…...

【算法】009、单双链表反转

【算法】009、单双链表反转 文章目录 一、单链表反转1.1 实现思路1.2 多语言解法 二、双链表反转2.1 实现思路2.2 多语言解法 一、单链表反转 1.1 实现思路 维护 pre 变量。 从前向后遍历 head&#xff0c;首先记录 next head.next&#xff0c;其次反转指针使 head.next pr…...

物联网设备接入系统后如何查看硬件实时数据?

要在软件中实时查看硬件设备的信息&#xff0c;通常需要结合前后端技术来实现。以下是设计思路和实现步骤&#xff1a; 1. 系统架构设计 实时查看硬件设备信息的系统通常采用以下架构&#xff1a; 数据采集层: 硬件设备通过传感器采集数据&#xff0c;发送到InfluxDB。数据存…...

【Linux系统编程】初识系统编程

目录 一、什么是系统编程1. 系统编程的定义2. 系统编程的特点3. 系统编程的应用领域4. 系统编程的核心概念5. 系统编程的工具和技术 二、操作系统四大基本功能1. 进程管理&#xff08;Process Management&#xff09;2. 内存管理&#xff08;Memory Management&#xff09;3. 文…...

解决stylelint对deep报错

报错如图 在.stylelintrc.json的rules中配置 "selector-pseudo-class-no-unknown": [true,{"ignorePseudoClasses": ["deep"]} ]...

React基础之useInperativehandlle

通过ref调用子组件内部的focus方法来实现聚焦 与forwardRef类似&#xff0c;但是forwardRef是通过暴露整个Ref来实现&#xff0c;而useInperativehandle是通过对外暴露一个方法来实现的 import { forwardRef, useImperativeHandle, useRef, useState } from "react";…...

使用joblib 多线程/多进程

文章目录 1. Joblib 并行计算的两种模式多进程(Multiprocessing,适用于 CPU 密集型任务)多线程(Multithreading,适用于 I/O 密集型任务)2. Joblib 的基本用法3. Joblib 多进程示例(适用于 CPU 密集型任务)示例:计算平方4. Joblib 多线程示例(适用于 I/O 密集型任务)…...

⭐算法OJ⭐N-皇后问题 II【回溯剪枝】(C++实现)N-Queens II

⭐算法OJ⭐N-皇后问题【回溯剪枝】&#xff08;C实现&#xff09;N-Queens 问题描述 The n-queens puzzle is the problem of placing n n n queens on an n n n \times n nn chessboard such that no two queens attack each other. Given an integer n, return the num…...

【数据结构初阶】---堆的实现、堆排序以及文件中的TopK问题

1.树的概念及结构 1.1树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。 有一个特殊的结点&…...

ubuntu20系统下conda虚拟环境下安装文件存储位置

在 Conda 虚拟环境中执行 pip install 安装软件后&#xff0c;安装的文件会存储在该虚拟环境专属的 site-packages 目录中。具体路径取决于你激活的 Conda 环境路径。以下是定位步骤&#xff1a; 1. 确认 Conda 虚拟环境的安装路径 查看所有环境&#xff1a; conda info --env…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

wpf在image控件上快速显示内存图像

wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像&#xff08;比如分辨率3000*3000的图像&#xff09;的办法&#xff0c;尤其是想把内存中的裸数据&#xff08;只有图像的数据&#xff0c;不包…...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...