SpikingNN_on_trial
refs
- Error-backpropagation in temporally encoded networks of spiking neurons, 10.1016/S0925-2312(01)00658-0
- Spatio-Temporal Backpropagation for Training High-Performance Spiking Neural Networks, 10.3389/fnins.2018.00331
神经元的脉冲在信息编码中的特点
[29] W. Maass, Fast sigmoidal networks via spiking neurons, Neural Comput. 9 (2) (1997) 279–304.
· 在上述文章中,已经给出证明,脉冲神经网络可以模拟任意形式的前馈sigmoid神经元组成的神经网络。 基于这个特性,SNN可以近似任意的连续函数。SNN中单个尖峰时间传递信息的神经元比具有sigmoid激活函数的神经元计算能力更强。
脉冲,在数学上表征为一个“活人/游戏事件”,即“地点,时刻”的坐标。而且活跃(尖峰)神经元的数量通常比较稀少。基于这个特性,SNN可以允许神经网络大模型在VLSI上高效部署。
SNN会产生与Kohonen’s SOM类似的自组织,无监督聚类网
针对时空编码范式的有监督的单脉冲学习算法:基于误差-反向传播的有监督学习算法
概念:阈值函数?(threshold function) 速率编码网络?(rate-coded network)活/人游戏? 突触后电位(呃呃呃死去的回忆突然攻击我)
SNN的网络结构
脉冲响应模型:spike response model (SRM),表征输入脉冲和神经元内部的状态的关系。
单个神经元(第j个)的 内在状态(inertial state) 的度量:
式中,
这个式子也表征了一个神经元的未加权的post-synaptic potential(突触后电位)。
至此,我们有了一个基本的认知:神经元的突触前膜产生的若干个电位信号作用在神经元,其和作用达到一个阈值之后,就会产生动作电位,并向下传导。这和高中学过的神经生理学的知识很相似。
每个突触与前后两个神经元的连接建模如下:
单个突触末端对神经元状态变量的非加权贡献值为
式中
至此,我们对单个突出的前后电位传递进行了建模。那么重写一下
SNN的误差反向传播
假设整个网络包括H(输入层)、I(隐藏层)、J(输出层):
前馈算法的目的是学习一组目标激活时刻/放电时刻(firing times):
对于神经元
对于误差反向传播,我们将每一个突触连接看作一个单独的作用单元k,
其权重是
此步就是正常的反向传播 ?思路。
1.
其中,
2.
3.
将上面三个子项代入原始的更新权重中:
为便于表示,定义超参数
对于第J层之前的隐藏层,同理:对于第i个神经元(
(以上的所有推导全部基于2002年的误差-反向传播思路,但是太™麻烦,也很难理清思路,不急,有的是时间理清)
tutor:上面的模型有些许误导性,若干个突触连接前后两个神经元,看似是把网络维度扩大了,网络更复杂了。但是如今的SNN网络架构已经摒弃了这种想法。类似ANN,前后神经元仅通过一个权重参数进行前向传播。
我:huh?
error-bp SNN 为什么不好?
SNN发展的几个派系(ε=ε=ε=┏(゜ロ゜;)┛)
ANN-to-SNN:采用近似的思想,实际工程中会造成精度丢失。近似过后的SNN性能也不如ANN。
膜电位驱动的学习算法(membrane potential-driven learning algorithms):空间需求大。
峰值驱动学习算法(spike-driven learning algorithms): 包括SpikeProp及其衍生算法。这类算法依赖神经元膜电位在点火时间邻域内增长近似线性,导数计算变得更容易。仍存在坏死的神经元和梯度爆炸问题(版本答案)
DeepSNN的建模过程以及其训练弊端
考虑一个全连接DeepSNN网络,为便于分析,假设所有神经元最多进行一次点火。
参数解释:
Parameter | Description |
---|---|
第 |
|
连接神经元 |
|
PSP(突触后电位)函数,以 |
|
在 |
|
尖峰发生函数,在膜电位等于 |
|
膜电位恢复函数(refractory kernel) |
根据上面对SNN网络的建模,我们可以通过BP算法更新参数:
计算
问题一:由于脉冲函数的离散性,脉冲函数不可导
问题二:梯度爆炸发生在
问题三:坏死的神经元(dead
neuron):如果突触前电位不足以使神经元点火,即探察不到有
三个问题怎么克服?
1. ReL-PSP-Based Spiking Neuron Model
索性重新建模神经元:
对比一下,不难发现,不仅舍去了恢复函数
核函数K的定义如下:
眼熟吗?很像一位老朋友:ReLU
不能说极度相似,简直是一模一样。(难怪作者起这个名字)
ReL-PSP的线性特性,使得膜电位在尖峰时刻达到之前(prior to)线性增长.
计算
有了ReL-PSP核函数,我们甚至不用假设近似线性。逐层的累计误差相当于没有了。
梯度爆炸问题中,由于分母中的
即便是
(好的这段话已经把我绕晕了)
坏死神经元问题:ReL-PSP摒弃了恢复函数,即膜电位不会恢复,只会不断积累。也就是说无论如何神经元都会发出脉冲,只是时间早晚的问题。
Error-BP
问题背景:n分类问题。
损失函数:交叉熵
输出层函数:softmax
参数解释:
Parameter | Description |
---|---|
$ |
目标类别索引 |
反向传播的偏导计算:
遗留问题:
为什么反向传播更新的过程中要更新
?关于梯度消失推导的最后一段描述,和坏死神经元的关系?
- OpenSMART NoC?
经典算法STBP:
SNN训练的三种方式:
无监督学习:STDP
间接监督学习:ANN-to-SNN
直接监督学习:梯度下降
尖峰神经网络中的迭代泄漏整合与发射模型(Iterative Leaky Integrate-And-Fire (LIF) Model in Spiking Neural Networks)
LIF用于对SNN网络中神经元行为进行描述:
参数解释:
Parameter | Description |
---|---|
t时刻的神经元膜电位 | |
时间常数 | |
突触前活动状态,外部刺激和突触权重 | |
膜电位阈值 |
直观感受这个公式,它在描述膜电位随时间的变化状态。变化快慢由
为了解决SNN网络在时间域上动态变化复杂,不便于进行反向传播,首先对上述的线性微分方程在
即:t时刻的膜电位与前一时刻的膜电位(Temporal Dynamics,
TD)以及t时刻突触前输入
通过DNN中误差反向传播的训练方法,研究者从中获得启发,DNN的误差反向传播是在空间域上进行的,如何拓展到基于LIF模型的SNN上呢?
参数解释:
Parameter | Description |
---|---|
forget gate(from LSTM |
|
output gate(from LSTM),用于控制脉冲释放 | |
上标t | t时刻 |
第n层 | |
(第n层中)第l个神经元 | |
突触前层第 j 个神经元到突触后层第 i 个神经元的突触权重 | |
神经元输出脉冲与否,1代表输出,0代表不输出 | |
第n层第i个神经元在t+1时刻的膜电位 | |
表征点火阈值的变量, 利用可调偏置 b 来模拟阈值行为 |
对于一个很小的时间之内(又要进行必要的假设了),
(额?)
STBP训练框架
定义损失函数为均方误差累积:
参数解释:
Parameter | Description |
---|---|
第s个训练样本标签 | |
第s个训练样本在特定时刻的输出 |
损失函数
假设我们已经得到了每一层n在特定时刻t的输出偏导数:
对于单个神经元,传播被分解为垂直路径 SD 和水平路径 TD。SD 中的误差传播数据流类似于 DNN 的典型 BP,即每个神经元累积来自上层的加权误差信号,并迭代更新不同层的参数。而 TD 中的数据流共享相同的神经元状态,这使得直接获得解析解变得相当复杂。为了解决这个问题,研究者利用提出的迭代 LIF 模型在 SD 和 TD 方向上展开状态空间,从而可以区分不同时间步长的 TD 中的状态,这就实现了迭代传播的链式规则。Werbos (1990) 中用于训练 RNN 的 BPTT 算法也有类似的思想。
denote:
Case 1:
Case 2:
(本人对上式深表怀疑)
Case 3:
where
Case 4:
最终得到关于
(上面这个式子应该是错误的)
对尖峰函数的近似表达:
STBP代码复现1:MNIST分类任务
ref: https://github.com/yjwu17/STBP-for-training-SpikingNN
a. spiking_model.py
1. 包依赖
1 | import torch |
2. 基本参数设定
1 | device = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
3. 近似点火函数
1 | class ActFun(torch.autograd.Function): |
该部分重写了两个方法:前向传播和反向传播。首先,函数传进torch.autograd.Function
,forward
方法接受输入张量 input,将其与预定义的 thresh
进行比较,然后通过 input.gt(thresh).float()
返回一个新的张量,其中每个元素都是对应输入张量元素是否大于阈值的浮点值。ctx.save_for_backward(input)
用于保存输入张量,以便在反向传播时使用。
在反向传播中,backward
方法接受梯度输出
grad_output
,然后通过 ctx.saved_tensors
获取保存的输入张量。梯度计算采用了一些条件判断,具体来说,计算了绝对值小于
lens
的部分。最终,返回的梯度是
grad_input * temp.float()
,其中 temp
是一个布尔张量,指示输入张量元素是否满足条件。
最后,通过 act_fun = ActFun.apply
创建了一个可以在模型中使用的激活函数。使用时,可以通过调用
act_fun(input)
进行前向传播。
4. 膜电位更新函数
1 | def mem_update(ops, x, mem, spike): |
膜电位 * 衰减系数 * (1 - 上一次的脉冲) + 对x运算过后的结果(
当前膜电位决定是否点火:
5. CNN网络层配置参数
1 | # cnn_layer(in_planes, out_planes, stride, padding, kernel_size) |
参数解释:
Parameters | Description |
---|---|
in_planes | 输入通道数 |
out_planes | 输出通道数 |
stride | 步长 |
padding | 填充 |
kernel_size | 卷积核大小 |
第一层:输入通道数为 1,输出通道数为 32,步幅为 1,填充为 1,卷积核大小为 3。
第二层:输入通道数为 32,输出通道数为 32,步幅为 1,填充为 1,卷积核大小为 3。
cfg_kernel
: 整数列表,存有不同层次的卷积核大小;
cfg_fc
:
整数列表,表示全连接层的配置,一边是128个神经元,一边是10个神经元。
6. 学习率调度器函数
1 | # Dacay learning_rate |
在每个 lr_decay_epoch 周期后将学习率衰减为原来的 0.1 倍。
optimizer.param_groups是一个包含参数组的列表,每个参数组是一个字典,包含一组参数和这组参数对应的优化选项,如学习率、权重衰减等。
7. SCNN网络架构设计
1 | class SCNN(nn.Module): |
b. main.py
1. 包依赖
1 | from __future__ import print_function |
2. 设定训练任务的基本配置
1 | names = 'spiking_model' |
3. SCNN训练循环
1 | for epoch in range(num_epochs): |
4. 测试阶段:
1 | with torch.no_grad(): # 在测试模型时,我们不需要计算梯度,因此可以关闭梯度计算以节省内存和计算资源。 |
5. 输出其他内容和保存模型状态
1 | print('Iters:', epoch, '\n\n\n') |
STBP代码复现2:CIFAR-10分类任务
ref:
Deep Residual Learning in Spiking Neural Networks, Wei Fang et al., Neural Information Processing Systems (NeurIPS) 2021 (SEW/Spike-Element-Wise block)
Differentiable Spike: Rethinking Gradient-Descent for Training Spiking Neural Networks, Yuhang Li et al., Neural Information Processing Systems (NeurIPS 2021). (a new family of Differentiable Spike (Dspike))
1. SEW block的结构:
神经元行为建模:
参数解释:
Parameter | Description |
---|---|
神经元在进行运算活动之后的膜电位 | |
神经元动态活动(运算方式),可以是卷积,可以是其他形式 | |
t时刻发出脉冲之后的膜电位 | |
阶跃函数 | |
点火阈值 | |
膜电位恢复函数 | |
t时刻发射的脉冲 |
例子:两个神经元行为的建模方式:IF(Integrate-and-Fire,式一)和LIF(Leaky-Integrate-and-Fire,式二)
Identity Mapping(恒等映射): ResNet的核心思想
当
但对于从ANN迁移到SNN的Spiking Resnet块,就无法满足Identity Mapping:
当
mad先不读了,spikingjelly是真好用,文档可视化做的真的不错,非常适合入门
Continue:
对于IF神经元,恒等映射可以满足。设定
但对于更复杂的神经元行为建模方法,很难保证这一条件成立。例如LIF神经元,存在一个电位恢复常数
Vanishing & Exploding Gradient in Spiking Resnet blocks
当在t时刻,有k个Spiking Resnet块参与神经网络的前馈传递
输出对第l层的输入求偏导进行反向传播时有:
式中,
逐元素点火的Resnet块(Spike-Element-Wise Resnet)
SEW-Resnet的优点:
- 更易于实现恒等映射:利用尖峰的二进制属性,我们可以找到满足恒等映射的不同元素函数
Name | Expression of |
---|---|
ADD(加) | |
AND(与) | |
IAND |
e.g.: 选择ADD函数或者IAND函数作为Element-Wise Function,设定
相反地,选择AND函数,设定
拓展:SEW-Resnet的下采样块设计:用于输入输出维度不一致的时候。Conv层的步长大于1
SEW-Resnet与ReLU-before-Addition(RBA):
某种程度上,SEW的行为是RBA的行为拓展,但不一样的是,RBA会导致输出层不断积累,而SEW中,使用AND和IAND作为g会输出尖峰(即二元张量),这意味着ANNs中的无限输出问题不会发生在具有SEW块的SNNs中,因为所有尖峰都小于或等于1。当选取ADD为g时,由于k个顺序SEW块的输出不会大于k + 1,可以缓解无穷输出问题。此外,当g为ADD时,一个下采样的SEW块将调节输出不大于2。
SEW对于梯度爆炸/消失问题的缓解
逐层计算( l + k - 1) - th SEW块的输出相对于第l - th SEW块输入的梯度:
补习填坑:复变函数
- 标题: SpikingNN_on_trial
- 作者: Eric Zhang
- 创建于 : 2023-11-29 14:33:01
- 更新于 : 2023-12-12 17:13:20
- 链接: https://ericzhang1412.github.io/2023/11/29/SpikingNN-on-trial/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。