Migrate from old versions#
Author: fangwei123456
中文版: 从老版本迁移
This page starts with V2 interface changes, followed by historical namespace
migration for <=0.0.0.0.12. V2 has breaking changes; update old configuration
using the table below.
V2: automatic execution and interface migration#
Previous usage |
Current usage |
|---|---|
Neuron |
Remove configuration; move modules and inputs to the same device |
|
Remove calls; use |
Backend-specific functional functions |
Use public |
Private imports from |
Use public neuron, functional or precision APIs, not |
Experimental IF/LIF/PLIF classes |
Use |
Auto CUDA and retired code/inference-graph generators |
Use |
|
Use |
|
Ordinary Linear/Conv plus memopt; retained fused/packed/sparse projections for specific algorithms |
CuPy dependencies and |
Remove them; install Triton or build optional native CUDA extensions |
Old code (cannot run with the current version):
neuron.LIFNode(step_mode="m", backend="cupy")
functional.set_backend(net, "triton")
Current standalone example:
import torch
from spikingjelly.activation_based import neuron, functional
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
node = neuron.LIFNode(step_mode="m").to(device)
x = torch.rand(4, 2, 8, device=device, requires_grad=True)
node(x).sum().backward()
functional.reset_net(node)
IF/LIF/PLIF sequence functional interfaces take explicit initial state and return spikes, final state and an optional trace. For example:
spikes, v_final, v_seq = functional.lif_multi_step(
x, torch.zeros_like(x[0]), tau=2.0, store_v_seq=True
)
Single-step lif_step returns (spike, v_next); lif_multi_step returns
three values. Check arguments and return values in Neuron and the
public API when migrating a function name.
Normal usage needs no implementation choice. See Automatic neuron execution for
installation/diagnostics, Training and Inference Precision for policies, FlexSN for
custom dynamics and Training Memory Optimization for memory optimization/projections.
There is no automatic migration script or promise that an old whole-module
pickle/checkpoint loads directly. Prefer trusted state_dict files and check
keys/shapes against the current model definition.
Historical migration: <=0.0.0.0.12#
The early namespace/step-mode migration below is retained; examples on the old version side cannot run directly in the current version. Also read Basic Conception.
Rename of Packages#
In the new version, SpikingJelly renames some sub-packages, which are:
Old |
New |
|---|---|
clock_driven |
activation_based |
event_driven |
timing_based |
Step Mode and Propagation Patterns#
All modules in the old version (<=0.0.0.0.12) of SpikingJelly are the single-step modules by default, except for the module that has the prefix MultiStep.
The new version of SpikingJelly does not use the prefix to distinguish the single/multi-step module. Now the step mode is controlled by the module itself, which is the attribute step_mode. Refer to Basic Conception for more details.
Hence, there is no multi-step module defined additionally in the new version of SpikingJelly. Now one module can be both the single-step module and the multi-step module, which is determined by step_mode is 's' or 'm'.In the old version of SpikingJelly, if we want to use the LIF neuron with single-step, we write codes as:
from spikingjelly.clock_driven import neuron
lif = neuron.LIFNode()
In the new version of SpikingJelly, all modules are single-step modules by default. We write codes similar to the old version, except we replace clock_driven``with ``activation_based:
from spikingjelly.activation_based import neuron
lif = neuron.LIFNode()
In the old version of SpikingJelly, if we want to use the LIF neuron with multi-step, we should write codes as:
from spikingjelly.clock_driven import neuron
lif = neuron.MultiStepLIFNode()
In the new version of SpikingJelly, one module can use both single-step and multi-step. We can use the LIF neuron with multi-step easily by setting step_mode='m':
from spikingjelly.activation_based import neuron
lif = neuron.LIFNode(step_mode='m')
In the old version of SpikingJelly, we use the step-by-step or layer-by-layer propagation patterns as the following codes:
import torch
import torch.nn as nn
from spikingjelly.clock_driven import neuron, layer, functional
with torch.no_grad():
T = 4
N = 2
C = 4
H = 8
W = 8
x_seq = torch.rand([T, N, C, H, W])
# step-by-step
net_sbs = nn.Sequential(
nn.Conv2d(C, C, kernel_size=3, padding=1, bias=False),
nn.BatchNorm2d(C),
neuron.IFNode()
)
y_seq = functional.multi_step_forward(x_seq, net_sbs)
# y_seq.shape = [T, N, C, H, W]
functional.reset_net(net_sbs)
# layer-by-layer
net_lbl = nn.Sequential(
layer.SeqToANNContainer(
nn.Conv2d(C, C, kernel_size=3, padding=1, bias=False),
nn.BatchNorm2d(C),
),
neuron.MultiStepIFNode()
)
y_seq = net_lbl(x_seq)
# y_seq.shape = [T, N, C, H, W]
functional.reset_net(net_lbl)
In the new version of SpikingJelly, we can use spikingjelly.activation_based.functional.set_step_mode to change the step mode of all modules in the whole network.If all modules use single-step, the network can use a step-by-step propagation pattern; if all modules use multi-step, the network can use a layer-by-layer propagation pattern:
import torch
import torch.nn as nn
from spikingjelly.activation_based import neuron, layer, functional
with torch.no_grad():
T = 4
N = 2
C = 4
H = 8
W = 8
x_seq = torch.rand([T, N, C, H, W])
# the network uses step-by-step because step_mode='s' is the default value for all modules
net = nn.Sequential(
layer.Conv2d(C, C, kernel_size=3, padding=1, bias=False),
layer.BatchNorm2d(C),
neuron.IFNode()
)
y_seq = functional.multi_step_forward(x_seq, net)
# y_seq.shape = [T, N, C, H, W]
functional.reset_net(net)
# set the network to use layer-by-layer
functional.set_step_mode(net, step_mode='m')
y_seq = net(x_seq)
# y_seq.shape = [T, N, C, H, W]
functional.reset_net(net)