**摘要:**本文围绕脉冲神经网络(SNN)的网络结构设计展开,先回顾LIF神经元的脉冲发放与膜电位更新流程,再依次讲解全连接SNN、卷积SNN和循环SNN三种典型结构:全连接结构直观、组合灵活,但不显式利用局部空间结构且参数量随输入维度增长;卷积SNN保留局部连接与权重共享,同时叠加LIF状态更新,输出随时间变化的脉冲特征图;循环SNN通过反馈权重把历史脉冲重新送入当前层,与神经元自身的膜电位记忆形成两条不同的历史依赖路径。文章最后讨论SNN中使用池化、归一化和残差连接时需要明确的关键问题,包括处理对象、统计维度、变量形式与相加后的脉冲发放规则,强调结构与神经元动态是两个独立的设计维度。
前面我们已经把SNN最基本的运行过程梳理清楚了。
首先,前一层神经元产生脉冲,这些脉冲经过连接权重组合,形成下一层的输入驱动。然后,LIF神经元根据当前输入和历史膜电位更新状态,决定是否发放。
与此同时,网络还会沿着时间连续运行,在多个时间步中保留状态,最后通过一定的解码规则得到输出结果。
但是,到目前为止,我们研究的主要还是基本的计算流程。
接下来就要解决另一个问题:
既然LIF神经元的计算规律已经确定,那么我们能不能通过改变神经元之间的连接方式,让SNN适应不同类型的信息处理任务?
答案是可以的。
今天我们就重点研究三种结构:全连接SNN、卷积SNN和循环SNN。
一、全连接SNN:最直接的脉冲组合方式
这张图大家应该比较熟悉了,左边有三个输入神经元,右边有两个LIF神经元,中间使用连接线把它们连接起来。

大家看这里,分别是S₁、S₂和S₃。
这三个神经元在当前时间步可能产生脉冲,也可能不产生脉冲。
现在再看右侧两个LIF神经元。
大家有没有发现,每个输入神经元都连接到了右边的两个LIF神经元?
比如S₁既连接上面的LIF,也连接下面的LIF。
S₂和S₃也是一样。
这种连接方式,就是我们所说的全连接结构。
在全连接结构中,目标层的每个神经元都可以接收前一层所有神经元的输出。
但是这里有一个问题。
既然两个LIF神经元都接收了同样三个输入,它们得到的结果是不是一定一样?
不一定。
为什么?
因为虽然它们的输入来源相同,但是对应的连接权重可能不同。
所以全连接结构最大的特点是什么?
它允许不同神经元通过不同的权重,对同一组输入进行不同的组合。
第一个,结构直观。
因为连接关系很容易理解,就是前一层的神经元与后一层的神经元进行密集连接。
第二个,组合灵活。
不同的权重可以让不同的目标神经元对输入产生不同的响应。
第三个,不显式利用局部空间结构。
这一点大家需要重点理解。
假设我们现在输入的是一幅图像。
图像中的相邻像素,通常在空间位置上存在一定的关系。
但是普通全连接层并没有在连接形式上明确规定:只处理局部相邻的像素,或者在不同位置复用同一套局部权重。
如果输入维度非常大,密集连接所需要的权重数量也可能随之增加。
例如,假设一个全连接层有1000个输入神经元和500个输出神经元。
如果每个输入都连接到每个输出,那么仅连接权重就有:

这就说明,全连接结构虽然很灵活,但是当输入维度较大时,也可能需要较多连接参数。
因此,全连接SNN非常适合帮助我们理解基本原理,但不一定是所有任务中最合适的结构。
二、卷积SNN:空间特征提取与时间动态结合
在学习卷积SNN之前,大家先回忆一下普通卷积神经网络,也就是CNN。
CNN为什么适合处理图像?
一个很重要的原因,就是它能够利用图像的局部空间结构。
我们举一个简单的例子。
假设有一幅图像,大小是5×5。
现在我们使用一个3×3的卷积核。
这个卷积核会不会在计算一个位置时,把整幅图像所有25个像素都放在一起?
不会。
它主要关注当前卷积窗口覆盖的局部区域。大家看这里。

这个方格代表一个具有空间结构的输入。
假设我们在一个局部位置上进行卷积计算。
卷积核中的不同权重,会与对应位置的输入相乘并求和,得到当前位置的卷积输出。
然后,卷积核会移动到下一个空间位置,继续进行类似的计算。
这里有两个非常重要的概念。
第一个叫局部连接,也就是局部感受野。
第二个叫权重共享。
所谓权重共享,是指同一个卷积核可以在不同的空间位置重复使用,而不必为每一个位置重新设置一套完全独立的卷积核参数。
所以,普通卷积结构能够利用局部空间关系,并逐层提取空间特征。
那么现在的问题是:
当我们把卷积结构引入SNN以后,原来这些卷积特点还保留吗?
是的,仍然可以保留。
卷积SNN同样可以使用局部连接、权重共享和空间层级特征提取的思想。
但是它又增加了什么?

大家看这里。
除了卷积加权,还增加了LIF状态更新。
也就是说,卷积计算产生的结果不是整个神经元计算过程的终点。
它首先形成当前时间步的输入驱动。
然后,脉冲神经元还需要结合上一时间步保留的膜电位,更新自己的内部状态。
接下来再判断是否达到发放阈值。
如果达到阈值,就在对应的位置产生脉冲。
因此,卷积SNN最终可以产生随时间变化的脉冲特征图。
这里大家要注意,我们现在已经不只是处理一幅静态图像了。
如果输入具有多个时间步,那么每一个时间步都可能有不同的输入脉冲分布。
经过卷积加权和LIF状态更新以后,每个时间步得到的输出脉冲特征图也可能不同。
所以,我们可以把卷积SNN理解为:
保留卷积结构利用局部空间关系的能力,同时引入脉冲神经元的时间状态和事件发放机制。
但是千万不要把它简单理解为:
先进行普通卷积,再把结果直接变成0和1,就完成了卷积SNN。
因为真正的脉冲神经元还包含膜电位状态更新,以及跨时间的状态依赖。
卷积负责形成输入驱动,LIF神经元负责在时间上积累状态并产生脉冲。

空间特征与时间活动同时变化

面有三张2×2的脉冲图,分别对应t=1、t=2和t=3。
下面是一张膜电位变化曲线。
我们先只看上面这三张图。
大家注意,这三张图对应的是同一组空间坐标。
空间位置没有变,但是不同时刻的发放活动发生了变化。
这说明什么?
说明卷积SNN的输出特征图,并不是一张固定不变的图。
它的脉冲活动可以随着时间变化。
接下来我们再看下面这张曲线图。
大家先找到阈值1对应的水平线。
然后观察这些曲线。
比如位置2,在第二个时间步的发放前膜电位达到1.25,超过了阈值。
因此,它在第二个时间步会产生脉冲。
而在第三个时间步,位置2对应的发放前膜电位变成了0.2。
大家注意,这些曲线画的是发放前状态。
如果某个位置发放了脉冲,真正留给下一时间步的状态,还要考虑发放后的复位。
所以我们不能把图中某一时刻的发放前膜电位,直接当成下一时刻的保留膜电位。
再来看位置1和位置3。
它们在第三个时间步的发放前膜电位分别达到1和1.15。
都达到了本例采用的阈值1。
因此,第三个时间步可以观察到对应位置的发放。
现在大家再把上面的脉冲图和下面的曲线结合起来看。
上面的脉冲图告诉我们:什么时间、什么空间位置产生了事件。
下面的膜电位曲线则能够帮助我们观察这些位置的内部状态怎样变化。
这两类图表达的信息并不完全相同。
而且这里需要提醒大家,这些曲线和脉冲图是为了说明原理构造的教学示意,不是真实实验记录。
这一页最重要的结论就是:
某一个时间步的脉冲特征图,只是整个时空响应中的一个切片。
如果我们只截取t=2的脉冲图,就无法直接知道t=1和t=3发生了什么。
所以分析卷积SNN时,不仅要看空间特征,还要沿时间观察脉冲活动和状态变化。
到这里,我们已经学习了全连接SNN和卷积SNN。
这两种结构都可以利用LIF神经元的膜电位来保留时间上的影响。
那么新的问题来了:
既然LIF神经元本身已经具有时间记忆,为什么我们还需要一种叫作循环SNN的网络结构呢?
接下来这两页,是今天最需要分清楚的概念。
三、循环SNN:历史脉冲也可以通过网络连接反馈
在讲这个结构之前,我想请大家先回忆一下:
前面我们学习LIF神经元的时候,它是不是已经能够保留历史信息?
是的。
它能够通过膜电位状态,把前一个时间步的影响保留下来。
那现在的问题就是:
既然LIF神经元本身已经有时间记忆,为什么还需要循环连接?
要回答这个问题,我们先看这张图。

左边仍然是输入神经元S₁、S₂和S₃。
它们通过紫色连接线,把脉冲传给右边的LIF神经元。
这部分和我们前面学习的全连接结构很相似。
但是现在大家注意右边。
这里多了一条连接。
这条连接不是来自前面的输入层,而是把历史脉冲活动通过反馈权重重新送入当前层的计算。
这就是循环连接。
我们可以这样理解:
在普通的前馈结构中,当前层主要接收前一层传来的脉冲。
而加入循环连接以后,当前层还可以接收自身或同层其他神经元在过去时间步产生的脉冲。
这样一来,当前层的输入来源就增加了。
以前只需要考虑前一层的输入,现在还需要考虑历史脉冲反馈。
这就和RNN非常相似了
因此,我们可以把当前层的输入驱动表示为:

大家先看第一部分:

这部分我们已经很熟悉了。
它表示前一层当前时间步的脉冲,经过权重W进行加权组合。
再看第二部分:

这里新出现的R,就是循环连接权重。
而 表示当前层上一时间步的脉冲活动。
也就是说,这个部分表示:历史脉冲经过循环权重加权以后,对当前输入产生的影响。
所以,循环SNN相比普通前馈SNN,多了一条历史活动反馈路径。
举个简单的例子。
假设一个神经元在t=2时,来自前一层的当前输入是0.3。
如果上一时间步有一个反馈脉冲,其反馈权重是0.5,那么它还可能获得0.5的循环输入。
这样,当前输入驱动就变成:

大家注意,我现在讲的是输入驱动。
我们还没有计算LIF神经元的完整膜电位。
为什么?
因为接下来还要考虑这个神经元上一时间步保留下来的膜电位状态。
大家看,图下面还专门写着'膜状态也沿时间保留'。
这就说明,循环SNN里实际上可能同时存在两种历史影响。
第一种,来自神经元自身的膜电位状态。
第二种,来自网络连接反馈的历史脉冲。
它们都能让过去影响现在,但它们的作用路径不同。
所以我们不要因为两者都涉及历史信息,就把它们理解成同一件事。
刚才我们已经看到,循环连接确实增加了一条历史信息反馈路径。
但这一点比较容易和LIF神经元原本就具有的膜电位记忆混淆。
所以接下来,我们把这两种机制单独拿出来比较。

我们先看左边。
这里画了一个LIF神经元。
它前面有一个框,写着'上一时刻膜电位'。
这代表什么?
代表我们在更新当前膜电位时,需要读取这个神经元上一时间步保留下来的状态。
我们可以把它理解成:这个神经元在过去接收输入后,已经积累了一定的膜电位,而这部分状态会影响它下一时刻的响应。
例如,上一时间步留下了0.8的膜电位。
如果保留系数是0.5,那么下一时间步就会保留0.4的历史贡献。
大家注意,这里没有要求另一个神经元把脉冲传回来。
我们读取的是神经元自身已经保存下来的膜电位状态。
所以,这属于神经元内部的时间动态。
接下来,再看右边。
这里画了两个LIF神经元,而且它们之间存在紫色的反馈连接。
这条连接和刚才的内部状态保留有什么区别?
区别就在于:
这里传递的是历史脉冲活动。
比如,某个神经元在上一个时间步产生了一个脉冲。
这个脉冲可以通过循环连接,影响当前层另一个神经元的输入驱动。
请大家特别注意这里的变量。
左边内部状态记忆,读取的是上一时间步的膜电位V。
右边循环活动反馈,读取的是上一时间步的脉冲S。
这两个变量本来就不是同一个东西。
而且,历史脉冲还需要经过循环权重R,才能参与当前计算。
现在我们用一个具体的情境比较一下。
假设有两个LIF神经元,分别叫A和B。
在第一个时间步,A神经元接收到输入,膜电位升高,但是没有达到阈值。
那么到了第二个时间步,A可以继续利用自己之前保留下来的膜电位。
这就是内部状态记忆。
再假设A在第一个时间步产生了一个脉冲。
如果网络结构中存在从A到B的循环连接,那么A之前产生的脉冲,就可以在后续时间步通过连接权重影响B的输入。
这就属于显式循环活动反馈。
大家看,虽然这两种机制都能体现历史依赖,但历史信息的形式不同,传递路径也不同。
所以我们得到一个重要结论:
LIF神经元具有内部状态记忆,并不意味着它所在的网络就一定具有显式循环连接。
反过来,一个循环SNN也可以同时利用这两种机制。
这就是我们为什么不能简单地把'神经元本身有记忆'和'网络具有循环结构'画上等号。
四、SNN中使用池化、归一化和残差连接,需要注意什么?
大家看这一页。
如果大家以前学习过CNN,应该知道池化操作。
比如最大池化,就是在一个局部区域中取最大值。
但是现在我们研究的是SNN。
如果有人告诉你:
'这个SNN里面使用了最大池化。'
那么我希望大家不要直接认为自己已经完全理解了这个操作。
为什么?
因为在SNN里面,我们首先需要知道:
被池化的数据究竟是什么?

第一种,单个时间步的脉冲图。
这里是一个2×2的区域,每个位置表示当前时间步有没有发放脉冲。
如果采用二值脉冲表示,那么每个位置的值就是0或者1。
在这种情况下,如果对这个2×2区域使用最大池化,得到的结果是什么意思?
它可以表示:这个区域在当前时间步里,是否至少有一个位置产生了脉冲。
如果四个位置都是0,那么最大值就是0。
只要其中存在一个1,最大值就是1。
所以,此时最大池化处理的是当前时刻的离散脉冲事件。
接下来我们看第二种情况。
这里有四个数,分别是2、4、1、3。
大家注意,它们已经不是当前时间步的二值脉冲了。
这里表示的是一段时间内的活动统计。
例如,它们可以表示四个空间位置在某个观察窗口中的脉冲累计次数。
那如果现在使用最大池化,得到什么?
得到4。
但这个4与刚才的1,在信息含义上完全一样吗?
当然不一样。
刚才的1表示当前时间步存在脉冲事件。
现在的4表示在某段观察窗口中,有一个空间位置累计了4次发放。
虽然都叫最大池化,但处理对象不同,它们表达的时间信息就不同。
再看第三种情况。
这里有四个连续数值:0.2、0.8、0.3、0.4。
假设它们代表某一时刻或某个读出阶段的连续膜电位值。
那么最大池化得到的是0.8。
这里输出的就不是一个二值脉冲事件,也不是一段时间的脉冲计数,而是连续状态中的最大值。
所以大家会发现:
池化算法的名字可能一样,但如果输入的数据形式不同,它所处理的信息就可能完全不同。
我们在介绍一个SNN池化模块时,不能只写'使用最大池化'就结束了。
还需要明确:它是在每个时间步的脉冲图上进行池化,还是对一段时间的活动统计进行池化,或者是对膜电位等连续状态进行池化。
另外,池化以后得到的输出是否还保持二值脉冲形式,以及后续是否还需要经过脉冲神经元,也需要根据具体设计说明。
所以,在SNN中使用池化之前,首先要明确处理对象。
池化需要明确处理对象,其实归一化也有类似的问题。
尤其是SNN的数据往往具有时间维度,那么我们在做归一化时,到底应该沿哪个维度进行统计呢?
在普通深度神经网络中,大家可能已经接触过Batch Normalization等归一化方法。
它们通常会涉及数据统计和数值变换。
但是把这类方法应用到SNN中时,我们需要多考虑一些事情。

大家看这里写着T、C、H、W。
这些符号我们前面已经介绍过。
T表示时间维度。
C表示通道维度。
H和W表示空间高度和宽度。
现在假设我们有一个具有多个时间步的脉冲特征图。
如果需要对其中的数据进行归一化,首先就要明确我们准备使用哪些维度上的统计信息。
比如第一个问题:
是否跨时间?
大家想一想,如果t=1的脉冲活动比较少,而t=3的脉冲活动比较多,那么我们是把不同时间步的数据放在一起统计,还是分别处理?
这两种选择的含义可能不同。
所以不能不加说明地把时间维度和空间维度混在一起。
第二个问题,归一化操作会不会改变神经元接收到的输入驱动,从而影响膜电位的分布?
大家前面已经知道,神经元是否发放,与膜电位和阈值之间的关系有关。
如果归一化改变了参与膜电位更新的数值,就可能影响后面的阈值判断与脉冲活动。
所以我们需要考虑它与神经元状态更新之间的关系。
第三个问题,是否影响脉冲表示?
比如原来的输入是0和1这样的离散事件。
如果经过某种连续数值变换,输出变成了其他实数,那么它还能不能直接被解释为同一形式的二值脉冲?
不能不加分析就这样认为。
我们必须明确归一化作用在什么位置、作用于什么变量,以及后续怎样处理这些数值。
第四个问题,训练和推理阶段采用的统计方式是否一致?
如果一个模型训练时采用某种统计规则,而推理时使用另一种规则,就需要检查这种差异是不是符合模型原本的设计。
刚才我们讨论的是归一化。
接下来再看一种大家比较熟悉的结构------残差连接。
残差连接在普通深度神经网络中应用广泛,但在SNN里面也存在一个需要特别注意的问题:两条路径上的信息,究竟能不能直接相加?

我们先看输入。
输入进入主路径以后,首先经过加权计算。
然后再经过状态更新与脉冲发放。
大家注意,到绿色这里,主路径可能已经输出了一组脉冲事件。
但是旁边还有一条绕过部分计算过程的残差路径。
现在这两条路径要在这里进行组合。
那么问题就来了:
它们能够直接相加吗?
我们先不要急着回答。
首先要问,两条路径上的变量是不是同一种形式。
假设主路径输出的是0和1这样的脉冲。
而残差路径传递的是连续膜电位。
那么这两个量虽然在数学上可能具有可以运算的数值形式,但能不能直接相加、相加以后代表什么,都需要明确说明。
另外,即使两条路径上都是二值脉冲,也不意味着相加之后仍然一定是二值脉冲。
第一,相加的是哪种变量?
是脉冲、膜电位,还是其他连续激活值?
第二,两条路径的状态是否匹配?
如果两条路径都涉及内部状态,那么状态的定义和使用方式是否明确?
第三,相加之后是否还要经过脉冲神经元?
如果需要,那么新的输入又将怎样参与状态更新和发放判断?
第四,网络活动水平是否改变?
例如,相加过程是否改变输入驱动的数值大小,从而影响后续神经元的发放情况?
这些问题,都需要结合具体网络结构进行分析。
所以,这一页我们并不是要详细学习某一种特定的ResNet结构。
真正需要建立的是一个设计意识:
SNN中的残差连接不能只画一个加号,而不说明相加对象、状态关系以及后续的脉冲发放规则。
总结:结构和神经元动态是两个不同的设计维度
这里把我们今天学习的三种主要结构放在了一起。
分别是全连接SNN、卷积SNN和循环SNN。
先看全连接SNN。
它的主要特点是什么?
前一层多个神经元的输出,可以通过密集连接与下一层的神经元进行组合。
所以它主要提供一种比较通用的特征组合方式。
再看卷积SNN。
它有什么特点?
它使用局部空间连接,并且可以在不同空间位置共享卷积核权重。
这样就能够利用图像或空间特征图中的局部关系,逐层形成空间特征。
最后看循环SNN。
它和前面两种结构有什么不同?
它额外引入了历史脉冲活动通过连接反馈的路径。
因此,当前层的输入不仅可以来自前一层的当前脉冲,还可以受到过去脉冲活动的影响。
