SpikingJelly笔记之IFLIF神经元

news2024/12/23 0:43:57

文章目录

  • 前言
  • 一、脉冲神经元
  • 二、IF神经元
    • 1、神经元模型
    • 2、神经元仿真
  • 三、LIF神经元
    • 1、神经元模型
    • 2、神经元仿真
  • 总结


前言

记录整合发放(integrate-and-fire, IF)神经元与漏电整合发放(leaky integrate-and-fire, LIF)神经元模型,以及在SpikingJelly中的实现方法。


一、脉冲神经元

1、脉冲神经元:只输出脉冲(1/0)的神经元

spikingjelly.activation_based.neuron

2、阈下神经动态方程:神经元根据输入及自身状态更新膜电位

微分方程: d V ( t ) d t = f ( V ( t ) , X ( t ) ) \frac{dV(t)}{dt}=f(V(t),X(t)) dtdV(t)=f(V(t),X(t))

差分近似: V [ t ] = f ( V [ t − 1 ] , X [ t ] ) V[t]=f(V[t-1],X[t]) V[t]=f(V[t1],X[t])

3、计算步骤

X:输入
S:输出(0/1)
H:充电后、放电前的膜电位
V:放电后的膜电位

4、放电方程

def neuronal_fire(self):
        self.spike = self.surrogate_function(self.v - self.v_threshold)

surrogate_function:前向传播时为阶跃函数,膜电位超过阈值时输出为1

Θ ( x ) = { 1 , x ≥ 0 0 , x < 0 \Theta(x) = \left\{\begin{matrix} 1,\quad x\ge 0\\ 0,\quad x<0\\ \end{matrix}\right. Θ(x)={1,x00,x<0

5、重置方程

def neuronal_reset(self):
        if self.v_reset is None:
                self.v = self.v - self.spike * self.v_threshold
        else:
                self.v = (1. - self.spike) * self.v + self.spike * self.v_reset

膜电位达到阈值时神经元发放脉冲,膜电位恢复至静息值
v = { v − v t h r e s h o l d , v r e s e t = N o n e v r e s e t , o t h e r w i s e v = \left\{\begin{matrix} \begin{alignat*}{2} v-v_{threshold},&\quad v_{reset}=None\\ v_{reset},&\quad otherwise \end{alignat*} \end{matrix}\right. v={vvthreshold,vreset,vreset=Noneotherwise

二、IF神经元

1、神经元模型

(1)整合发放(integrate-and-fire)神经元:neuron.IFNode

理想积分器,无输入时膜电位保持恒定

(2)模型方程: I ( t ) = C d V ( t ) d t I(t)=C\frac{dV(t)}{dt} I(t)=CdtdV(t)

I(t):输入电流
V(t):膜电位
C:膜电容

(3)阈下神经动力学方程: H [ t ] = V [ t − 1 ] + X [ t ] H[t]=V[t-1]+X[t] H[t]=V[t1]+X[t]

(4)充电方程

def neuronal_charge(self, x: torch.Tensor):
        self.v = self.v + x

(5)构建IF神经元:layer = neuron.IFNode()

构造参数:
①v_threshold=1.0:阈值电压
②v_reset=0.0:重置电压
③surrogate_function=surrogate.Sigmoid():反向传播梯度替代函数
④step_mode=‘s’:步进模式,单步’s’,多步’m’
⑤store_v_seq=False:是否保存所有时间步的膜电位self.v

2、神经元仿真

(1)构建输入与神经元层,前50步输入为1,后50步输入为0

import torch
from torch import nn
from spikingjelly.activation_based import neuron, monitor, functional
from spikingjelly import visualizing
####################构建输入####################
T = 100 # 时间步数
N = 1 # 样本数目
D = 1 # 输入维度/神经元数目
x_seq1 = torch.ones(50, N, D)
x_seq2 = torch.zeros(50, N, D)
x_seq = torch.cat((x_seq1,x_seq2), 0)
# 构建一层IF神经元
net = nn.Sequential(neuron.IFNode(v_threshold=9.0,
                                  v_reset=0.0,
                                  step_mode='s',
                                  store_v_seq=False))
print(net)

神经元数量N由输入维度(T,N)确定
使用脉冲神经元代替神经网络的激活函数

(2)根据输入按时间步更新神经元膜电位与输出
单步模式(默认):逐步传播,深度优先遍历,内存占用小,适用于ANN2SNN
需要手动for循环按时间步计算

####################记录神经元状态####################
v_list = [] # 膜电位
s_list = [] # 神经元输出
####################单步模式:逐步传播####################
with torch.no_grad(): # 计算时关闭自动求导
    for i in range(T):
        y = net(x_seq[i])
        v_list.append(net[0].v)
        s_list.append(y)
functional.reset_net(net) # 重置神经元状态
####################可视化膜电位与输出####################
v_list = torch.cat(v_list).flatten()
s_list = torch.cat(s_list).flatten()
visualizing.plot_one_neuron_v_s(v_list.numpy(),
                                s_list.numpy(),
                                v_threshold=net[0].v_threshold,
                                v_reset=net[0].v_reset,
                                figsize=(12, 8),
                                dpi=100)

脉冲神经元是有状态的(self.v)
输入一批样本后需要进行复位:functional.reset_net(net)

(3)网络结构

Sequential(
  (0): IFNode(
    v_threshold=9.0, v_reset=0.0, detach_reset=False, step_mode=s, backend=torch
    (surrogate_function): Sigmoid(alpha=4.0, spiking=True)
  )
)

4、各时间步神经元的膜电位与输出

三、LIF神经元

1、神经元模型

(1)漏电整合发放(leaky integrate-and-fire)神经元:neuron.LIFNode

引入漏电项,无输入时膜电位恢复至静息电位,模拟离子扩散

(2)模型方程:
I ( t ) − g ( V ( t ) − E ) = C d V ( t ) d t I(t)-g(V(t)-E)=C\frac{dV(t)}{dt} I(t)g(V(t)E)=CdtdV(t)

I(t):输入电流
V(t):膜电位
C:膜电容
g:泄漏电导
E:静息电位

(3)阈下神经动力学方程:

H [ t ] = { V [ t − 1 ] + X [ t ] − 1 τ ( V [ t − 1 ] − V r e s e t ) , d e c a y _ i n p u t = F a l s e V [ t − 1 ] + 1 τ ( X [ t ] − ( V [ t − 1 ] − V r e s e t ) ) , d e c a y _ i n p u t = T r u e H[t] = \left\{\begin{matrix} \begin{alignat*}{2} V[t-1]+X[t]-\frac{1}{\tau}(V[t-1]-V_{reset}),&\quad decay\_input=False\\ V[t-1]+\frac{1}{\tau}(X[t]-(V[t-1]-V_{reset})),&\quad decay\_input=True \end{alignat*} \end{matrix}\right. H[t]= V[t1]+X[t]τ1(V[t1]Vreset),V[t1]+τ1(X[t](V[t1]Vreset)),decay_input=Falsedecay_input=True

decay_input为False时,膜电位V的衰减由 1 τ ( V − V r e s e t ) \frac{1}{\tau}(V-V_{reset}) τ1(VVreset)控制
decay_input为True时,输入X[t]参与衰减,乘以系数 1 τ \frac{1}{\tau} τ1

(4)充电方程

def neuronal_charge(self, x: torch.Tensor):
    if self.decay_input:
        if self.v_reset is None or self.v_reset == 0.:
            self.v = self.v + (x - self.v) / self.tau
        else:
            self.v = self.v + (x - (self.v - self.v_reset) / self.tau
    else:
        if self.v_reset is None or self.v_reset == 0.:
            self.v = self.v + x - self.v / self.tau
        else:
            self.v = self.v + x - (self.v - self.v_reset) / self.tau

(5)构建LIF神经元:layer = neuron.LIFNode()

构造参数:
①tau=2.0:膜电位时间常数
②decay_input=True:输入是否参与衰减
③v_threshold=1.0:阈值电压
④v_reset=0.0:重置电压
⑤surrogate_function=surrogate.Sigmoid():梯度替代函数
⑥step_mode=‘s’:步进模式
⑦store_v_seq=False:是否保存所有时间步的膜电位self.v

2、神经元仿真

(1)构建输入与神经元层,前50步输入为1,后50步输入为0

####################构建输入####################
T = 100 # 时间步数
N = 1 # 样本数目
D = 1 # 输入维度/神经元数目
x_seq1 = torch.ones(50, N, D)
x_seq2 = torch.zeros(50, N, D)
x_seq = torch.cat((x_seq1,x_seq2), 0)
# 构建一层LIF神经元
net = nn.Sequential(neuron.LIFNode(tau=10.0,
                                    decay_input=True,
                                    v_threshold=0.9,
                                    v_reset=0.0,
                                    step_mode='m',
                                    store_v_seq=True))
print(net)

(2)根据输入按时间步更新神经元膜电位与输出
多步模式:逐层传播,广度优先遍历,并行速度更快,适用于梯度替代法
直接计算,不需要手动写for循环

####################监视器记录神经元状态####################
# 记录膜电位
monitor_v = monitor.AttributeMonitor('v_seq',
                                      pre_forward=False,
                                      net=net,
                                      instance=neuron.LIFNode)
# 记录输出
monitor_o = monitor.OutputMonitor(net=net,
                                  instance=neuron.LIFNode)
####################多步模式:逐层传播####################
with torch.no_grad(): # 计算时关闭自动求导
    net(x_seq)
functional.reset_net(net) # 重置神经元状态
####################可视化膜电位与输出####################
v_list = monitor_v.records[0].flatten()
s_list = monitor_o.records[0].flatten()
visualizing.plot_one_neuron_v_s(v_list.numpy(),
                                s_list.numpy(),
                                v_threshold=net[0].v_threshold,
                                v_reset=net[0].v_reset,
                                figsize=(12, 8),
                                dpi=100)

使用monitor监视器记录神经元输出与成员变量(膜电位)

(3)网络结构

Sequential(
  (0): LIFNode(
    v_threshold=0.9, v_reset=0.0, detach_reset=False, step_mode=m, backend=torch, tau=10.0
    (surrogate_function): Sigmoid(alpha=4.0, spiking=True)
  )
)

(4)各时间步神经元的膜电位与输出

输入为0时,膜电位自发泄漏

(5)当时间常数tau很大时,LIF神经元退化为IF神经元

net = nn.Sequential(neuron.LIFNode(tau=1.0e8,
                                    decay_input=False,
                                    v_threshold=9.0,
                                    v_reset=0.0,
                                    step_mode='m',
                                    store_v_seq=True))
Sequential(
  (0): LIFNode(
    v_threshold=9.0, v_reset=0.0, detach_reset=False, step_mode=m, backend=torch, tau=100000000.0
    (surrogate_function): Sigmoid(alpha=4.0, spiking=True)
  )
)


总结

不同神经元的主要差别在于阈下神经动力学方程(充电方程),而放电方程与重置方程相似;
IF神经元具有记忆效应,在无输入时,神经元膜电位会一直维持在当前状态;
LIF神经元引入漏电流项,在无输入时,膜电位会恢复至静息电位;
通过monitor和visualizing可以方便地监控和绘制神经元的膜电位与输出。

参考:
[1] SpikingJelly的文档——神经元
[2] 脉冲神经网络:模型、学习算法与应用
[3] 脉冲神经网络研究进展综述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mybatis----动态Sql

1.if标签 通过if标签构建动态条件&#xff0c;通过其test属性的true或false来判断该添加语句是否执行。 mapper接口 public interface AccountMapper {List<Account> selectAllByCondition(Account account); } 映射文件 <select id"selectAllByCondition&q…

《文苑》文学艺术文化期刊投稿邮箱投稿方式

《文苑》杂志是国家新闻出版总署批准的正规期刊&#xff0c;本刊致力于中华优秀传统文化、文化旅游、文学艺术、哲学社会科学等方面的理论和实践研究&#xff0c;集理论性、艺术性、指导性于一体&#xff0c;是广大文化、哲学、社会科学工作者交流科研成果、传递学术思想的重要…

(蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)

能够表示为某个整数的平方的数字称为“平方数 虽然无法立即说出某个数是平方数&#xff0c;但经常可以断定某个数不是平方数。因为平方数的末位只可能是:0,1,4,5,6,9 这 6 个数字中的某个。所以&#xff0c;4325435332 必然不是平方数。 如果给你一个 2 位或 2 位以上的数字&am…

【Linux】基本指令收尾

文章目录 日期查找打包压缩系统信息Linux和Windows互传文件 日期 这篇是基本指令的收尾了&#xff0c;还有几个基本指令我们需要说一下 首先是Date&#xff0c;它是用来显示时间和日期 直接输入date的话显示是有点不好看的&#xff0c;所以我们可以根据自己的喜欢加上分隔符&…

MATLAB解决考研数学一题型(上)

闲来无事&#xff0c;情感问题和考研结束后的戒断反应比较严重&#xff0c;最近没有什么写博文的动力&#xff0c;抽空来整理一下考研初试前一直想做的工作——整理一下MATLAB解决数学一各题型的命令~ 本贴的目录遵循同济版的高数目录~ 目录 一.函数与极限 1.计算双侧极限 2…

如何理解 GO 语言的接口 - 鸭子模型

个人认为&#xff0c;要理解 Go 的接口&#xff0c;一定先了解下鸭子模型。 鸭子模型 那什么鸭子模型&#xff1f; 鸭子模型的解释&#xff0c;通常会用了一个非常有趣的例子&#xff0c;一个东西究竟是不是鸭子&#xff0c;取决于它的能力。游泳起来像鸭子、叫起来也像鸭子…

Kafka-服务端-网络层

Reactor模式 Kafka网络层采用的是Reactor模式&#xff0c;是一种基于事件驱动的模式。熟悉Java编程应该了解JavaNIO提供了实现Reactor模式的API。常见的单线程Java NIO的编程模式如图所示。 为了满足高并发的需求&#xff0c;也为了充分利用服务器的资源&#xff0c;服务端需要…

Wimdows如何修改自己权限不够的文件

使用管理员身份运行cmd cd 文件目录 cd C:\Windows\System32\drivers\etc 打开文件 notepad 文件名 进行修改&#xff0c;保存就能成功&#xff01;

基于springboot+vue的教师工作量管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…

部署Filebeat+Kafka+ELK 集群

目录 Kafka 概述 为什么需要消息队列&#xff08;MQ&#xff09; 使用消息队列的好处 消息队列的两种模式 Kafka 定义 Kafka 简介 Kafka 的特性 Kafka 系统架构 在zookeeper集群的基础上部署 kafka 集群 部署zookeeper集群 部署kafka集群 下载安装包 安装 Kafka Ka…

Leetcode—22.括号生成【中等】

2023每日刷题&#xff08;七十九&#xff09; Leetcode—22.括号生成 算法思想 实现代码 class Solution { public:vector<string> generateParenthesis(int n) {vector<string> ans;int m n * 2;string path(m, 0);function<void(int, int)> dfs [&…

LabVIEW电火花线切割放电点位置

介绍了一个电火花线切割放电点位置分布评价系统&#xff0c;特别是在系统组成、硬件选择和LabVIEW软件应用方面。 本系统由两个主要部分组成&#xff1a;硬件和软件。硬件部分包括电流传感器、高速数据采集卡、开关电源、电阻和导线。软件部分则由LabVIEW编程环境构成&#xf…

数学建模学习笔记||层次分析法

评价类问题 解决评价类问题首先需要想到一下三个问题 我们评价的目标是什么我们为了达到这个目标有哪几种可行方案评价的准则或者说指标是什么 对于以上三个问题&#xff0c;我们可以根据题目中的背景材料&#xff0c;常识以及网上收集到的参考资料进行结合&#xff0c;从而筛…

java多线程(线程池)

1、创建一个可缓存线程池&#xff0c;如果线程池长度超过处理需要&#xff0c;可灵活回收空闲线程&#xff0c;若无可回收&#xff0c;则新建线程。 public static void main(String[] args) {ExecutorService cachedThreadPool Executors.newCachedThreadPool();for (int i …

基于Altium Designer 10设计双层印刷电路板的详细步骤

基于Altium Designer 10设计双层印刷电路板的详细步骤 一、基于Altium Designer 10设计双层印刷电路板总纲二、、基于Altium Designer 10设计双层印刷电路原理图三、制作集成库(包括原理图、PCB封装库、PCB 3D库)1、新建集成库2、新建原理图库3、绘制原理图库(1)、手工绘制…

02_Collection

文章目录 集合Java的集合类 Collectioniterator方法Collection的遍历 集合 在Java中&#xff0c;指的就是存放数据的容器&#xff0c;是一个载体&#xff0c;可以一次容纳多个对象。 解决Bug的两种方法&#xff1a; 打印 System.out.println();log.info(); debug 检查数据 …

CentOs7 安装Mysql(5.7和8.0版本)密码修改跳过 超详细教程

CSDN 成就一亿技术人&#xff01; 今天出一期Centos下安装Mysql&#xff08;详细教程&#xff09;包括数据库密码跳过修改 CSDN 成就一亿技术人&#xff01; 目录 1.获取安装包 2.安装程序 安装下载的rpm包 查看安装包 修改5.7版本&#xff08;重要&#xff09; 安装M…

【RHCE服务搭建实验】之DNS

目录 一、DNS简介二、安装DNS 一、DNS简介 域名系统&#xff08;DNS&#xff09;是一个分层的分布式数据库。它存储用于将Internet主机名映射到IP地址&#xff08;反之亦然&#xff09;的信息、邮件路由信息以及Internet应用程序使用的其他数据。 客户端通过调用解析器库在DNS…

股权众筹模式介绍(上)

众筹&#xff0c;是指个人或小企业通过互联网向大众筹集资金的一种项目融资方式&#xff0c;根据众筹的筹集目的和回报方式&#xff0c;可以分为债权众筹、回报众筹、股权众筹和捐赠众筹四大类。本文重点介绍我国股权众筹的几种模式。 一、众筹当事方 一个众筹项目&#xff0…

【ARMv8M Cortex-M33 系列 7 -- RA4M2 移植 RT-Thread 问题总结】

请阅读【嵌入式开发学习必备专栏 】 文章目录 问题小结栈未对齐 经过几天的调试&#xff0c;成功将rt-thead 移植到 RA4M2&#xff08;Cortex-M33 核&#xff09;上&#xff0c;thread 和 shell 命令已经都成功支持。 问题小结 在完成 rt-thread 代码 Makefile 编译系统搭建…