SpikingJelly惊蛰学习笔记

本文介绍了深度学习中的几种关键模型,包括DNN、CNN、RNN和LSTM,讨论了它们的特点、局限性以及相互之间的区别。此外,还涉及了SNN(脉冲神经网络)的基本概念,如LIF模型和前向传播、反向传播的过程。文章还提到了SpikingJelly,这是一个基于PyTorch的SNN深度学习框架,支持不同的传播模式和梯度替代方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前置知识

(一)DNN、CNN、RNN、LSTM的区别

此部分感谢@Jfightingk发布的《DNN、CNN、RNN、LSTM的区别,最全最详细解答》给到的启发。
DNN-深度神经网络
CNN-卷积神经网络
RNN-循环神经网络
LSTM-长短时记忆单元
1、神经网络三要素
(1)权重:神经元之间的连接强度由权重表示,权重的大小表示可能性的大小
(2)偏置:偏置的设置是为了正确分类样本,即保证通过输入算出的输出值不能随便激活。
(3)激活函数:起非线性映射的作用,其可将神经元的输出幅度限制在一定范围内,一般限制在(-1,1)或(0,1)之间。最常用的激活函数是Sigmoid函数,可将(-∞,+∞)的数映射到(0~1)的范围内。
在这里插入图片描述

2、MLP(多层感知器) -最简单且最原汁原味的神经网络
最典型的MLP包括输入层、隐层和输出层。MLP不同层之间是全连接(上一层的任意一个神经元与下一层的所有神经元都有连接)的。
在这里插入图片描述
经典例子:数字识别-随便给出一张上面写有数字的图片作为输入,由MLP给出图片上的数字是几。
对于一张写有数字的图片,可将其分解为由28*28=784个像素点构成,每个像素点的值在(0,1)之间,表示灰度值,值越大该像素点越亮,反之越暗。
而输出则由十个神经元构成,分别表示0-9这十个数字,这十个神经元的值也是在0-1之间,也表示灰度值,但这里的神经元值越大表示经过判断后是该数字的可能性越大。
3、DNN-感知器的拓展
DNN可以理解为有很多隐藏层的神经网络。
DNN存在的局限:
(1)参数数量膨胀
由于DNN采用的是全连接的形式,结构中的连接带来了数量级的权值参数,这不仅容易导致过拟合,也容易造成陷入局部最优。
(2)局部最优
随着神经网络的加深,优化函数更容易陷入局部最优,偏离真正的全局最优。对于有限的训练数据,性能甚至不如浅层网络。
(3)梯度消失
使用sigmoid激活函数,在BP反向传播梯度时,梯度会衰减,随着神经网络层数的增加,衰减累积下,到底层时梯度基本为0.
(4)无法对事件序列上的变化进行建模
4、CNN-针对DNN存在的参数数量膨胀问题
CNN并不是所有的上下层神经元都能直接相连,而是通过“卷积核”作为中介(部分连接)。
CNN因为限制参数个数并挖掘局部结构,适合图像识别。
5、RNN-针对CNN中无法对时间序列上的变化进行建模
为了适应时序数据的处理,出现了RNN。
在普通的全连接网络或者CNN中,每层神经元的信号只能向上一层传播,样本的处理在各个时刻独立(这种就是前馈神经网络)。而在RNN中,神经元的输出可以在下一个时间戳直接作用到自身。
(t+1)时刻网络的最终结果O(t+1)是该时刻输入和所有历史共同作用的结果,这就达到了对时间序列建模的目的。
存在的问题:
RNN可以看成一个在时间上传递的神经网络,它的深度是时间的长度,而梯度消失的现象出现时间轴上。
6、LSTM-解决RNN中时间上的梯度消失
原始RNN无法处理长距离依赖,原始RNN的隐藏层只有一个状态,即h,它对于短期的输入非常敏感。
长短时记忆网络在RNN的基础上再增加一个状态c,让它来保存长期的状态。
在这里插入图片描述

(二)SNN神经元模型

1、简介
基于神经元特性,开发了脉冲神经元模型。
图1 神经元和脉冲神经元模型类比
图2 SNN神经元
2、特点
(1)使用脉冲序列作为输入信号,脉冲序列本质上是二进制事件,即0或1;
(2)下游神经元由上游神经元驱动;
(3)SNN神经元只有在接收和发射脉冲信号时才会被激活
3、优点
(1)计算能力强,SNN可以模拟任何前馈的DNN
(2)节能
4、LIF(Leaky Integrate and Fired)模型-SNN中常用模型
leaky(泄露)——细胞膜内外存在电势差时,电压会逐渐降低(泄露)
I: integrate(积分)——外部向神经元注入电流时,神经元会对接收到的脉冲序列进行积分求和。
F: fire(发放)——上一步的膜电压的值超过设定的阈值后,当前神经元就会发放脉冲
(1)充电
可以在spikingjelly.activation_based.neuron.IFNode.neuronal_charge中找到如下代码:

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

(2)放电
可以在spikingjelly.activation_based.neuron.BaseNode.neuronal_fire中找到释放脉冲的代码

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

特别注意!!surrogate_function()在前向传播时是阶跃函数,只要输入大于或等于0,就会返回1,否则返回0。
(3)重置
Hard方式:释放脉冲时,膜电位直接设置为重置电压:V[t]=Vreset
Soft方式:释放脉冲后,膜电位减去阈值电压:V[t]=v[t]-Vthreshold

spikingjelly.activation_based.neuron.BaseNode.neuronal_fire.neuronal_reset中可以找到膜电位重置的代码:

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

图3 LIF模型的三个过程
5、LIF神经元的微分方程
该方程描述了当电压达到阈值时,神经元的电压会进行一个重置。
图4 LIF模型微分方程推导过程

(三)前向传播&反向传播

1、前向传播
将训练集数据输入到输入层,经过隐藏层,最后到达输出层并输出结果。
类比:三个人玩你画我猜,第一个人给第二个人描述,再将信息传给第三个人,由第三个人说画的是什么。
2、反向传播
由于输入结果和输出结果有误差,则计算实际值和估计值之间的误差,并将该误差从输出层向隐藏层反向传播,直至传播到输入层。
在反向传播的过程中,根据误差调整各种参数的值,不断迭代上述过程,直至收敛。
类比:第三个人得知自己说的和真实答案之间的误差后,发现他们传递时的问题在哪里,并向前一个人说下次描述时怎样可以更加准确地传递信息,就这样一直向前一个人告知。

二、SpikingJelly

(一)基本概念

基于PyTorch的SNN深度学习框架。使用pytorch作为自动微分后端,利用C++和CUDA扩展进行性能增强,框架中包含数据集、可视化、深度学习三大模块。
图5 SpikingJelly框架
1、框架提供了neuron、layer、functional、encoding四个基本模块:
(1)neuron提供了深度SNN中最常用的LIF和IF神经元;
(2)layer提供了SNN中特有的网络层;
(3)functional提供深度SNN所需函数;
(4)encoding提供常用的脉冲编码器

(二)spikingjelly.activation_based

1、数据格式&步进模式
图6 步进模式对比
所有模块地默认步进模式都是单步。
2、传播模式
(1)逐步传播(step-by-step)
若一个网络全部由单步模块构成,则整个网络的计算顺序是按照逐步传播的模式进行的。
(2)逐层传播(layer-by-layer)
如果网络全部由多步模块构成,则整个网络的计算顺序是按照逐层传播的模式进行的。
(3)计算图
SNN的计算图有2个维度,分别为时间步数网络深度。网络的传播实际上就是生成完整计算图的过程。
逐步传播-DFS:
图7 逐步传播构建计算图的顺序
逐层传播-BFS:
图8 逐层传播构建计算图的顺序
(4)对比
使用梯度替代法训练时,通常推荐逐层传播;
在内存受限时使用逐步传播。
----------------------------------------------2023.6.1笔记---------------------------------------------------

(三)包装器

在这里插入图片描述
1、更推荐使用 spikingjelly.activation_based.layer 中的网络层,而不是使用 SeqToANNContainer 手动包装,尽管 spikingjelly.activation_based.layer 中的网络层实际上就是用包装器包装 forward 函数实现的。优势在于:
(1)支持单步和多步模式,而 SeqToANNContainer 和 MultiStepContainer 包装的层,只支持多步模式;
(2)包装器会使得 state_dict 的 keys() 也增加一层包装,给加载权重带来麻烦
2、StepModeContainer 用处
(1)可以用于包装无状态或有状态的单步模块,需要在包装时指明是否有状态;
(2)支持切换单步和多步模式。
3、使用 set_step_mode 改变 StepModeContainer 是安全的,只会改变包装器本身的 step_mode,而包装器内的模块仍然保持单步。
4、如果模块本身就支持单步和多步模式的切换,则不推荐使用 MultiStepContainer 或 StepModeContainer 对其进行包装。通常需要用到 MultiStepContainer 或 StepModeContainer 的是一些没有定义多步的模块,例如一个在 torch.nn 中存在,但在 spikingjelly.activation_based.layer 中不存在的网络层。

(四)梯度替代

1、梯度替代的意义
直接使用冲激函数进行梯度下降,显然会使得网络的训练及其不稳定。为了解决这一问题,各种梯度替代法(the surrogate gradient method)被相继提出。
2、梯度替代法的原理
在前向传播时使用y =Θ(x),而在反向传播时使用dy/dx=σ’(x),而非dy/dx=Θ’(x),其中σ(x)即为替代函数。 通常是一个形状与Θ(x) 类似,但光滑连续的函数。
spikingjelly.activation_based.surrogate 中提供了一些常用的替代函数,其中Sigmoid函数为spikingjelly.activation_based.surrogate.Sigmoid

import torch
from spikingjelly.activation_based import surrogate

sg = surrogate.Sigmoid(alpha=4.)

x = torch.rand([8]) - 0.5
x.requires_grad = True
y = sg(x)
y.sum().backward()
print(f'x={x}')
print(f'y={y}')
print(f'x.grad={x.grad}')

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值