SpikingFlow.neuron package

Module contents

class SpikingFlow.neuron.BaseNode(shape, r, v_threshold, v_reset=0.0, device='cpu')[源代码]

基类:torch.nn.modules.module.Module

参数
  • shape – 输出的shape,可以看作是神经元的数量

  • r – 膜电阻,可以是一个float,表示所有神经元的膜电阻均为这个float。 也可以是形状为shape的tensor,这样就指定了每个神经元的膜电阻

  • v_threshold – 阈值电压,可以是一个float,也可以是tensor

  • v_reset – 重置电压,可以是一个float,也可以是tensor 注意,更新过程中会确保电压不低于v_reset,因而电压低于v_reset时会被截断为v_reset

  • device – 数据所在的设备

时钟驱动(逐步仿真)的神经元基本模型

这些神经元都是在t时刻接收电流i作为输入,与膜电阻r相乘,得到dv = i * r

之后self.v += dv,然后根据神经元自身的属性,决定是否发放脉冲

需要注意的是,所有的神经元模型都遵循如下约定:

  1. 电压会被截断到[v_reset, v_threshold]

  2. 数据经过一个BaseNode,需要1个dt的时间。可以参考simulating包的流水线的设计

  3. t-dt时刻电压没有达到阈值,t时刻电压达到了阈值,则到t+dt时刻才会放出脉冲。这是为了方便查看波形图, 如果不这样设计,若t-dt时刻电压为0.1,v_threshold=1.0,v_reset=0.0, t时刻增加了0.9,直接在t时刻发放脉冲,则从波形图 上看,电压从0.1直接跳变到了0.0,不利于进行数据分析

forward(i)[源代码]
参数

i – 当前时刻的输入电流,可以是一个float,也可以是tensor

Return:out_spike

shape与self.shape相同,输出脉冲

接受电流输入,更新膜电位的电压,并输出脉冲(如果过阈值)

reset()[源代码]
返回

None

将所有状态变量全部设置为初始值,作为基类即为将膜电位v设置为v_reset

对于子类,如果存在除了v以外其他状态量的神经元,应该重写此函数

training: bool
class SpikingFlow.neuron.IFNode(shape, r, v_threshold, v_reset=0.0, device='cpu')[源代码]

基类:SpikingFlow.neuron.BaseNode

参数
  • shape – 输出的shape,可以看作是神经元的数量

  • r – 膜电阻,可以是一个float,表示所有神经元的膜电阻均为这个float。 也可以是形状为shape的tensor,这样就指定了每个神经元的膜电阻

  • v_threshold – 阈值电压,可以是一个float,也可以是tensor

  • v_reset – 重置电压,可以是一个float,也可以是tensor。 注意,更新过程中会确保电压不低于v_reset,因而电压低于v_reset时会被截断为v_reset

  • device – 数据所在的设备

IF神经元模型,可以看作理想积分器,无输入时电压保持恒定,不会像LIF神经元那样衰减

\[\frac{\mathrm{d}V(t)}{\mathrm{d} t} = R_{m}I(t)\]

电压一旦达到阈值v_threshold则下一个时刻放出脉冲,同时电压归位到重置电压v_reset

测试代码

if_node = neuron.IFNode([1], r=1.0, v_threshold=1.0)
v = []
for i in range(1000):
    if_node(0.01)
    v.append(if_node.v.item())

pyplot.plot(v)
pyplot.show()
forward(i)[源代码]
参数

i – 当前时刻的输入电流,可以是一个float,也可以是tensor

返回

out_spike: shape与self.shape相同,输出脉冲

training: bool
class SpikingFlow.neuron.LIFNode(shape, r, v_threshold, v_reset=0.0, tau=1.0, device='cpu')[源代码]

基类:SpikingFlow.neuron.BaseNode

参数
  • shape – 输出的shape,可以看作是神经元的数量

  • r – 膜电阻,可以是一个float,表示所有神经元的膜电阻均为这个float。 也可以是形状为shape的tensor,这样就指定了每个神经元的膜电阻

  • v_threshold – 阈值电压,可以是一个float,也可以是tensor

  • v_reset – 重置电压,可以是一个float,也可以是tensor 注意,更新过程中会确保电压不低于v_reset,因而电压低于v_reset时会被截断为v_reset

  • tau – 膜电位时间常数,越大则充电越慢 对于频率编码而言,tau越大,神经元对“频率”的感知和测量也就越精准 在分类任务中,增大tau在一定范围内能够显著增加正确率

  • device – 数据所在的设备

LIF神经元模型,可以看作是带漏电的积分器

\[\tau_{m} \frac{\mathrm{d}V(t)}{\mathrm{d}t} = -(V(t) - V_{reset}) + R_{m}I(t)\]

电压在不为v_reset时,会指数衰减

v_decay = -(self.v - self.v_reset)
self.v += (self.r * i + v_decay) / self.tau

电压一旦达到阈值v_threshold则下一个时刻放出脉冲,同时电压归位到重置电压v_reset

测试代码

lif_node = neuron.LIFNode([1], r=9.0, v_threshold=1.0, tau=20.0)
v = []

for i in range(1000):
    if i < 500:
        lif_node(0.1)
    else:
        lif_node(0)
    v.append(lif_node.v.item())

pyplot.plot(v)
pyplot.show()
training: bool
forward(i)[源代码]
参数

i – 当前时刻的输入电流,可以是一个float,也可以是tensor

返回

out_spike: shape与self.shape相同,输出脉冲