SNN反向传播方式到底是怎样的?
一、反向传播的基本原理
反向传播(Backpropagation, BP)是一种用于训练神经网络的技术。它通过链式法则
计算损失函数相对于每个参数的梯度,从而进行参数更新。
基本概念
反向传播是一种优化算法,用于通过计算梯度来最小化神经网络的损失函数。反向传播的核心思想是使用链式法则来计算损失函数相对于每个网络参数的梯度,从而更新参数以减少损失。
什么是链式法则?
链式法则(Chain Rule)是微积分中的一个重要法则,用于计算复合函数的导数。它告诉我们,如果一个函数 f f f 可以表示为另一个函数 g g g 的复合,即 f ( g ( x ) ) f(g(x)) f(g(x)) ,那么 f f f 对 x x x 的导数可以分解为 f f f 对 g g g 的导数乘以 g g g 对 x x x 的导数。
数学上,链式法则可以表示为:
d d x f ( g ( x ) ) = f ′ ( g ( x ) ) ⋅ g ′ ( x ) \frac{d}{dx} f(g(x)) = f'(g(x)) \cdot g'(x) dxdf(g(x))=f′(g(x))⋅g′(x)
反向传播的过程
假设我们有一个简单的两层神经网络:
- 输入层: x x x
- 隐藏层: h = f ( W x + b ) h = f(Wx + b) h=f(Wx+b) ,其中 W W W 是权重矩阵, b b b 是偏置, f f f 是激活函数。
- 输出层: y ^ = g ( V h + c ) \hat{y} = g(Vh + c) y^=g(Vh+c) ,其中 V V V 是权重矩阵, c c c 是偏置, g g g 是激活函数。
目标是通过最小化损失函数 L ( y ^ , y ) L(\hat{y}, y) L(y^,y) 来训练网络,其中 y y y 是真实标签。
反向传播步骤
前向传播(Forward Propagation):
- 计算隐藏层输出: h = f ( W x + b ) h = f(Wx + b) h=f(Wx+b)
- 计算最终输出: y ^ = g ( V h + c ) \hat{y} = g(Vh + c) y^=g(Vh+c)
计算损失(Loss Calculation):
- 损失函数: L ( y ^ , y ) L(\hat{y}, y) L(y^,y)
反向传播(Backward Propagation):
- 目标:计算损失函数 L L L 相对于所有参数 W , b , V , c W, b, V, c W,b,V,c 的梯度。
举例:具体计算梯度
假设激活函数 f f f 和 g g g 都是简单的线性函数(即 f ( x ) = x f(x) = x f(x)=x 和 g ( x ) = x g(x) = x g(x)=x ),损失函数为均方误差(MSE):
L ( y ^ , y ) = 1 2 ( y ^ − y ) 2 L(\hat{y}, y) = \frac{1}{2} (\hat{y} - y)^2 L(y^,y)=21(y^−y)2
1. 前向传播:
h = W x + b h = Wx + b h=Wx+b
y ^ = V h + c \hat{y} = Vh + c y^=Vh+c
2. 计算损失:
L ( y ^ , y ) = 1 2 ( y ^ − y ) 2 L(\hat{y}, y) = \frac{1}{2} (\hat{y} - y)^2 L(y^,y)=21(y^−y)2
3. 反向传播:
Step 1: 计算输出层的梯度
对输出层的输出 y ^ \hat{y} y^ 求导:
∂ L ∂ y ^ = y ^ − y \frac{\partial L}{\partial \hat{y}} = \hat{y} - y ∂y^∂L=y^−y
对 V V V 和 c c c 求导:
∂ L ∂ V = ∂ L ∂ y ^ ⋅ ∂ y ^ ∂ V = ( y ^ − y ) ⋅ h \frac{\partial L}{\partial V} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial V} = (\hat{y} - y) \cdot h ∂V∂L=∂y^∂L⋅∂V∂y^=(y^−y)⋅h
∂ L ∂ c = ∂ L ∂ y ^ ⋅ ∂ y ^ ∂ c = ( y ^ − y ) ⋅ 1 = ( y ^ − y ) \frac{\partial L}{\partial c} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial c} = (\hat{y} - y) \cdot 1 = (\hat{y} - y) ∂c∂L=∂y^∂L⋅∂c∂y^=(y^−y)⋅1=(y^−y)
Step 2: 计算隐藏层的梯度
对隐藏层的输出 ( h ) 求导:
∂ L ∂ h = ∂ L ∂ y ^ ⋅ ∂ y ^ ∂ h = ( y ^ − y ) ⋅ V \frac{\partial L}{\partial h} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial h} = (\hat{y} - y) \cdot V ∂h∂L=∂y^∂L⋅∂h∂y^=(y^−y)⋅V
对 W W W 和 b b b 求导:
∂ L ∂ W = ∂ L ∂ h ⋅ ∂ h ∂ W = ( ( y ^ − y ) ⋅ V ) ⋅ x \frac{\partial L}{\partial W} = \frac{\partial L}{\partial h} \cdot \frac{\partial h}{\partial W} = ((\hat{y} - y) \cdot V) \cdot x ∂W∂L=∂h∂L⋅∂W∂h=((y^−y)⋅V)⋅x
∂ L ∂ b = ∂ L ∂ h ⋅ ∂ h ∂ b = ( y ^ − y ) ⋅ V \frac{\partial L}{\partial b} = \frac{\partial L}{\partial h} \cdot \frac{\partial h}{\partial b} = (\hat{y} - y) \cdot V ∂b∂L=∂h∂L⋅∂b∂h=(y^−y)⋅V
为什么要求导?
求导(计算梯度)是为了直到损失函数L对每个参数的敏感度
。具体来说,梯度告诉我们如果稍微调整一个参数 θ \theta θ,损失L会如何变化。
通过知道这个变化的方向和大小,我们可以调整参数,使得损失函数变小,这也就是优化模型的过程。
对于神经网络来说,输出层的梯度计算是反向传播的起点,因为输出层直接影响损失函数。我们需要知道损失函数对输出层输出的影响,以便逐层传播回去,调整每一层的参数
更新参数:
使用梯度下降法
更新参数:
W ← W − η ∂ L ∂ W W \leftarrow W - \eta \frac{\partial L}{\partial W} W←W−η∂W∂L
b ← b − η ∂ L ∂ b b \leftarrow b - \eta \frac{\partial L}{\partial b} b←b−η∂b∂L
V ← V − η ∂ L ∂ V V \leftarrow V - \eta \frac{\partial L}{\partial V} V←V−η∂V∂L
c ← c − η ∂ L ∂ c c \leftarrow c - \eta \frac{\partial L}{\partial c} c←c−η∂c∂L
其中, η \eta η 是学习率。
为什么可以使用梯度下降法更新?原理是什么?
梯度下降法是一种优化算法,用于最小化目标函数(在这里是损失函数)。它的基本思想是 沿着目标函数梯度的负方向更新参数 ,因为梯度指示了函数增大的最快方向,而我们希望减少损失函数的值。
具体来说,梯度下降法的更新规则是:
θ ← θ − η ∂ L ∂ θ \theta \leftarrow \theta - \eta \frac{\partial L}{\partial \theta} θ←θ−η∂θ∂L
其中:
- θ \theta θ 是需要更新的参数
- η \eta η 是学习率,控制每次更新的步长
- ∂ L ∂ θ \frac{\partial L}{\partial \theta} ∂θ∂L 是损失函数对参数 θ \theta θ 的梯度
梯度下降法的原理基于以下几点:
- 梯度的方向性:梯度指示了函数增大的方向。为了最小化损失函数,我们沿着梯度的负方向更新参数。
- 迭代更新:通过多次迭代更新参数,逐步逼近损失函数的局部最小值。
- 学习率控制:学习率决定了每次更新的步长。如果步长太大,可能会错过最优点;如果步长太小,收敛速度会很慢。
通过反向传播计算出每个参数的梯度后,我们使用梯度下降法来更新这些参数,使得损失函数逐步减小,从而训练出一个性能更好的模型。
如何理解“梯度指示了函数增大的方向”?
梯度是函数在某一点的导数向量
,表示该点在各个方向上的 变化率 。在一个多维空间中, 梯度向量的方向指向函数值增长最快的方向 。我们来举个简单的二维例子来帮助理解。
假设我们有一个二维函数 f ( x , y ) f(x, y) f(x,y) ,在某个点 ( x 0 , y 0 ) (x_0, y_0) (x0,y0) ,函数值为 f ( x 0 , y 0 ) f(x_0, y_0) f(x0,y0) 。如果我们在该点计算梯度 ∇ f ( x 0 , y 0 ) \nabla f(x_0, y_0) ∇f(x0,y0) ,得到的梯度向量可能是 ( ∂ f / ∂ x , ∂ f / ∂ y ) (\partial f / \partial x, \partial f / \partial y) (∂f/∂x,∂f/∂y)。
这个梯度向量表示在 ( x 0 , y 0 ) (x_0, y_0) (x0,y0) 点,函数 f f f 在 x x x 和 y y y 方向上的变化率。梯度的方向就是函数值增加最快的方向,即如果我们沿着梯度的方向移动,函数值会迅速增大。
为了最小化函数值,我们需要沿着梯度的反方向(即梯度的负方向)移动,因为这会使函数值减小。这就是梯度下降法的基本原理。
为什么梯度的方向是函数值增加最快的方向?
1. 梯度的直观理解
我们先从二维空间中的一个简单例子开始,假设我们有一个函数 f ( x , y ) f(x, y) f(x,y) ,其图像是一个地形图,表示一个山的高度。梯度 ∇ f ( x , y ) \nabla f(x, y) ∇f(x,y) 在某点 ( x 0 , y 0 ) (x_0, y_0) (x0,y0) 处的方向和大小,表示在该点处函数值变化最快的方向和变化的速度。
2. 梯度的定义
在多维空间中,函数 f f f 的梯度 ∇ f \nabla f ∇f 是一个向量,其每个分量是函数在该方向上的偏导数
:
∇ f = ( ∂ f ∂ x 1 , ∂ f ∂ x 2 , … , ∂ f ∂ x n ) \nabla f = \left( \frac{\partial f}{\partial x_1}, \frac{\partial f}{\partial x_2}, \ldots, \frac{\partial f}{\partial x_n} \right) ∇f=(∂x1∂f,∂x2∂f,…,∂xn∂f)
这个向量在点 ( x 0 , y 0 ) (x_0, y_0) (x0,y0) 处的方向,就是 函数值增加最快的方向 。
3. 具体的例子
考虑一个简单的函数 f ( x , y ) = x 2 + y 2 f(x, y) = x^2 + y^2 f(x,y)=x2+y2 ,其梯度是:
∇ f ( x , y ) = ( ∂ f ∂ x , ∂ f ∂ y ) = ( 2 x , 2 y ) \nabla f(x, y) = \left( \frac{\partial f}{\partial x}, \frac{\partial f}{\partial y} \right) = (2x, 2y) ∇f(x,y)=(∂x∂f,∂y∂f)=(2x,2y)
4. 在点 (1, 1) 处的梯度
假设我们在点 ( (1, 1) ) 处,那么梯度就是:
∇ f ( 1 , 1 ) = ( 2 ⋅ 1 , 2 ⋅ 1 ) = ( 2 , 2 ) \nabla f(1, 1) = (2 \cdot 1, 2 \cdot 1) = (2, 2) ∇f(1,1)=(2⋅1,2⋅1)=(2,2)
这个梯度向量 ( 2 , 2 ) (2, 2) (2,2) 指向坐标轴的第一个象限,并且指示了函数 f ( x , y ) f(x, y) f(x,y) 在这个点处增加最快的方向。
5. 梯度的几何解释
如果我们在点 ( 1 , 1 ) (1, 1) (1,1) 沿着梯度方向 ( 2 , 2 ) (2, 2) (2,2) 移动,函数值会迅速增加。具体来说,如果我们沿着梯度的方向小步移动 Δ s \Delta s Δs ,新点的坐标为 ( 1 + Δ s ⋅ 2 , 1 + Δ s ⋅ 2 ) (1 + \Delta s \cdot 2, 1 + \Delta s \cdot 2) (1+Δs⋅2,1+Δs⋅2) 。
6. 数学证明
要证明梯度是函数值增加最快的方向,可以从以下角度考虑:
我们在 ( x 0 , y 0 ) (x_0, y_0) (x0,y0) 点沿着一个单位向量 u \mathbf{u} u 的方向移动一小步 Δ s \Delta s Δs ,那么函数值的变化量为:
Δ f = f ( x 0 + Δ s ⋅ u x , y 0 + Δ s ⋅ u y ) − f ( x 0 , y 0 ) \Delta f = f(x_0 + \Delta s \cdot u_x, y_0 + \Delta s \cdot u_y) - f(x_0, y_0) Δf=f(x0+Δs⋅ux,y0+Δs⋅uy)−f(x0,y0)
在 ( x 0 , y 0 ) (x_0, y_0) (x0,y0) 点附近,我们可以使用泰勒展开来近似表示函数 f ( x , y ) f(x, y) f(x,y) 的变化。泰勒展开的一阶近似形式为:
f ( x 0 + Δ x , y 0 + Δ y ) ≈ f ( x 0 , y 0 ) + ∂ f ∂ x Δ x + ∂ f ∂ y Δ y f(x_0 + \Delta x, y_0 + \Delta y) \approx f(x_0, y_0) + \frac{\partial f}{\partial x} \Delta x + \frac{\partial f}{\partial y} \Delta y f(x0+Δx,y0+Δy)≈f(x0,y0)+∂x∂fΔx+∂y∂fΔy
泰勒展开是一种用于近似表示函数在某点附近的值的方法。它将一个函数表示为无穷阶导数的级数。泰勒展开的一阶近似形式如下:
f ( x 0 + Δ x ) ≈ f ( x 0 ) + d f d x ( x 0 ) Δ x f(x_0 + \Delta x) \approx f(x_0) + \frac{df}{dx}(x_0) \Delta x f(x0+Δx)≈f(x0)+dxdf(x0)Δx其中, f ( x 0 ) f(x_0) f(x0) 是函数 f ( x ) f(x) f(x) 在点 x 0 x_0 x0 处的值, d f d x ( x 0 ) \frac{df}{dx}(x_0) dxdf(x0) 是函数 f ( x ) f(x) f(x) 在点 x 0 x_0 x0 处的导数。
对于二元函数 f ( x , y ) f(x, y) f(x,y),泰勒展开可以表示为:
f ( x 0 + Δ x , y 0 + Δ y ) ≈ f ( x 0 , y 0 ) + ∂ f ∂ x ( x 0 , y 0 ) Δ x + ∂ f ∂ y ( x 0 , y 0 ) Δ y f(x_0 + \Delta x, y_0 + \Delta y) \approx f(x_0, y_0) + \frac{\partial f}{\partial x}(x_0, y_0) \Delta x + \frac{\partial f}{\partial y}(x_0, y_0) \Delta y f(x0+Δx,y0+Δy)≈f(x0,y0)+∂x∂f(x0,y0)Δx+∂y∂f(x0,y0)Δy
这里, ∂ f ∂ x ( x 0 , y 0 ) \frac{\partial f}{\partial x}(x_0, y_0) ∂x∂f(x0,y0) 和 ∂ f ∂ y ( x 0 , y 0 ) \frac{\partial f}{\partial y}(x_0, y_0) ∂y∂f(x0,y0) 分别表示函数 f ( x , y ) f(x, y) f(x,y) 在点 ( x 0 , y 0 ) (x_0, y_0) (x0,y0) 处的偏导数。
对于给定的步长 Δ x \Delta x Δx 和 Δ y \Delta y Δy ,可以使用泰勒展开来近似计算函数值的变化 Δ f \Delta f Δf 。
将 Δ x = Δ s ⋅ u x \Delta x = \Delta s \cdot u_x Δx=Δs⋅ux 和 Δ y = Δ s ⋅ u y \Delta y = \Delta s \cdot u_y Δy=Δs⋅uy 代入上式,得到:
f ( x 0 + Δ s ⋅ u x , y 0 + Δ s ⋅ u y ) ≈ f ( x 0 , y 0 ) + ∂ f ∂ x ( Δ s ⋅ u x ) + ∂ f ∂ y ( Δ s ⋅ u y ) f(x_0 + \Delta s \cdot u_x, y_0 + \Delta s \cdot u_y) \approx f(x_0, y_0) + \frac{\partial f}{\partial x} (\Delta s \cdot u_x) + \frac{\partial f}{\partial y} (\Delta s \cdot u_y) f(x0+Δs⋅ux,y0+Δs⋅uy)≈f(x0,y0)+∂x∂f(Δs⋅ux)+∂y∂f(Δs⋅uy)
进一步整理可得:
f ( x 0 + Δ s ⋅ u x , y 0 + Δ s ⋅ u y ) ≈ f ( x 0 , y 0 ) + ∂ f ∂ x u x Δ s + ∂ f ∂ y u y Δ s f(x_0 + \Delta s \cdot u_x, y_0 + \Delta s \cdot u_y) \approx f(x_0, y_0) + \frac{\partial f}{\partial x} u_x \Delta s + \frac{\partial f}{\partial y} u_y \Delta s f(x0+Δs⋅ux,y0+Δs⋅uy)≈f(x0,y0)+∂x∂fuxΔs+∂y∂fuyΔs
由于 ∇ f = ( ∂ f ∂ x , ∂ f ∂ y ) \nabla f = \left( \frac{\partial f}{\partial x}, \frac{\partial f}{\partial y} \right) ∇f=(∂x∂f,∂y∂f) ,可以将上式改写为:
f ( x 0 + Δ s ⋅ u x , y 0 + Δ s ⋅ u y ) ≈ f ( x 0 , y 0 ) + ∇ f ⋅ u ⋅ Δ s f(x_0 + \Delta s \cdot u_x, y_0 + \Delta s \cdot u_y) \approx f(x_0, y_0) + \nabla f \cdot \mathbf{u} \cdot \Delta s f(x0+Δs⋅ux,y0+Δs⋅uy)≈f(x0,y0)+∇f⋅u⋅Δs
为了最大化 Δ f \Delta f Δf ,我们需要最大化 ∇ f ( x 0 , y 0 ) ⋅ u \nabla f(x_0, y_0) \cdot \mathbf{u} ∇f(x0,y0)⋅u 。由于 u \mathbf{u} u 是单位向量,其模为1,最大化点积意味着 u \mathbf{u} u 必须与 ∇ f ( x 0 , y 0 ) \nabla f(x_0, y_0) ∇f(x0,y0) 同向。因此,梯度的方向就是函数值增加最快的方向。
7. 反向传播和梯度的关系
在反向传播中,我们利用梯度信息来更新模型的参数。通过计算损失函数相对于每个参数的梯度,我们知道每个参数变化的方向和大小,从而调整参数使损失函数减小。具体步骤如下:
- 计算损失函数的梯度:反向传播计算每个参数的梯度。
- 沿梯度的反方向更新参数:为了最小化损失函数,我们沿梯度的反方向移动参数。
这样,我们就逐步调整模型,使其性能越来越好。
二、反向传播通过时间(Backpropagation Through Time, BPTT)
BPTT 是将反向传播扩展到处理时间序列数据
的方法。对于 SNN 来说,神经元的状态依赖于之前的状态(即时间步的依赖),需要将误差从输出层逐时间步地传播回输入层。
SNN的状态更新方程
首先,SNN的状态更新方程:
U [ t ] = β U [ t − 1 ] + I [ t ] − θ S [ t − 1 ] U[t] = \beta U[t-1] + I[t] - \theta S[t-1] U[t]=βU[t−1]+I[t]−θS[t−1]
其中:
- U [ t ] U[t] U[t] 是在时间步 t t t 的膜电位(membrane potential)。
- β \beta β 是衰减因子(通常小于1)。
- I [ t ] I[t] I[t] 是在时间步 ( t ) 的输入电流。
- θ \theta θ 是阈值电位(threshold potential)。
- S [ t − 1 ] S[t-1] S[t−1] 是在时间步 ( t-1 ) 的脉冲发射(spike)。
梯度计算
我们将逐步计算损失函数对权重的梯度。假设在时间步 T T T 计算损失函数 L [ T ] L[T] L[T] 。
1. 损失函数对膜电位的梯度
∂ L ∂ U [ t ] = ∂ L [ T ] ∂ U [ t ] ( T 是终止时间步 ) \frac{\partial L}{\partial U[t]} = \frac{\partial L[T]}{\partial U[t]} \quad (\text{T 是终止时间步}) ∂U[t]∂L=∂U[t]∂L[T](T 是终止时间步)
这一步表示我们需要知道在每个时间步 t t t 上,损失函数 L [ T ] L[T] L[T] 对膜电位 U [ t ] U[t] U[t] 的敏感度。
2. 膜电位对权重的梯度
接下来,我们需要计算膜电位 U [ t ] U[t] U[t] 对权重 w w w 的梯度:
∂ U [ t ] ∂ w = ∑ k = 0 t ∂ U [ t ] ∂ U [ k ] ∂ U [ k ] ∂ w \frac{\partial U[t]}{\partial w} = \sum_{k=0}^{t} \frac{\partial U[t]}{\partial U[k]} \frac{\partial U[k]}{\partial w} ∂w∂U[t]=k=0∑t∂U[k]∂U[t]∂w∂U[k]
根据状态更新方程:
∂ U [ t ] ∂ U [ k ] = { β t − k if k < t 1 if k = t 0 if k > t \frac{\partial U[t]}{\partial U[k]} = \begin{cases} \beta^{t-k} & \text{if } k < t \\ 1 & \text{if } k = t \\ 0 & \text{if } k > t \end{cases} ∂U[k]∂U[t]=⎩ ⎨ ⎧βt−k10if k<tif k=tif k>t
这意味着如果 k < t k < t k<t , U [ k ] U[k] U[k] 对 U [ t ] U[t] U[t] 的影响会以 β t − k \beta^{t-k} βt−k 的形式衰减;如果 k = t k = t k=t ,梯度是1;如果 k > t k > t k>t ,梯度是0。
3. 总梯度
结合上面的梯度,我们可以得到损失函数对权重的总梯度:
∂ L ∂ w = ∑ t = 0 T ∂ L [ T ] ∂ U [ t ] ∂ U [ t ] ∂ w = ∑ t = 0 T ∂ L [ T ] ∂ U [ t ] ( ∑ k = 0 t β t − k ∂ U [ k ] ∂ w ) \frac{\partial L}{\partial w} = \sum_{t=0}^{T} \frac{\partial L[T]}{\partial U[t]} \frac{\partial U[t]}{\partial w} = \sum_{t=0}^{T} \frac{\partial L[T]}{\partial U[t]} \left( \sum_{k=0}^{t} \beta^{t-k} \frac{\partial U[k]}{\partial w} \right) ∂w∂L=t=0∑T∂U[t]∂L[T]∂w∂U[t]=t=0∑T∂U[t]∂L[T](k=0∑tβt−k∂w∂U[k])
这个公式表示在每个时间步 t t t ,我们需要计算损失函数 L [ T ] L[T] L[T] 对膜电位 U [ t ] U[t] U[t] 的梯度,然后将其乘以膜电位 U [ t ] U[t] U[t] 对权重 w w w 的梯度,并对所有时间步进行求和。
梯度消失问题
这里的关键在于理解梯度会随着时间步的增加呈指数级衰减
,这导致了所谓的梯度消失问题。具体地说,当 β \beta β 是一个小于1的数时, β t − k \beta^{t-k} βt−k 会随着 t t t 和 k k k 之间的差距增大而快速减小,这使得早期时间步的信息在后期时间步中逐渐消失。
三、近似梯度(Surrogate Gradients)
在脉冲神经网络(SNN)中,通过
近似梯度
的方法实现反向传播,其实质就是在无法直接对脉冲(spike)进行微分
的情况下,引入连续且可微的近似函数,来替代原本不可微的脉冲函数。这样就可以使用反向传播算法来计算梯度,并更新权重。
1. 脉冲神经网络中的问题
在SNN中,神经元的激活是通过脉冲(spike)实现的,而脉冲函数是非连续的,通常表示为Heaviside阶跃函数 H H H ,形式如下:
S ( U ) = H ( U − θ ) S(U) = H(U - \theta) S(U)=H(U−θ)
其中 U U U 是膜电位, θ \theta θ 是阈值电位。Heaviside函数的定义是:
H ( x ) = { 0 if x < 0 1 if x ≥ 0 H(x) = \begin{cases} 0 & \text{if } x < 0 \\ 1 & \text{if } x \geq 0 \end{cases} H(x)={01if x<0if x≥0
这个函数在 x = θ x = \theta x=θ 处不连续,其导数在大部分区域为0,导致无法直接使用反向传播算法来计算梯度。
2. 近似梯度(Surrogate Gradients)方法
为了使得梯度计算可行,我们引入了一个连续且可微的近似函数 S ^ ( U ) \hat{S}(U) S^(U) 。常用的近似函数是sigmoid函数,形式为:
S ^ ( U ) = σ ( U − θ ) = 1 1 + e − ( U − θ ) \hat{S}(U) = \sigma(U - \theta) = \frac{1}{1 + e^{-(U - \theta)}} S^(U)=σ(U−θ)=1+e−(U−θ)1
这种近似函数在整个区域都是连续且可微的,因此可以使用其导数来替代脉冲函数的导数。
3. 近似梯度的计算
为了计算近似函数的梯度,我们需要求其导数:
∂ S ^ ( U ) ∂ U = σ ′ ( U − θ ) = σ ( U − θ ) ( 1 − σ ( U − θ ) ) \frac{\partial \hat{S}(U)}{\partial U} = \sigma'(U - \theta) = \sigma(U - \theta)(1 - \sigma(U - \theta)) ∂U∂S^(U)=σ′(U−θ)=σ(U−θ)(1−σ(U−θ))
当我们要求解 ∂ S ^ ( U ) ∂ U \frac{\partial \hat{S}(U)}{\partial U} ∂U∂S^(U) 时,其中 S ^ ( U ) \hat{S}(U) S^(U) 是 sigmoid 函数,其表达式为 σ ( U − θ ) \sigma(U - \theta) σ(U−θ), σ ( x ) \sigma(x) σ(x) 是 sigmoid 函数, θ \theta θ 是阈值。我们可以按照链式法则来计算导数。
首先,我们回顾一下 sigmoid 函数的定义:
σ ( x ) = 1 1 + e − x \sigma(x) = \frac{1}{1 + e^{-x}} σ(x)=1+e−x1
现在,我们要计算 ∂ S ^ ( U ) ∂ U \frac{\partial \hat{S}(U)}{\partial U} ∂U∂S^(U):
- 首先,我们将 S ^ ( U ) \hat{S}(U) S^(U) 展开,即 S ^ ( U ) = σ ( U − θ ) \hat{S}(U) = \sigma(U - \theta) S^(U)=σ(U−θ)。
- 对 σ ( U − θ ) \sigma(U - \theta) σ(U−θ) 求导,使用链式法则,即先对 σ ( x ) \sigma(x) σ(x) 求导,再对 x = U − θ x = U - \theta x=U−θ 求导:
首先,对 σ ( x ) \sigma(x) σ(x) 求导:
d d x σ ( x ) = d d x ( 1 1 + e − x ) = e − x ( 1 + e − x ) 2 = 1 1 + e − x ⋅ e − x 1 + e − x = σ ( x ) ⋅ ( 1 − σ ( x ) ) \begin{aligned} \frac{d}{dx}\sigma(x) &= \frac{d}{dx}\left(\frac{1}{1 + e^{-x}}\right) \\ &= \frac{e^{-x}}{(1 + e^{-x})^2} \\ &= \frac{1}{1 + e^{-x}} \cdot \frac{e^{-x}}{1 + e^{-x}} \\ &= \sigma(x) \cdot (1 - \sigma(x)) \end{aligned} dxdσ(x)=dxd(1+e−x1)=(1+e−x)2e−x=1+e−x1⋅1+e−xe−x=σ(x)⋅(1−σ(x))
然后,对 x = U − θ x = U - \theta x=U−θ 求导:
d d U ( U − θ ) = 1 \frac{d}{dU}(U - \theta) = 1 dUd(U−θ)=1- 将上述两个结果相乘即可得到 ∂ S ^ ( U ) ∂ U \frac{\partial \hat{S}(U)}{\partial U} ∂U∂S^(U) 的表达式:
∂ S ^ ( U ) ∂ U = σ ( U − θ ) ⋅ ( 1 − σ ( U − θ ) ) \frac{\partial \hat{S}(U)}{\partial U} = \sigma(U - \theta) \cdot (1 - \sigma(U - \theta)) ∂U∂S^(U)=σ(U−θ)⋅(1−σ(U−θ))
最终结果为 σ ( U − θ ) ⋅ ( 1 − σ ( U − θ ) ) \sigma(U - \theta) \cdot (1 - \sigma(U - \theta)) σ(U−θ)⋅(1−σ(U−θ))。
我们将这个近似梯度用于反向传播过程中。具体步骤如下:
1. 损失函数对近似脉冲函数的梯度
假设我们有一个损失函数 L L L ,其对近似脉冲函数 S ^ [ t ] \hat{S}[t] S^[t] 的梯度可以近似为对真实脉冲函数 S [ t ] S[t] S[t] 的梯度:
∂ L ∂ S ^ [ t ] ≈ ∂ L ∂ S [ t ] \frac{\partial L}{\partial \hat{S}[t]} \approx \frac{\partial L}{\partial S[t]} ∂S^[t]∂L≈∂S[t]∂L
2. 近似脉冲函数对膜电位的梯度
利用上面的导数公式:
∂ S ^ [ t ] ∂ U [ t ] = S ^ ′ ( U [ t ] ) = σ ′ ( U [ t ] − θ ) = σ ( U [ t ] − θ ) ( 1 − σ ( U [ t ] − θ ) ) \frac{\partial \hat{S}[t]}{\partial U[t]} = \hat{S}'(U[t]) = \sigma'(U[t] - \theta) = \sigma(U[t] - \theta)(1 - \sigma(U[t] - \theta)) ∂U[t]∂S^[t]=S^′(U[t])=σ′(U[t]−θ)=σ(U[t]−θ)(1−σ(U[t]−θ))
3. 总梯度的计算
我们需要计算损失函数对权重 ( w ) 的总梯度:
∂ L ∂ w ≈ ∑ t = 0 T ∂ L ∂ S ^ [ t ] ∂ S ^ [ t ] ∂ U [ t ] ∂ U [ t ] ∂ w \frac{\partial L}{\partial w} \approx \sum_{t=0}^{T} \frac{\partial L}{\partial \hat{S}[t]} \frac{\partial \hat{S}[t]}{\partial U[t]} \frac{\partial U[t]}{\partial w} ∂w∂L≈t=0∑T∂S^[t]∂L∂U[t]∂S^[t]∂w∂U[t]
这个公式表示在每个时间步 t t t 上,我们计算损失函数对近似脉冲函数的梯度,乘以近似脉冲函数对膜电位的梯度,再乘以膜电位对权重的梯度。然后对所有时间步进行求和,得到损失函数对权重的总梯度。
为什么近似梯度有效?
1. 跨越非连续性
通过引入近似函数,代替原来的不可微脉冲函数,允许我们在反向传播过程中计算梯度。这解决了由于脉冲函数的非连续性导致的梯度计算问题。
2. 处理死神经元问题
死神经元问题是指神经元永远不会发放脉冲,从而对损失函数的梯度贡献为零。使用近似梯度后,即使膜电位没有达到阈值, 近似函数也会有非零的梯度 ,这使得权重仍然可以更新,从而避免了死神经元问题。
近似梯度具体例子
以sigmoid函数为例,假设我们的近似函数为:
S ^ ( U ) = σ ( U − θ ) = 1 1 + e − ( U − θ ) \hat{S}(U) = \sigma(U - \theta) = \frac{1}{1 + e^{-(U - \theta)}} S^(U)=σ(U−θ)=1+e−(U−θ)1
其导数为:
∂ S ^ ( U ) ∂ U = σ ( U − θ ) ( 1 − σ ( U − θ ) ) = e θ − U ( e θ − U + 1 ) 2 \frac{\partial \hat{S}(U)}{\partial U} = \sigma(U - \theta)(1 - \sigma(U - \theta)) = \frac{e^{\theta - U}}{(e^{\theta - U} + 1)^2} ∂U∂S^(U)=σ(U−θ)(1−σ(U−θ))=(eθ−U+1)2eθ−U
这个导数在 U = θ U = \theta U=θ 附近有较大的值,而在其他区域渐近于0,但仍然是非零的。这使得在反向传播过程中,无论膜电位是否达到阈值,梯度都可以传播到更早的层次,进行有效的参数更新。
通过这个方法,我们可以在SNN中使用类似于传统神经网络的反向传播算法,进行有效的训练。
近似梯度是如何避免梯度消失的?
近似梯度方法避免梯度消失的关键在于 近似函数的导数在所有区域都有非零值 。这意味着在反向传播过程中,梯度不会变为零,而是能够有效传播回去。这一点可以通过数学推导来具体说明:
- 以sigmoid函数为例,其导数为 σ ( U − θ ) ( 1 − σ ( U − θ ) ) \sigma(U - \theta)(1 - \sigma(U - \theta)) σ(U−θ)(1−σ(U−θ))。
- 当 U U U 很大或很小时,虽然导数值很小,但始终是非零的,这确保了梯度不会完全消失。
- 这种非零导数在整个范围内保持有效,避免了由于脉冲函数的不连续性导致的梯度消失问题。
四、本地学习规则(Local Learning Rules)
1. 脉冲时序依赖可塑性(STDP)
STDP是一种生物启发的学习规则,它根据突触前神经元和突触后神经元的脉冲时间差来调整突触权重。具体来说,如果突触前神经元在突触后神经元之前发射脉冲(即 Δ t > 0 \Delta t > 0 Δt>0 ),则突触权重会增加;反之,如果突触前神经元在突触后神经元之后发射脉冲(即 Δ t < 0 \Delta t < 0 Δt<0 ),则突触权重会减少。
2. STDP权重更新公式
STDP权重更新公式如下:
Δ w = { A + exp ( − Δ t τ + ) if Δ t > 0 − A − exp ( Δ t τ − ) if Δ t < 0 \Delta w = \begin{cases} A_+ \exp\left(-\frac{\Delta t}{\tau_+}\right) & \text{if } \Delta t > 0 \\ -A_- \exp\left(\frac{\Delta t}{\tau_-}\right) & \text{if } \Delta t < 0 \end{cases} Δw=⎩ ⎨ ⎧A+exp(−τ+Δt)−A−exp(τ−Δt)if Δt>0if Δt<0
其中:
- Δ w \Delta w Δw 是突触权重的变化。
- Δ t = t post − t pre \Delta t = t_{\text{post}} - t_{\text{pre}} Δt=tpost−tpre 是突触前后神经元发射脉冲的时间差。
- A + A_+ A+ 和 A − A_- A− 是权重增加和减少的幅度系数。
- τ + \tau_+ τ+ 和 τ − \tau_- τ− 是控制权重变化的时间常数。
3. 权重更新过程
当突触前神经元发射脉冲:
- 如果突触前神经元在突触后神经元之前发射脉冲( Δ t > 0 \Delta t > 0 Δt>0 ),则权重增加。权重增加的量随着时间差的增大呈指数衰减,即时间差越大,增加的权重越小。
- 增加权重的公式为: Δ w = A + exp ( − Δ t τ + ) \Delta w = A_+ \exp\left(-\frac{\Delta t}{\tau_+}\right) Δw=A+exp(−τ+Δt)
当突触后神经元发射脉冲:
- 如果突触前神经元在突触后神经元之后发射脉冲( Δ t < 0 \Delta t < 0 Δt<0 ),则权重减少。权重减少的量随着时间差的增大呈指数衰减,即时间差越大,减少的权重越小。
- 减少权重的公式为: Δ w = − A − exp ( Δ t τ − ) \Delta w = -A_- \exp\left(\frac{\Delta t}{\tau_-}\right) Δw=−A−exp(τ−Δt)
4. 数学推导和解释
让我们更详细地推导和解释这些公式:
权重增加( Δ t > 0 \Delta t > 0 Δt>0 ):
当突触前神经元在突触后神经元之前发射脉冲,时间差 Δ t = t post − t pre > 0 \Delta t = t_{\text{post}} - t_{\text{pre}} > 0 Δt=tpost−tpre>0 。
权重增加的公式是:
Δ w = A + exp ( − Δ t τ + ) \Delta w = A_+ \exp\left(-\frac{\Delta t}{\tau_+}\right) Δw=A+exp(−τ+Δt)
- 当 Δ t \Delta t Δt 很小时, exp ( − Δ t τ + ) ≈ 1 \exp\left(-\frac{\Delta t}{\tau_+}\right) \approx 1 exp(−τ+Δt)≈1 ,因此 Δ w ≈ A + \Delta w \approx A_+ Δw≈A+ 。
- 当 Δ t \Delta t Δt 增大时, exp ( − Δ t τ + ) \exp\left(-\frac{\Delta t}{\tau_+}\right) exp(−τ+Δt) 会迅速减小,导致 Δ w \Delta w Δw 也迅速减小。
权重减少( Δ t < 0 \Delta t < 0 Δt<0 ):
当突触前神经元在突触后神经元之后发射脉冲,时间差 Δ t = t post − t pre < 0 \Delta t = t_{\text{post}} - t_{\text{pre}} < 0 Δt=tpost−tpre<0 。
权重减少的公式是:
Δ w = − A − exp ( Δ t τ − ) \Delta w = -A_- \exp\left(\frac{\Delta t}{\tau_-}\right) Δw=−A−exp(τ−Δt)
- 当 Δ t \Delta t Δt 很小时, exp ( Δ t τ − ) ≈ 1 \exp\left(\frac{\Delta t}{\tau_-}\right) \approx 1 exp(τ−Δt)≈1 ,因此 Δ w ≈ − A − \Delta w \approx -A_- Δw≈−A− 。
- 当 Δ t \Delta t Δt 减小时, exp ( Δ t τ − ) \exp\left(\frac{\Delta t}{\tau_-}\right) exp(τ−Δt) 会迅速减小,导致 Δ w \Delta w Δw 也迅速减小。
5. STDP的生物学意义
STDP被认为是生物神经网络中学习和记忆的基础之一。它通过调整突触前后神经元的连接强度
,使得神经元能够根据 脉冲时间模式 进行学习。具体来说,STDP可以使得同步发射脉冲的神经元连接变得更强,从而增强这种时间相关性。
6. 示例和应用
假设我们有一个突触前神经元和一个突触后神经元:
- 突触前神经元在 t pre = 10 t_{\text{pre}} = 10 tpre=10 ms时发射脉冲。
- 突触后神经元在 t post = 15 t_{\text{post}} = 15 tpost=15 ms时发射脉冲。
时间差 Δ t = t post − t pre = 15 − 10 = 5 \Delta t = t_{\text{post}} - t_{\text{pre}} = 15 - 10 = 5 Δt=tpost−tpre=15−10=5 ms。
根据STDP规则,权重更新为:
Δ w = A + exp ( − 5 τ + ) \Delta w = A_+ \exp\left(-\frac{5}{\tau_+}\right) Δw=A+exp(−τ+5)
如果 A + = 0.1 A_+ = 0.1 A+=0.1 和 τ + = 20 \tau_+ = 20 τ+=20 ms:
Δ w = 0.1 exp ( − 5 20 ) = 0.1 exp ( − 0.25 ) ≈ 0.1 × 0.7788 ≈ 0.07788 \Delta w = 0.1 \exp\left(-\frac{5}{20}\right) = 0.1 \exp\left(-0.25\right) \approx 0.1 \times 0.7788 \approx 0.07788 Δw=0.1exp(−205)=0.1exp(−0.25)≈0.1×0.7788≈0.07788
因此,权重增加了约0.07788。
对比分析
脉冲神经网络(SNN)中的反向传播和权重更新方式主要包括以下三种方法:反向传播通过时间(BPTT)、近似梯度(Surrogate Gradients)和脉冲时序依赖可塑性(STDP)。每种方法的特点和适用场景如下:
1. 反向传播通过时间(BPTT)
特点:
- BPTT是传统反向传播算法在
时间
上的扩展,适用于时序数据。 - 这种方法会将时间展开,将时间步的依赖关系展开成一个长链。
- 在每个时间步进行梯度计算,并将梯度反向传播回去。
优点:
- 可以处理长期依赖问题,适用于时序数据。
- 能够精确地计算梯度,并用于优化权重。
缺点:
- 由于时间展开后链条很长,容易出现
梯度消失(vanishing gradient)
或梯度爆炸(exploding gradient)
问题。 - 计算复杂度高,计算和存储成本较大。
2. 近似梯度(Surrogate Gradients)
特点:
- 由于脉冲神经元的激活函数是非连续的,传统的梯度计算无法直接应用。
- 近似梯度方法使用连续的、可微的函数(例如Sigmoid函数)来替代非连续的脉冲激活函数。
优点:
- 通过使用连续的近似函数,能够进行梯度计算并应用反向传播。
- 可以避免梯度消失问题,因为近似函数在所有区域都有非零导数。
缺点:
- 近似函数引入了额外的(逼近)误差,可能会影响训练效果。
- 需要选择合适的近似函数,否则可能导致收敛问题。
3. 脉冲时序依赖可塑性(STDP)
特点:
- STDP是一种生物启发的学习规则,通过突触前后神经元发射脉冲的时间差来调整突触权重。
- 权重更新是基于局部的时间相关规则,而不是全局的误差。
优点:
- 不需要全局误差信号,只需要局部的时间信息,计算简单。
- 能够捕捉神经元之间的时间相关性,适用于
生物神经网络
。
缺点:
- 由于缺乏全局误差信号,可能无法达到全局最优解。
- 适用范围有限,通常用于研究生物神经网络的学习机制。
总结
这三种方法各有优缺点和适用场景:
- BPTT:适用于处理长时间依赖关系的时序数据,但存在梯度消失和梯度爆炸问题,计算复杂度高。
- 近似梯度:通过使用连续的近似函数,使得梯度计算和反向传播成为可能,适合处理SNN中的非连续激活函数问题。
- STDP:基于时间相关的局部权重更新规则,不需要全局误差信号,适用于生物神经网络的研究,但可能无法达到全局最优。
在实际应用中,可以根据具体问题的特点和需求选择合适的反向传播和权重更新方法。