spikingjelly学习-基本概念

对应内容【https://spikingjelly.readthedocs.io/zh-cn/0.0.0.0.14/activation_based/basic_concept.html#】

  • spikingjelly.activation_based 使用取值仅为0或1的张量表示脉冲
  • 基于激活值的表示方法
import torch

v = torch.rand([8])
v_th = 0.5
spike = (v >= v_th).to(v)
print('spike =', spike)
# spike = tensor([0., 0., 0., 1., 1., 0., 1., 0.])```

```python
在PyTorch中,`.to()`方法用于改变一个Tensor的数据类型或设备。在这个上下文中,`spike = (v >= v_th).to(v)`这行代码的目的是将比较操作`(v >= v_th)`的结果(一个布尔型Tensor)转换为与`v`相同的数据类型。

具体来说,`(v >= v_th)`会生成一个布尔型Tensor,其中每个元素的值根据`v`中对应元素是否大于或等于`v_th`来确定,结果为`True`或`False`。然后,`.to(v)`调用将这个布尔型Tensor转换为与`v`相同的数据类型。如果`v`是浮点型或整型,布尔型的`True`和`False`会被转换为相应的数值(通常是`1`和`0`)。

这种用法在处理神经网络时非常有用,特别是在需要将布尔型的掩码或条件操作的结果转换为神经网络可以处理的数值型数据时。

简而言之,`.to()`在这里用于确保结果Tensor与`v`有相同的数据类型,以便后续操作可以无缝进行。
import torch
from spikingjelly.activation_based import neuron

net_s = neuron.IFNode(step_mode='s')
T = 4
N = 1
C = 3
H = 8
W = 8
x_seq = torch.rand([T, N, C, H, W])
y_seq = []
print("###########################################################################")
for t in range(T):
    print("----------")
    x = x_seq[t]  # x.shape = [1, 3, 8, 8]
    print("x的shape=",x.shape)
    print("x=",x)

    y = net_s(x)  # y.shape = [N, C, H, W]
    print("y的shape=",y.shape)
    print("y=",y)

    y_seq.append(y.unsqueeze(0))
    print("y_seq=",y_seq)

print("最后的y_seq=",y_seq)
y_seq = torch.cat(y_seq)
print(y_seq.shape)
print("最后的y_seq CAT之后的=",y_seq)
# y_seq.shape = [T, N, C, H, W]

在这里插入图片描述

import torch
from spikingjelly.activation_based import neuron

net_s = neuron.IFNode(step_mode='s')
x = torch.rand([4])
print(net_s)
print(f'the initial v={net_s.v}')
y = net_s(x)
print(f'x={x}')
print(f'y={y}')
print(f'v={net_s.v}')

# outputs are:

'''
IFNode(
v_threshold=1.0, v_reset=0.0, detach_reset=False
(surrogate_function): Sigmoid(alpha=4.0, spiking=True)
)
the initial v=0.0
x=tensor([0.5543, 0.0350, 0.2171, 0.6740])
y=tensor([0., 0., 0., 0.])
v=tensor([0.5543, 0.0350, 0.2171, 0.6740])
'''

初始if的v=0
x通过if之后
y是激活之后的脉冲可能是0或者1
if神经元的电压会保持

import torch
from spikingjelly.activation_based import neuron

net_s = neuron.IFNode(step_mode='s')
x = torch.rand([4])
print(f'check point 0: v={net_s.v}')
y = net_s(x)
print(f'check point 1: v={net_s.v}')
net_s.reset()
print(f'check point 2: v={net_s.v}')
x = torch.rand([8])
y = net_s(x)
print(f'check point 3: v={net_s.v}')

# outputs are:

'''
check point 0: v=0.0
check point 1: v=tensor([0.9775, 0.6598, 0.7577, 0.2952])
check point 2: v=0.0
check point 3: v=tensor([0.8728, 0.9031, 0.2278, 0.5089, 0.1059, 0.0479, 0.5008, 0.8530])
'''
import torch
import torch.nn as nn
from spikingjelly.activation_based import neuron, functional, layer
T = 4
N = 2
C = 8
x_seq = torch.rand([T, N, C]) * 64.

net = nn.Sequential(
    layer.Linear(C, 4),
    neuron.IFNode(),
    layer.Linear(4, 2),
    neuron.IFNode()
)

functional.set_step_mode(net, step_mode='m')
with torch.no_grad():
    y_seq_layer_by_layer = x_seq
    for i in range(net.__len__()):
        y_seq_layer_by_layer = net[i](y_seq_layer_by_layer)

print(f'y_seq_layer_by_layer=\n{y_seq_layer_by_layer}')

在这里插入图片描述

import torch
import torch.nn as nn
from spikingjelly.activation_based import neuron, functional, layer
T = 4
N = 2
C = 3
H = 8
W = 8
x_seq = torch.rand([T, N, C, H, W]) * 64.

net = nn.Sequential(
layer.Conv2d(3, 8, kernel_size=3, padding=1, stride=1, bias=False),
neuron.IFNode(),
layer.MaxPool2d(2, 2),
neuron.IFNode(),
layer.Flatten(start_dim=1),
layer.Linear(8 * H // 2 * W // 2, 10),
neuron.IFNode(),
)

print(f'net={net}')

with torch.no_grad():
    y_seq_step_by_step = []
    for t in range(T):
        x = x_seq[t]
        y = net(x)
        y_seq_step_by_step.append(y.unsqueeze(0))

    y_seq_step_by_step = torch.cat(y_seq_step_by_step, 0)
    # we can also use `y_seq_step_by_step = functional.multi_step_forward(x_seq, net)` to get the same results

    print(f'y_seq_step_by_step=\n{y_seq_step_by_step}')

    functional.reset_net(net)
    functional.set_step_mode(net, step_mode='m')
    y_seq_layer_by_layer = net(x_seq)

    max_error = (y_seq_layer_by_layer - y_seq_step_by_step).abs().max()
    print(f'max_error={max_error}')
    

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
尽管两者区别仅在于计算顺序,但计算速度和内存消耗上会略有区别。

在使用梯度替代法训练时,通常推荐使用逐层传播。在正确构建网络的情况下,逐层传播的并行度更大,速度更快
训练的时候用layer by layer 一层一层训练

在内存受限时使用逐步传播,例如ANN2SNN任务中需要用到非常大的 T。因为在逐层传播模式下,对无状态的层而言,真正的 batch size 是 TN 而不是 N (参见下一个教程),当 T 太大时内存消耗极大

snn推理的时候,一次的缓存有限,要一步一步来

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_44781508

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值