The problem
The spike function is a Heaviside step: Its derivative is zero everywhere except atV = θ, where it is undefined. Standard backpropagation requires computing ∂L/∂V through this function. At zero derivative, no gradient flows and the network cannot learn.
The solution
During the backward pass only, replace the Heaviside with a smooth surrogate functiong(V) whose derivative approximates what a useful learning signal would look like near the threshold:
The forward pass is unchanged — spikes are still exactly 0 or 1. Only the gradient is approximated.
This is called the straight-through estimator in the broader machine learning literature. In the SNN context, it was formalized by Neftci et al. (2019) and has become the standard training method for deep SNNs.
Fast sigmoid surrogate
THRINDEX uses the fast sigmoid surrogate by default: wherex = V - θ (potential relative to threshold) and k controls the sharpness. A larger k makes the surrogate a tighter approximation of the true step function — useful later in training; a smaller k provides a wider gradient signal — useful early.
The surrogate is applied automatically by THRINDEX’s autograd layer. It is not a hyperparameter you configure in snn.LIF.
Why not a simple sigmoid?
A logistic sigmoidσ(x) = 1 / (1 + e^{-x}) is smooth everywhere, but its derivative peaks at x = 0 with value 0.25 and decays slowly. For a typical LIF neuron with threshold θ = 1.0, the gradient from a logistic surrogate is nearly constant across a wide range of potentials — it provides a gradient signal even far from threshold, which introduces noise.
The fast sigmoid concentrates the gradient near the threshold and decays sharply away from it, which empirically produces faster convergence and better-calibrated networks.
Implications for training
Because the gradient is only an approximation, SNN training is sensitive to a few things that ANN training is not: Learning rate. SNNs typically need a lower learning rate than equivalent ANNs. The surrogate gradient noise accumulates across timesteps and layers. THRINDEX tutorials uselr = 1e-3 as a starting point; tune downward if loss oscillates, upward if learning is slow.
Threshold. A threshold that is too high means most neurons never reach it, gradients are always zero, and the network is stuck. A threshold that is too low means neurons fire constantly, information is lost, and gradients are saturated. threshold = 0.3 works well for rate-coded inputs in [0, 1]; adjust proportionally to your input scale.
Gradient clipping. Because spike counts are bounded (0 to T), the loss surface can have sharp gradients in the weight space. Clipping gradient norms to 5.0 (clip_grad_norm_(..., 5.0)) prevents occasional large updates from destabilizing training.
In practice
loss.backward(). Everything else is standard PyTorch.
Further reading
- Neftci, E. O., Mostafa, H., & Zenke, F. (2019). Surrogate gradient learning in spiking neural networks. IEEE Signal Processing Magazine.
- Zenke, F., & Ganguli, S. (2018). SuperSpike: Supervised learning in multilayer spiking neural networks. Neural Computation.