赞
踩
为了便于理解时间驱动,我们可以将SNN(spiking neuron network)看作是一种RNN,它的输入是电压增量(电流与膜电阻的乘积),隐藏状态是膜电压,输出是脉冲。这样的SNN神经元具有马尔可夫性:当前时刻的输出只与当前时刻的输入,神经元自身的状态有关。
可以用充电,放电,重置3个方程描述脉冲神经元: H ( t ) = f ( V ( t − 1 ) , X ( t ) ) H(t)=f(V(t-1),X(t)) H(t)=f(V(t−1),X(t)) S ( t ) = g ( H ( t ) − V t h r e s h o l d ) = Θ ( H ( t ) − V t h r e s h o l d ) S(t)=g(H(t)-V_{threshold})=\Theta(H(t)-V_{threshold}) S(t)=g(H(t)−Vthreshold)=Θ(H(t)−Vthreshold) V ( t ) = H ( t ) ⋅ ( 1 − S ( t ) ) + V r e s e t ⋅ S ( t ) V(t)=H(t)\cdot(1-S(t))+V_{reset}\cdot S(t) V(t)=H(t)⋅(1−S(t))+Vreset⋅S(t)其中, V ( t ) V(t) V(t)是神经元的膜电压, X ( t ) X(t) X(t)是外源输入,即电压增量, H ( t ) H(t) H(t)是神经元的隐藏状态,可以理解为神经元还没有发脉冲前的瞬间, f ( V ( t − 1 ) , X ( t ) ) f(V(t-1),X(t)) f(V(t−1),X(t))是神经元的状态更新方程,不同的神经元,区别在于更新方程不同。
对于LIF神经元,其动作的微分方程和近似差分方程分别为: τ m d V ( t ) d t = − ( V ( t ) − V r e s e t ) + X ( t ) \tau_{m}\frac{dV(t)}{dt}=-(V(t)-V_{reset})+X(t) τmdtdV(t)=−(V(t)−Vreset)+X(t) τ m ( V ( t ) − V ( t − 1 ) ) = − ( V ( t − 1 ) − V r e s e t ) + X ( t ) \tau_{m}(V(t)-V(t-1))=-(V(t-1)-V_{reset})+X(t) τm(V(t)−V(t−1))=−(V(t−1)−Vreset)+X(t)因此,对应的充电(状态更新)方程为: f ( V ( t − 1 ) , X ( t ) ) = V ( t − 1 ) + 1 τ m ( − ( V ( t − 1 ) − V r e s e t ) + X ( t ) ) f(V(t-1),X(t))=V(t-1)+\frac{1}{\tau_{m}}(-(V(t-1)-V_{reset})+X(t)) f(V(t−1),X(t))=V(t−1)+τm1(−(V(t−1)−Vreset)+X(t))放电方程中的 S ( t ) S(t) S(t)是神经元发放的脉冲, g ( x ) = Θ ( x ) g(x)=\Theta(x) g(x)=Θ(x)是阶跃函数,也被称为脉冲函数,脉冲函数的输出仅为0或1。
重置表示电压重置过程:发放脉冲,则电压重置为 V r e s e t V_{reset} Vreset;如果没有发放脉冲,则电压不变。
注意到,在RNN中,使用了可微分的激活函数,例如tanh。但SNN中对应的脉冲函数 g ( x ) g(x) g(x)是不可微分的,这就导致了包含SNN层的深度学习模型不能用反向传播的方式来训练。但是我们可以用一个形状与阶跃函数相似的激活函数 σ ( x ) \sigma(x) σ(x)去代替。这被称为梯度替代法。
在前向传播时,使用 g ( x ) = Θ ( x ) g(x)=\Theta(x) g(x)=Θ(x),神经元的输出是离散的0和1,网络依然是标准的SNN,但反向传播时,使用梯度替代函数代替计算脉冲函数的梯度: g ′ ( x ) = σ ′ ( α x ) g'(x)=\sigma'(\alpha x) g′(x)=σ′(αx)其中, α \alpha α可以调整激活函数的平滑程度: σ ( α x ) = 1 1 + e x p ( − α x ) \sigma(\alpha x)=\frac{1}{1+exp(-\alpha x)} σ(αx)=1+exp(−αx)1当 α \alpha α越大, σ ( α x ) \sigma(\alpha x) σ(αx)就越接近 Θ ( x ) \Theta(x) Θ(x),但也越容易在靠近 x = 0 x=0 x=0时梯度爆炸,远离 x = 0 x=0 x=0时则容易梯度消失,导致网络难以训练。
下图显示了不同
α
\alpha
α时,梯度替代函数的形状:
对于事件驱动的SNN,不需要通过时钟驱动SNN的计算,神经元的状态更新由事件触发。
在脉冲响应模型(Spike response model,SRM)中,使用显式的 V − t V-t V−t方程来描述神经元的活动,而不是用微分方程去描述神经元的充电过程。由于 V − t V-t V−t是已知的,因此给与任何输入 X ( t ) X(t) X(t),神经元的响应 V ( t ) V(t) V(t)都可以被直接算出(不需要提供 V ( t − 1 ) V(t-1) V(t−1)的信息,因此与时钟取消了关联)。
Tempotron神经元也是一种SNN神经元,其命名来源于ANN中的感知器,感知器是最简单的ANN神经元,其对输入数据加权求和,输出二值0或1来表示数据的分类结果。Tempotron神经元可以看作是SNN中的感知器,它同样对输入数据加权求和,再输出二分类结果。
Tempotron的膜电位定义为: V ( t ) = ∑ i w i ∑ t i K ( t − t i ) + V r e s e t V(t)=\sum_{i}w_{i}\sum_{t_{i}}K(t-t_{i})+V_{reset} V(t)=i∑witi∑K(t−ti)+Vreset其中, w i w_{i} wi是第 i i i个输入的权重,也可以看作是所连接的突触的权重; t i t_{i} ti是第 i i i个输入的脉冲发射时刻, K ( t − t i ) K(t-t_{i}) K(t−ti)是由于输入脉冲引发的突触后膜电位(postsynaptic potentials,PSPs); V r e s e t V_{reset} Vreset是Tempotron的重置电位,或者称为静息电位。
其中,关于 K ( t − t i ) K(t-t_{i}) K(t−ti)是一个关于 t i t_{i} ti的函数(PSP Kernel),当 t ≥ t i t\geq t_{i} t≥ti时,其函数表达为: K ( t − t i ) = V 0 ( e x p ( − t − t i τ ) − e x p ( − t − t i τ s ) ) K(t-t_{i})=V_{0}(exp(-\frac{t-t_{i}}{\tau})-exp(-\frac{t-t_{i}}{\tau_{s}})) K(t−ti)=V0(exp(−τt−ti)−exp(−τst−ti))当 t < t i t<t_{i} t<ti时,其函数表达为: K ( t − t i ) = 0 K(t-t_{i})=0 K(t−ti)=0其中, V 0 V_{0} V0是归一化系数,使得函数的最大值为1; τ \tau τ是膜电位时间常数,可以看出输入的脉冲在Tempotron上会引起瞬时的电位激增,但之后会呈指数衰减; τ s \tau_{s} τs是突触电流的时间常数,这一项的存在表示突触上传导的电流会随时间衰减。
单个的Tempotron可以作为一个二分类器,分类结果的判别,是看Tempotron的膜电位在仿真周期内是否超过阈值:
其中
t
m
a
x
=
a
r
g
m
a
x
t
{
V
t
}
t_{max}=argmax_{t}\left\{V_{t}\right\}
tmax=argmaxt{Vt}。从Tempotron的输出结果也可以看出,Tempotron只能发射不超过1个脉冲。单个Tempotron只能做二分类,但多个Tempotron就可以做多分类。
关于Tempotron的训练,可以使用梯度下降法优化网络参数
w
i
w_{i}
wi,以二分类问题为例,损失函数被定义为仅在分类错误的情况下存在。当实际类别
y
y
y是1而实际输出
y
^
\widehat{y}
y
是0,损失为
V
t
h
r
e
s
h
o
l
d
−
V
t
m
a
x
V_{threshold}-V_{t_{max}}
Vthreshold−Vtmax;当实际类别是0而实际输出是1,损失为
V
t
m
a
x
−
V
t
h
r
e
s
h
o
l
d
V_{t_{max}}-V_{threshold}
Vtmax−Vthreshold。可以统一写为:
E
=
(
y
−
y
^
)
(
V
t
h
r
e
s
h
o
l
d
−
V
t
m
a
x
)
E=(y-\widehat{y})(V_{threshold}-V_{t_{max}})
E=(y−y
)(Vthreshold−Vtmax)直接对参数求梯度,可以得到:
因为:
∂
V
(
t
m
a
x
)
∂
t
m
a
x
=
0
\frac{\partial V(t_{max})}{\partial t_{max}}=0
∂tmax∂V(tmax)=0
后续内容的实验部分将基于第三方库spikingjelly进行。SpikingJelly是一个开源脉冲神经网络深度学习框架,使用PyTorch作为自动微分后端,利用C++和CUDA扩展进行性能增强,同时支持CPU和GPU。框架中包含数据集,可视化,深度学习三大模块。
安装spikingjelly:
pip install spikingjelly
在spikingjelly中,约定只能输出脉冲,即0或1的神经元,都可以称之为"脉冲神经元",使用脉冲神经元的网络,进而也可以称之为脉冲神经网络。在spikingjelly.clock_driven.neuron
中定义了各种常见的脉冲神经元模型,我们以spikingjelly.clock_driven.neuron.LIFNode
为例进行了解。
首先导入相关模块:
import torch
import torch.nn as nn
import numpy as np
from spikingjelly.clock_driven import neuron
from spikingjelly import visualizing
import matplotlib.pyplot as plt
新建一个LIF神经元构成的网络层:
lif=neuron.LIFNode(tau=100.0)
LIF神经元的参数有以下:
其中 surrogate_function 参数,在前向传播时的行为与阶跃函数完全相同。
神经元的数量是在初始化或调用 reset()
函数重新初始化后,根据第一次接收输入的 shape
自动决定的。
与RNN中的神经元非常类似,脉冲神经元也是有状态的,或者说是有记忆。脉冲神经元的状态变量,一般是它的膜电位
V
(
t
)
V(t)
V(t)(发射脉冲前),因此,spikingjelly.clock_driven.neuron
中的神经元,都有对象v
,可以打印刚刚新建神经元的膜电位:
print(lif.v) # 0.0
电位是0,因为我们没有给它任何输入,我们给几个不同的输入,观察神经元的电压shape
:
x = torch.rand(size=[2, 3])
lif(x)
print('x.shape', x.shape, 'lif.v.shape', lif.v.shape)
# x.shape torch.Size([2, 3]) lif.v.shape torch.Size([2, 3])
lif.reset()
x = torch.rand(size=[4, 5, 6])
lif(x)
print('x.shape', x.shape, 'lif.v.shape', lif.v.shape)
# x.shape torch.Size([4, 5, 6]) lif.v.shape torch.Size([4, 5, 6])
回顾前面的LIF神经元状态更新方程(充电):
τ
m
d
V
(
t
)
d
t
=
−
(
V
(
t
)
−
V
r
e
s
e
t
)
+
X
(
t
)
\tau_{m}\frac{dV(t)}{dt}=-(V(t)-V_{reset})+X(t)
τmdtdV(t)=−(V(t)−Vreset)+X(t)其中,
τ
m
\tau_{m}
τm是膜电位时间常数,
V
r
e
s
e
t
V_{reset}
Vreset是重置电压,对于这样的微分方程,由于
X
(
t
)
X(t)
X(t)不是常数,所以不易求出解析解,我们用差分方程近似微分:
τ
m
(
V
(
t
)
−
V
(
t
−
1
)
)
=
−
(
V
(
t
−
1
)
−
V
r
e
s
e
t
)
+
X
(
t
)
\tau_{m}(V(t)-V(t-1))=-(V(t-1)-V_{reset})+X(t)
τm(V(t)−V(t−1))=−(V(t−1)−Vreset)+X(t)因此可以得到
V
(
t
)
V(t)
V(t)(神经元未发射脉冲前的瞬时电压)的表达式:
V
(
t
)
=
f
(
V
(
t
−
1
)
,
X
(
t
)
)
=
V
(
t
−
1
)
+
1
τ
m
(
−
(
V
(
t
−
1
)
−
V
r
e
s
e
t
)
+
X
(
t
)
)
V(t)=f(V(t-1),X(t))=V(t-1)+\frac{1}{\tau_{m}}(-(V(t-1)-V_{reset})+X(t))
V(t)=f(V(t−1),X(t))=V(t−1)+τm1(−(V(t−1)−Vreset)+X(t))不同的神经元,充电方程不尽相同。但膜电位超过阈值电压后,释放脉冲,以及释放脉冲后,膜电位的重置都是相同的。因此它们全部继承自 spikingjelly.clock_driven.neuron.BaseNode
,共享相同的放电、重置方程。
surrogate_function()
在前向传播时是阶跃函数,只要输入大于或等于0,就会返回1,否则会返回0。我们将这种元素仅为0或1的 tensor 视为脉冲。
发射脉冲消耗了神经元累积的电荷,因此膜电位会有一个瞬时的降低,即电压重置,在spikingjelly中,设置了两种重置方式,根据spikingjelly.clock_driven.neuron
中的构造函数的参数之一 v_reset
选择:
v_reset=1.0
(默认值为1.0),释放脉冲后,膜电位直接被设置成重置电压:
V
(
t
)
=
V
r
e
s
e
t
V(t)=V_{reset}
V(t)=Vreset;v_reset=None
,释放脉冲后,膜电位减去阈值电压:
V
(
t
)
=
V
(
t
)
−
V
t
h
r
e
s
h
o
l
d
V(t)=V(t)-V_{threshold}
V(t)=V(t)−Vthreshold。接下来,我们将逐步给与神经元输入,并查看它的膜电位和输出脉冲。
现在我们给与LIF神经元层持续的输入,并画出其放电后的膜电位和输出脉冲:
lif.reset()
x = torch.as_tensor([2.0])
T = 150
s_list = [] # 输出脉冲
v_list = [] # 隐藏状态:膜电位
for t in range(T):
s_list.append(lif(x))
v_list.append(lif.v)
visualizing.plot_one_neuron_v_s(np.asarray(v_list), np.asarray(s_list), v_threshold=lif.v_threshold, v_reset=lif.v_reset,
dpi=200)
plt.show()
我们给与的输入shape=[1]
(固定数值2.0),因此这个神经元层只有一个神经元。它的膜电位(Membrane Potentials)和输出脉冲随着时间变化情况如上图。
现在将该层神经元重置(重新初始化),并给与shape=[32]
的随机数组输入,查看这32个神经元的膜电位和输出脉冲:
lif.reset() x = torch.rand(size=[32]) * 4 T = 50 s_list = [] # 32个神经元在50步仿真下输出的脉冲 v_list = [] # 32个神经元在50步仿真下的膜电位 for t in range(T): s_list.append(lif(x).unsqueeze(0)) # unsqueeze(0)增加首维度,lif(x).unsqueeze(0) shape=[1,32] v_list.append(lif.v.unsqueeze(0)) s_list = torch.cat(s_list) # shape=[50,32] v_list = torch.cat(v_list) # shape=[50,32] visualizing.plot_2d_heatmap(array=np.asarray(v_list), title='Membrane Potentials', xlabel='Simulating Step', ylabel='Neuron Index', int_x_ticks=True, x_max=T, dpi=200) visualizing.plot_1d_spikes(spikes=np.asarray(s_list), title='Spiking', xlabel='Simulating Step', ylabel='Neuron Index', dpi=200) plt.show()
从Spiking中可以看出,有部分神经元发射了脉冲,有的却没有发射。我们可以想像,在重复输入一个信息对象的过程中,该信息对象对应的某个特征持续被感知到,迫使该神经元膜电位上升而作出发射脉冲的行为。
从上面的仿真可以看出,脉冲神经元层可以接收连续数值张量,但只能输出脉冲,如果仅包含LIF脉冲神经元层,模型不需要训练(因为没有可学习参数)。
对比传统的神经元,传统神经元的激活是瞬时的,缺少时间尺度上提供的信息,从生物角度看,此刻兴奋的神经元在下一时刻应该惯性地也比较兴奋。这就引出了脉冲神经网络(SNN)的想法,神经元的兴奋度不应该是一瞬间更新的,而是具有慢慢衰减的表现,在持续输入信息的刺激下,最后激活的兴奋区才是预测判别结果。SNN更贴近生物角度,适合处理与脉冲序列有关的应用前景。
研究问题随笔
通过观察LIF神经元,发现神经元缺少知识,若想嵌入到深度学习模型,只能作为替代激活函数的一个工具。LIF神经元只是模拟了生物上信息的传递与神经元电位的改变,后续研究或许可以在LIF的机理上进行修改,为神经元增加知识。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。