ANN-to-SNN Conversion¶
Convert trained PyTorch ANNs to rate-coded spiking neural networks.
Contract¶
The conversion package is an optional PyTorch surface. The base package can be
imported without PyTorch; resolving convert, ConvertedSNN, or
QCFSActivation requires a PyTorch-capable environment.
convert(model, calibration_data=None, T=None, percentile=99.9)extractsLinearandConv2dweights and selects a conversion route from the model's activations, returning a deterministicConvertedSNN:- Threshold-balancing route (ReLU models, Diehl et al. 2015) — calibrates
activation thresholds from ReLU layers when calibration data is supplied,
starts each IF neuron from rest, and defaults
Tto 16. - QCFS route (QCFS-trained models, Bu et al. 2022) — takes each
QCFSActivation's learned threshold directly, pre-loads each IF neuron totheta / 2(the optimal shift that cancels the quantisation bias), ignores calibration data, and adopts the layers' trained step budget whenTis left unset. ConvertedSNN.run(x)rate-codes NumPy input with a fixed RNG seed and returns output spike counts for one vector or a batch.initial_membrane_fractioncontrols the per-layer membrane pre-load (0.0rest,0.5QCFS shift).ConvertedSNN.classify(x)returns the argmax class index from output spike counts.QCFSActivationreplaces ReLU during conversion-aware training by clipping activations to[0, theta]and quantising them toT + 1spike-rate levels with a straight-through gradient.replace_relu_with_qcfs(model, T=8, theta=1.0, learn_theta=True)substitutes everyReLU/ReLU6in a model (recursing through submodules) with aQCFSActivation, preparing the network for QCFS conversion-aware fine-tuning.
Verification¶
The public conversion files are covered by the scoped NumPy-docstring policy:
src/sc_neurocore/conversion/__init__.pysrc/sc_neurocore/conversion/ann_to_snn.pysrc/sc_neurocore/conversion/qcfs.py
Focused production tests live in tests/test_conversion.py and
tests/test_conversion_ann_snn.py. They exercise real PyTorch modules, the
threshold-balancing and QCFS conversion routes, ConvertedSNN.run,
ConvertedSNN.classify, the membrane shift, the ReLU→QCFS substitution helper,
QCFS range and gradient behaviour, and the layer-extraction contract.
Converter¶
sc_neurocore.conversion.ann_to_snn
¶
Convert trained PyTorch ANNs to rate-coded spiking neural networks.
Two conversion routes are supported, selected automatically from the activations present in the source model:
Threshold-balancing route (ReLU models, Diehl et al. 2015)
Replaces ReLU activations with integrate-and-fire (IF) neurons and
rescales weights so that the calibrated maximum activation maps onto
the firing threshold. A spike train of rate a / theta over T
timesteps approximates the ANN activation a.
QCFS route (QCFS-trained models, Bu et al. 2022)
When the model carries :class:~sc_neurocore.conversion.qcfs.QCFSActivation
layers, their learned per-layer thresholds become the IF thresholds
directly (no calibration pass) and each IF neuron is initialised to a
membrane potential of theta / 2 — the optimal shift that cancels
the quantisation flooring bias. A QCFS-trained ANN then converts to an
SNN with near-zero accuracy loss at the matching timestep budget.
Pipeline
- Extract weights and biases from the PyTorch model.
- Derive per-layer thresholds — from QCFS layers when present, otherwise from calibration activation statistics.
- Normalise weights so each threshold maps onto unity.
- Build an IF-neuron SNN that reproduces the ANN output as spike
counts over
Ttimesteps, with the QCFS membrane shift applied when converting a QCFS-trained model.
References¶
Diehl et al. 2015 — "Fast-classifying, high-accuracy spiking deep networks through weight and threshold balancing". Bu et al. 2022 — "Optimal ANN-SNN Conversion for High-accuracy and Ultra-low-latency Spiking Neural Networks" (ICLR).
ConvertedSNN
dataclass
¶
Rate-coded SNN converted from an ANN.
Attributes¶
weights : list of ndarray
Per-layer weight matrices.
biases : list of ndarray or None
Per-layer biases (None if absent).
thresholds : list of float
Per-layer firing thresholds after normalization.
T : int
Number of simulation timesteps.
initial_membrane_fraction : float
Fraction of each layer's threshold pre-loaded into the IF membrane
potential before the first timestep. 0.0 reproduces the
threshold-balancing route; 0.5 applies the QCFS optimal shift
(Bu et al. 2022) that cancels the quantisation flooring bias.
n_layers : int
Number of layers.
Source code in src/sc_neurocore/conversion/ann_to_snn.py
| Python | |
|---|---|
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | |
__post_init__()
¶
Derive the layer count from the converted weight stack.
Source code in src/sc_neurocore/conversion/ann_to_snn.py
| Python | |
|---|---|
93 94 95 | |
run(x)
¶
Run the converted SNN for T timesteps on input x.
Parameters¶
x : ndarray of shape (n_input,) or (batch, n_input) Input values in [0, 1]. Converted to Poisson spike trains.
Returns¶
ndarray of shape (n_output,) or (batch, n_output) Output spike counts over T timesteps (unnormalized).
Source code in src/sc_neurocore/conversion/ann_to_snn.py
| Python | |
|---|---|
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | |
classify(x)
¶
Run SNN and return predicted class indices.
Source code in src/sc_neurocore/conversion/ann_to_snn.py
| Python | |
|---|---|
147 148 149 150 151 | |
convert(model, calibration_data=None, T=None, percentile=99.9)
¶
Convert a trained PyTorch ANN to a rate-coded SNN.
The conversion route is selected from the model's activations: a model
carrying :class:QCFSActivation layers takes the QCFS route (learned
thresholds, theta / 2 membrane shift, no calibration); any other
model takes the threshold-balancing route (calibrated or unit
thresholds, rest-state membrane).
Parameters¶
model : nn.Module Trained PyTorch model with Linear/Conv2d layers and either ReLU or QCFS activations. calibration_data : Tensor, optional Sample input batch for threshold calibration on the ReLU route. If None, the ReLU route uses a default threshold of 1.0 per layer. Ignored on the QCFS route, whose thresholds are already learned. T : int, optional Number of simulation timesteps (higher = more accurate, slower). If None, the QCFS route adopts the layers' trained step budget and the ReLU route defaults to 16. percentile : float Activation percentile for threshold normalization on the ReLU route.
Returns¶
ConvertedSNN Converted spiking network ready to run.
Source code in src/sc_neurocore/conversion/ann_to_snn.py
| Python | |
|---|---|
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 | |
replace_relu_with_qcfs(model, T=8, theta=1.0, learn_theta=True)
¶
Swap every ReLU/ReLU6 in a model for a QCFS activation, in place.
This prepares a trained or fresh ANN for conversion-aware fine-tuning:
after substitution the network is retrained for a few epochs so the QCFS
thresholds settle, after which :func:convert produces a near-lossless
SNN (Bu et al. 2022).
Parameters¶
model : nn.Module Model whose ReLU/ReLU6 activations are replaced. Mutated in place, recursing through every submodule. T : int Quantisation step budget for each inserted QCFS layer. theta : float Initial firing threshold for each inserted QCFS layer. learn_theta : bool Whether each inserted threshold is a trainable parameter (the QCFS fine-tuning default).
Returns¶
nn.Module
The same model instance, returned for chaining.
Source code in src/sc_neurocore/conversion/ann_to_snn.py
| Python | |
|---|---|
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | |
QCFS Activation¶
sc_neurocore.conversion.qcfs
¶
QCFS (Quantization-Clip-Floor-Shift) activation function.
Replaces ReLU in the ANN during conversion-aware training or post-hoc conversion. QCFS approximates the rate-coded SNN firing rate as a quantized step function, minimizing conversion error.
Reference: Bu et al. 2022 — "Optimal ANN-SNN Conversion for High-accuracy and Ultra-low-latency Spiking Neural Networks"
QCFSActivation
¶
Bases: Module
QCFS activation: quantized clip-floor-shift ReLU replacement.
For T timesteps and threshold theta
QCFS(x) = clip(floor(x * T / theta + 0.5), 0, T) * theta / T
This quantizes activations to T+1 levels in [0, theta], matching the achievable spike rates of an IF neuron over T timesteps.
Parameters¶
T : int Number of simulation timesteps. theta : float Firing threshold (default 1.0). learn_theta : bool Make threshold trainable (default False).
Source code in src/sc_neurocore/conversion/qcfs.py
| Python | |
|---|---|
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | |
forward(x)
¶
Quantise activations to the spike-rate grid with a straight-through gradient.
Parameters¶
x : torch.Tensor
ANN activation tensor to clip and quantise into T + 1 rate levels.
Returns¶
torch.Tensor
Tensor with values clipped to [0, theta] and quantised to the
finite-timestep spike-rate lattice.
Source code in src/sc_neurocore/conversion/qcfs.py
| Python | |
|---|---|
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | |
extra_repr()
¶
Return the compact PyTorch module representation.
Source code in src/sc_neurocore/conversion/qcfs.py
| Python | |
|---|---|
73 74 75 | |