コード例 #1
0
ファイル: neuron.py プロジェクト: starhxh/SpikingFlow
    def __init__(self,
                 init_w=-1e-3,
                 v_threshold=1.0,
                 v_reset=0.0,
                 pulse_soft=soft_pulse_function.Sigmoid(),
                 monitor_state=False):
        '''
        :param init_w: 初始的自连接权重
        :param v_threshold: 神经元的阈值电压
        :param v_reset: 神经元的重置电压
        :param pulse_soft: 反向传播时用来计算脉冲函数梯度的替代函数,即软脉冲函数
        :param monitor_state: 是否设置监视器来保存神经元的电压和释放的脉冲。
                        若为True,则self.monitor是一个字典,键包括'v'和's',分别记录电压和输出脉冲。对应的值是一个链表。为了节省显存(内存),列表中存入的是原始变量
                        转换为numpy数组后的值。还需要注意,self.reset()函数会清空这些链表

        Recurrent IF神经元模型。与Parametric LIF神经元模型类似,但有微妙的区别,自连接权重不会作用于输入。其膜电位更新方程为:

        .. math::
            \\frac{\\mathrm{d}V(t)}{\\mathrm{d}t} = w(V(t) - V_{reset}) + R_{m}I(t)

        其中 :math:`w` 是自连接权重,权重是可以学习的。对于同一层神经元,它们的 :math:`w` 是共享的。

        '''
        super().__init__(v_threshold, v_reset, pulse_soft, monitor_state)
        self.w = nn.Parameter(torch.tensor([init_w]))
コード例 #2
0
ファイル: neuron.py プロジェクト: starhxh/SpikingFlow
    def __init__(self,
                 init_tau=2.0,
                 v_threshold=1.0,
                 v_reset=0.0,
                 pulse_soft=soft_pulse_function.Sigmoid(),
                 monitor_state=False):
        '''
        :param init_tau: 初始的tau
        :param v_threshold: 神经元的阈值电压
        :param v_reset: 神经元的重置电压
        :param pulse_soft: 反向传播时用来计算脉冲函数梯度的替代函数,即软脉冲函数
        :param monitor: 是否设置监视器来保存神经元的电压和释放的脉冲。
                        若为True,则self.monitor是一个字典,键包括'v'和's',分别记录电压和输出脉冲。对应的值是一个链表。为了节省显存(内存),列表中存入的是原始变量
                        转换为numpy数组后的值。还需要注意,self.reset()函数会清空这些链表
        Parametric LIF神经元模型,时间常数tau可学习的LIF神经元:

        .. math::
            \\tau_{m} \\frac{\\mathrm{d}V(t)}{\\mathrm{d}t} = -(V(t) - V_{reset}) + R_{m}I(t)

        电压在不为v_reset时,会指数衰减。对于同一层神经元,它们的tau是共享的。

        .. tip::
            LIF神经元的电压更新方程为:

            ``self.v += (dv - (self.v - self.v_reset)) / self.tau``

            为了防止出现除以0的情况,PLIF神经元没有使用除法,而是用乘法代替:

            ``self.v += (dv - (self.v - self.v_reset)) * self.tau``
        '''
        super().__init__(v_threshold, v_reset, pulse_soft, monitor_state)
        self.tau = nn.Parameter(1 / torch.tensor([init_tau]))
コード例 #3
0
ファイル: neuron.py プロジェクト: starhxh/SpikingFlow
    def __init__(self,
                 v_threshold=1.0,
                 v_reset=0.0,
                 pulse_soft=soft_pulse_function.Sigmoid(),
                 monitor_state=False):
        '''
        :param v_threshold: 神经元的阈值电压
        :param v_reset: 神经元的重置电压。如果不为None,当神经元释放脉冲后,电压会被重置为v_reset;如果设置为None,则电压会被减去阈值
        :param pulse_soft: 反向传播时用来计算脉冲函数梯度的替代函数,即软脉冲函数
        :param monitor_state: 是否设置监视器来保存神经元的电压和释放的脉冲。
                        若为True,则self.monitor是一个字典,键包括'v'和's',分别记录电压和输出脉冲。对应的值是一个链表。为了节省显存(内存),列表中存入的是原始变量
                        转换为numpy数组后的值。还需要注意,self.reset()函数会清空这些链表

        softbp包中,可微分SNN神经元的基类神经元。

        可微分SNN神经元,在前向传播时输出真正的脉冲(离散的0和1)。脉冲的产生过程可以看作是一个阶跃函数:

        .. math::
            S = \\Theta(V - V_{threshold})

            其中\\Theta(x) =
            \\begin{cases}
            1, & x \\geq 0 \\\\
            0, & x < 0
            \\end{cases}

        :math:`\\Theta(x)` 是一个不可微的函数,用一个形状与其相似的函数 :math:`\\sigma(x)`,即代码中的pulse_soft去近\\
        似它的梯度。默认的pulse_soft = SpikingFlow.softbp.soft_pulse_function.Sigmoid(),\\
        在反向传播时用 :math:`\\sigma'(x)` 来近似 :math:`\\Theta'(x)`,这样就可以使用梯度下降法来更新SNN了。

        前向传播使用 :math:`\\Theta(x)`,反向传播时按前向传播为 :math:`\\sigma(x)` 来计算梯度,在PyTorch中很容易实现,参见\\
        这个类的spiking()函数。
        '''
        super().__init__()
        self.v_threshold = v_threshold
        self.v_reset = v_reset
        if self.v_reset is None:
            self.v = 0
        else:
            self.v = self.v_reset
        self.pulse_soft = pulse_soft
        if monitor_state:
            self.monitor = {'v': [], 's': []}
        else:
            self.monitor = False
コード例 #4
0
ファイル: neuron.py プロジェクト: starhxh/SpikingFlow
    def __init__(self,
                 v_threshold=1.0,
                 v_reset=0.0,
                 pulse_soft=soft_pulse_function.Sigmoid(),
                 monitor_state=False):
        '''
        :param v_threshold: 神经元的阈值电压
        :param v_reset: 神经元的重置电压
        :param pulse_soft: 反向传播时用来计算脉冲函数梯度的替代函数,即软脉冲函数
        :param monitor_state: 是否设置监视器来保存神经元的电压和释放的脉冲。
                        若为True,则self.monitor是一个字典,键包括'v'和's',分别记录电压和输出脉冲。对应的值是一个链表。为了节省显存(内存),列表中存入的是原始变量
                        转换为numpy数组后的值。还需要注意,self.reset()函数会清空这些链表

        IF神经元模型,可以看作理想积分器,无输入时电压保持恒定,不会像LIF神经元那样衰减:

        .. math::
            \\frac{\\mathrm{d}V(t)}{\\mathrm{d} t} = R_{m}I(t)

        电压一旦达到阈值v_threshold则放出脉冲,同时电压归位到重置电压v_reset。
        '''
        super().__init__(v_threshold, v_reset, pulse_soft, monitor_state)
コード例 #5
0
ファイル: neuron.py プロジェクト: starhxh/SpikingFlow
    def __init__(self,
                 tau=100.0,
                 v_threshold=1.0,
                 v_reset=0.0,
                 pulse_soft=soft_pulse_function.Sigmoid(),
                 monitor_state=False):
        '''
        :param tau: 膜电位时间常数,越大则充电越慢
        :param v_threshold: 神经元的阈值电压
        :param v_reset: 神经元的重置电压
        :param pulse_soft: 反向传播时用来计算脉冲函数梯度的替代函数,即软脉冲函数
        :param monitor_state: 是否设置监视器来保存神经元的电压和释放的脉冲。
                        若为True,则self.monitor是一个字典,键包括'v'和's',分别记录电压和输出脉冲。对应的值是一个链表。为了节省显存(内存),列表中存入的是原始变量
                        转换为numpy数组后的值。还需要注意,self.reset()函数会清空这些链表

        LIF神经元模型,可以看作是带漏电的积分器:

        .. math::
            \\tau_{m} \\frac{\\mathrm{d}V(t)}{\\mathrm{d}t} = -(V(t) - V_{reset}) + R_{m}I(t)

        电压在不为v_reset时,会指数衰减。
        '''
        super().__init__(v_threshold, v_reset, pulse_soft, monitor_state)
        self.tau = tau