脉冲神经元模型#

作者: Liuhui

与脑仿真中的神经元模型不同的是,用于脉冲神经网络(SNN)中神经元模型有以下区别:

在SNN中,神经元之间的信息传递通过离散的脉冲信号进行,而不是传统的连续值。

在脑仿真中,神经元模型则是一个更为广泛的概念,它涵盖了多种用于模拟大脑神经元行为和交互的模型。这些模型可以基于不同的生物学原理、数学公式或计算方法,以更精确地描述和预测神经元的动态行为。脑仿真中的神经元模型不仅考虑了神经元的电生理特性,还涉及了神经元之间的连接关系、突触传递、学习机制等多个方面。

因此,SNN与脑仿真中的神经元模型的主要区别体现在以下几个方面:

  1. 信息传递方式:SNN主要依赖于离散的脉冲信号进行信息传递,而脑仿真中的神经元模型可能使用连续值或其他形式的信号。

  2. 模型复杂度:SNN通常关注于神经元的脉冲发放和传递机制,相对较为简化。而脑仿真中的神经元模型可能涉及更复杂的电生理特性和交互方式,以更准确地模拟大脑的功能。

  3. 应用范围:SNN主要用于模拟和解释大脑中的脉冲编码和信息处理机制,以及开发基于脉冲计算的智能系统。而脑仿真中的神经元模型则更广泛地应用于神经科学、认知科学、生物医学工程等领域,用于研究和理解大脑的工作原理、疾病机制以及开发新的治疗方法和技术。

但是随着神经科学和计算科学的不断发展,SNN和脑仿真中的神经元模型都在不断完善和更新,以更好地模拟和解释大脑的功能和机制。因此,这两者的界限也在逐渐模糊,有些模型可以同时融合SNN和脑仿真的思想和方法。详见 混合网络 章节。

在NeurAI框架中,脉冲神经元模型的构建是基于基类 neurai.nn.neuron.neuron.Neuron 。为了更具体地定义脉冲神经元的行为,从这个基类派生出了另一个基类 neurai.nn.neuron.neuron.StepwiseNeuron。 StepwiseNeuron 基类具备了不同时间步长模式下的更新计算能力,它支持单步更新和多步更新机制。例如,SNNIF(Spiking Neural Network Integrate-and-Fire)和SNNLIF(Spiking Neural Network Leaky Integrate-and-Fire) 等神经元模型就是继承自 StepwiseNeuron 基类。而那些不需要这种时间步长更新模式的神经元模型,则直接继承自 Neuron 基类。neurai.nn.neuron.neuron.Neuron 基类的参数说明参见 神经元模型 部分。

neurai.nn.neuron.neuron.StepwiseNeuron 基类参数说明如下:

  • V_reset,float类型,发放脉冲后的重置电位,默认为0;

  • V_th,float类型,表示神经元的电压阈值,默认为1;

  • Record_v,bool类型,是否记录模电压值。 True 时,将输出脉冲值和模电压值,否则只输出脉冲值;

  • surrogate_grad_fn,Callable类型,用于计算heaviside函数反向传播的代理梯度函数,默认值为surrogate_grad.Sigmoid();

  • step_modeneurai.const.train.StepMode 类型, 包含单步模式(神经元只接受一个时间步的输入数据)和 多步模式(神经元接受包含多个时间步的输入数据),默认为多步模式;

  • reset_type Union[None, neurai.const.reset_type.ResetType]类型,发放脉冲后的模电压重置方式,其值包括 neurai.const.reset_type.ResetType.HARDneurai.const.reset_type.ResetType.SOFT,默认为 HARD ;

  • time_recurrent,bool类型,表明神经元是否是用于SRNN结构,当在SRNN模型中使用神经元时,该值会自动设置为 True ,该参数无需用户指定,默认值为 False

  • before_reset_mem,bool类型,是否输出重置后的膜电压值;

  • param_dtype,Any类型,传递给参数初始化方法的dtype。默认值为 jnp.float32

SNNIF#

IF模型(Integrate-and-Fire模型)是最简单的模型之一,它基于神经元膜电位的积分,并在膜电位达到阈值时产生一个脉冲。IF模型假设了简单的积分和放电的过程,忽略了神经元的许多生物细节。 使用方式如下:

首先,导入需要的模块:

from neurai.nn.neuron import SNNIF
import neurai.const as nc

创建一个SNNIF模型:

if_neuron = SNNIF(step_mode=nc.single, record_v=True)

IF模型的几个关键参数描述:

  • record_v:是否记录模电压值。True 时,将输出脉冲值和模电压值,否则只输出脉冲值。

  • step_mode:神经元更新步进模式,分为单步 nc.single 和 多步 nc.multi 两种模式,单步模式指神经元只接受一个时间步的输入数据;多步模式指神经元接受包含多个时间步的输入数据。

SNNLIF#

LIF(Leaky Integrate-and-Fire)模型是生物神经元行为的简化数学模型,它用于描述神经元的电活动和兴奋性特性。LIF模型的基本思想是将神经元的电位视为一个电容器的电压,该电容器通过接收来自其他神经元的电流输入来充电,同时以一定的速率自行放电, 当电位超过某个阈值时,神经元将产生一个脉冲,然后电位被重置为一个初始值,该过程模拟了神经元的放电行为。

创建一个SNNLIF模型:

from neurai.nn.neuron import SNNLIF
lif_neuron = SNNLIF(step_mode=nc.single, record_v=True)

LIF模型的几个关键参数描述:

  • record_v:是否记录模电压值。True 时,将输出脉冲值和模电压值,否则只输出脉冲值。

  • step_mode:神经元更新步进模式,分为单步 nc.single 和 多步 nc.multi 两种模式,单步模式指神经元只接受一个时间步的输入数据;多步模式指神经元接受包含多个时间步的输入数据。

SNNALIF#

Adaptive LIF是LIF模型的扩展,详见论文Accurate and efficient time-domain classification with adaptive spiking recurrent neural networks(here)。

from neurai.nn.neuron import SNNALIF
alif_neuron = SNNALIF(step_mode=nc.single, tau_shape=(512,))

ALIF模型的几个关键参数描述:

  • tau_shape:参数 tau_mtau_adp 的形状。

  • v_th0:神经阈值基准值。

  • Eta:变量term of threshold的初始值,默认为1.0。

  • beta:自适应系数的可变项阈值,默认为1.8。

  • time_step:采样时间,默认为1.0。

  • tau_m_initializer:膜衰减时间常数初始化函数,默认NormalIniter(20.,5)。

  • tau_adp_initializer:阈值衰减时间常数初始化函数,默认为NormalIniter(150,10)。

SNNEIF#

Exponential integrate-and-fire(EIF)模型与IF模型类似,EIF模型也基于神经元膜电位的积分,但引入了指数型的膜电位动力学。EIF模型相比传统的IF模型更加复杂,但也更贴近生物神经元的实际情况。它能够更好地捕捉到神经元在不同外部输入条件下的动态行为。

from neurai.nn.neuron import SNNEIF
eif_neuron = SNNEIF(step_mode=nc.single)

EIF模型的几个关键参数描述:

  • delta_T:脉冲斜率因子,这个参数与I-V曲线在阈值V_th处的曲率成反比,衡量的是脉冲起始的锐度,默认为1。

  • v_T:软触发阈值,默认为0.8。

SNNQIF#

Quadratic integrate-and-fire (QIF) 模型是一种生物物理学的计算模型,用于模拟神经元的行为。该模型在传统的线性积分-发放(Integrate-and-Fire, IF)模型的基础上进行了改进,通过引入一个二次项来更准确地描述神经元膜电位的变化。

在标准的IF模型中,膜电位随时间线性增长,直到达到一个阈值,此时神经元发放一个脉冲(或称为“动作电位”),然后膜电位被重置到一个较低的值。然而,这种线性增长可能无法充分捕捉到神经元在脉冲生成过程中膜电位的复杂动态。

QIF模型通过在膜电位方程中加入一个二次项来解决这个问题。这个二次项允许膜电位的变化率不仅依赖于当前的膜电位,还依赖于膜电位的平方。这样的非线性特性使得模型能够更真实地模拟神经元在接近发放阈值时的行为,以及在不同刺激条件下的膜电位动态。

from neurai.nn.neuron import SNNQIF
qif_neuron = SNNQIF(step_mode=nc.single)

QIF模型的几个关键参数描述:

  • a0:斜率因子,默认为1。

  • v_c:触发阈值,默认为0.8。

SNNKLIF#

k-based leaky Integrate-and-Fire(KLIF) 模型是一种生物物理学的计算模型,用于模拟神经元的行为。该模型在传统的线性积分-发放(Integrate-and-Fire, IF)模型的基础上进行了改进。

KLIF 在训练过程中添加了一个可学习的缩放因子,以动态更新替代梯度曲线的斜率和宽度,并结合了 ReLU 激活函数,选择性地将膜电位传递给尖峰发射和复位。 .. code:: python

from neurai.nn.neuron import SNNKLIF kif_neuron = SNNKLIF(step_mode=nc.single)

KLIF模型的几个关键参数描述:

  • decay_input:输入是否也会参与衰减,默认为True。

SNNParamtricLIF#

Parametric LIF模型,详见论文(Incorporating Learnable Membrane Time Constant to Enhance Learning of Spiking Neural Networks)。

from neurai.nn.neuron import SNNParamtricLIF
paramtriclif_neuron = SNNParamtricLIF(step_mode=nc.single)

ParamtricLIF模型的几个关键参数描述:

  • init_tau:膜时间常数的初始值,默认为10。

SNNSRM#

SRM(Spike Response Model)脉冲响应神经元模型主要用于描述神经元如何响应来自其他神经元的脉冲输入,考虑了脉冲响应函数,SRM模型使用两个核函数来更新神经元状态:响应核 res_kernel 和不应期核 ref_kernel

在SRM模型中,res_kernel 负责计算神经元响应输入脉冲时的膜电位。它在一段时间内对输入脉冲进行卷积以更新膜电位。该函数考虑了输入脉冲的时间和幅度,以确定何时生成响应脉冲。响应核函数的形状取决于时间常数和时间窗口的长度,并在 response_kernel 方法中实现。

另一方面,ref_kernel 用于模拟神经元的绝对不应期,即神经元在发出脉冲后一段时间内无法产生新的脉冲。这两个核函数在计算过程中相互作用,通过更新膜电位和检测阈值来产生输出脉冲。

SRM模型使用方法,如:

from neurai.nn.neuron import SNNSRM
import neurai.const as nc
srm_neuron = SNNSRM(computation_type=nc.for_loop)

参数:

  • computation_type:计算类型。不同的计算类型( nc.for_loopnc.cuda )用于神经元膜电位和脉冲发放的优化和加速计算。

  1. 膜电位(PSP,突触后电位)计算过程:

  • _psp_for_loop:使用for循环计算神经元的膜电位。它在不同的时间步上进行迭代,并且在每个时间步上,根据脉冲输入和响应核权重计算膜电位的变化。它在内部使用嵌套循环来计算不同时间步和不同核权重上的加权总和。这个实现方法很直观,但在计算大规模数据时可能较慢。经过测试,发现当以 JIT (即时编译)模式使用该方法时,初始编译较慢,但随后的调用会有显著的速度改善。

  • _psp_cuda:使用CUDA对psp计算膜电位部分进行优化加速,它充分利用了GPU的并行计算能力来加速计算过程。这种实现显著提高了计算速度,特别适用于处理大规模数据。(在Slayer类中支持)

  1. 脉冲发放计算过程:

  • _spike_for_loop:使用for循环计算神经元的脉冲发放。它在不同的时间步上进行迭代,并且在每个时间步上,根据膜电位是否超过阈值来确定是否发放脉冲,并更新膜电位。它在内部使用嵌套循环来计算不同时间步上的脉冲输出和膜电位更新。这种实现方法直观易懂,但在计算大规模数据时可能较慢。

  • _spike_cuda:是一种利用CUDA技术在GPU上执行脉冲发放过程的计算方法。通过CUDA的并行处理能力,这种方法能够显著提高计算效率,尤其适用于处理大规模数据。它是一个可以被继承并在子类中实现的功能,例如在Slayer类中。这种实现方式使得Slayer类能够利用GPU的强大性能,从而优化脉冲神经网络的模拟过程。

以上是SNNSRM类中膜电位计算和脉冲发放的主要过程。根据所选择的计算类型( for_loopcuda ),可以选择适当的计算方式来提高计算效率。

除了前面提到的神经元模型, neurai 收录了性能良好的开源SNN算法模型,将其集成为网络层,它可以直接用于构建SNN模型。

Slayer#

layer.slayer 是Slayer(Spike Layer Error Reassignment) 算法的实现,该模型是一种针对SNN的误差反向传播的通用方法。Slayer通过SNN层将误差信度反向分配,就像传统的反向传播算法通过ANN的层将误差反向分配一样。

在Slayer中,脉冲神经元的当前状态取决于其先前状态,而先前状态又取决于其输入神经元的先前状态。这种时间依赖性允许误差信号在Slayer中及时传播和分配。

通过考虑神经元的时间状态以及它们对先前状态的依赖关系,Slayer允许误差信号在整个网络中得以高效分配和传播。这使得在时间域内能够有效地进行反向传播和误差分配,使Slayer 非常适用于涉及时间依赖数据的任务。

Slayer 能够处理和学习来自时间相关的时序数据,因此它适用于各种任务,例如时间序列预测、语音识别和机器人控制。Slayer算法的出处:here.

layer.slayer 支持 for_loopcuda 两种计算方式,当使用 cuda 计算方式时,需要一个GPU环境,并且需要安装 neurailib 。以下是安装步骤:

cd neurai/lib
pip install .

请确保你的系统已正确配置,并具备支持GPU计算所需的驱动程序和CUDA库。

安装成功后,即可在Slayer类中使用 cuda 计算方式。

from neurai.nn.layer.slayer import Slayer
slayer_neuron = Slayer(V_th=10.0, scale_rho=1, tau_rho=1, computation_type=nc.cuda)

Exodus#

layer.exodus 模块对应于Exodus(EXact computation of Derivatives as Update to SLAYER)算法的实现,这是Slayer的改进版本。Exodus算法解决了Slayer中存在的数值不稳定性和计算成本问题。

Exodus在梯度计算中引入了神经元的重置机制,以确保在训练期间获得准确的梯度并保持稳定性。它利用了隐函数定理来计算精确的梯度,消除了梯度的临时缩放,从而显著降低了训练计算成本。

如需了解有关Exodus的更详细信息,你可以参考《EXODUS: Stable and Efficient Training of Spiking Neural Networks(here)。你还可以在GitHub仓库上找到相关的代码实现:synsense/sinabs-exodus.

要使用Exodus算法,请确保安装了 neurailib,它提供了所需的功能和依赖项。这将确保你可以正确利用Exodus算法来构建和训练脉冲神经网络模型。根据之前提到的步骤来安装neurailib。Exodus模型的应用实例如下:

from neurai.nn.layer.exodus import Exodus
exodus_neuron = Exodus(V_rest=0., V_reset=0., V_th=1.0, record_v=False)

SRNN#

SRNN(Spiking Recurrent Neural Network,脉冲循环神经网络)是一种基于脉冲神经元的循环神经网络结构,用于处理时序性任务。 脉冲神经网络模型采用与生物神经系统相似的脉冲传递方式,其中神经元通过脉冲来进行信息传递。 SRNN模型是文章《EFFECTIVE AND EFFICIENT COMPUTATION WITH MULTIPLE-TIMESCALE SPIKING RECURRENT NEURAL NETWORKS (here) 和《Accurate and efficient time-domain classification with adaptive spiking recurrent neural networks》 (here) 中提到的脉冲网络模型,文中所提的SRNN结构如下图所示:

具有两个循环层的SRNN。层内的神经元完全循环连接,层间的神经元通过前向连接完全连接。

从图中可以看出,其结构描述如下:

  1. 层间全连接(Forward Connection):不同层之间的神经元是全连接的,但是连接是单向的,也就是说来自较低层的神经元向较高层的神经元传递信息。这种连接方式允许信息从网络的输入层传递到输出层,完成整个网络的信息处理过程。

  2. 层内循环连接,该连接包括两个部分:

  • Recurrence of Neuron:同一层内的神经元在时间上是自连接的,它接收前一时间刻的脉冲输出,并将其传递给当前时间刻。

  • Recurrent Connection:同一层内的每个神经元在空间上相互连接,它接受前一时间刻的膜电压输出,并将其传递给当前时间刻。

  1. 网络计算方式:SRNN的计算方式基于一个公式,描述了神经元处理的计算过程。该公式是

\[I_t = [W_{m,n}X_m + W_{n,n}S_{t-1}]\]

其中:

  • \(W_{m,n}\):输入到神经元的权重矩阵。

  • \(X_m\):输入。

  • \(W_{n,n}\):循环连接的权重矩阵。

  • \(S_{t-1}\):前一个时间步的神经元状态。

这个公式说明了每个神经元的输入通常包括两部分:当前时间步的输入和前一个时间步的神经元状态。 这两部分的组合可以视为一个线性组合,因为它们通常通过加权求和的方式结合起来,以更新当前时间步的神经元状态。

综上所述,SRNN具有丰富的连接方式和计算方式,能够处理具有时序关联性的任务,同时在层间和层内的连接上具有全连接的特性。 脉冲神经元模拟了大脑神经元的工作方式,它们以脉冲(或事件)的形式传递和处理信息。循环结构使得网络能够存储和利用先前时间步的信息,从而更好地处理时序数据。

SRNN的关键特性包括:

1、 脉冲神经元:使用脉冲作为信息传递的方式。这些脉冲神经元的激发和响应方式模拟了生物神经元的行为。SRNN使用脉冲神经元作为其基本构建块,在SRNN网络中,可以使用不同类型的脉冲神经元中的一种,如LIF神经元、ALIF神经元模型,来模拟生物神经元行为。每个神经元在接收到输入后,会生成脉冲信号,这种脉冲信号通过神经网络的连接传递,形成时间上的动态。

2、 循环结构:具有循环连接,使得网络可以在时间上保持信息,并且能够处理具有时序关联性的任务,如时间序列预测、时间相关的分类等。

3、 时序任务处理:由于脉冲神经元和循环结构的特性,SRNN 在处理时序任务时具有潜在优势,特别是在需要考虑时间相关性和时序信息的任务中。

SRNN模块的使用过程: 首先,需要导入SRNN和某一个神经元模型,如

from neurai.nn.layer import SRNN
from neurai.nn.neuron import SNNLIF

创建一个SRNN层:

lif_neuron = SNNLIF(tau=2.0)
srnn_neuron = SRNN(lif_neuron, out_dim=1024)

SRNN类的主要参数:

  • neuron: 在SRNN中被使用的神经元模型。

  • dense_w: 输入到神经元的线性变换层,将输入数据转换为循环层的隐藏状态。

  • dense_r: 循环连接的线性变换层,将循环层神经元上一时刻的输出进行转换。

  • out_dim: SRNN层的输出维度。

  • time_dim: 输入数据中时间维度的位置。

  • bias: 是否在线性层中使用偏置。

  • kernel_init: 线性层权重的初始化方法。

  • recurrent_kernel_init: 循环连接层的线性层初始化方法。

  • bias_init: 偏置的初始化方法。

  • param_dtype: 数据类型,默认值是jnp.float32。