| name | dynamic-gated-neuron-snn |
| description | Dynamic Gated Neuron (DGN) - Biologically plausible gating mechanism for Spiking Neural Networks via dynamic membrane conductance modulation. Enables selective input filtering and adaptive noise suppression. Activation triggers: dynamic gated neuron, DGN, SNN gating, conductance-based SNN, robust spiking neural network, biological gating. |
Dynamic Gated Neuron (DGN) for SNNs
A brain-inspired gating mechanism that unlocks robust computation in Spiking Neural Networks through dynamic membrane conductance modulation.
Metadata
- Source: arXiv:2509.03281
- Authors: Qianyi Bai, Haiteng Wang, Qiang Yu
- Published: 2025-09
- Institution: Tianjin University, Tianjin Normal University
- Code: TBD (check paper for updates)
Core Methodology
Key Innovation
Traditional Leaky Integrate-and-Fire (LIF) neurons lack internal gating mechanisms, limiting their ability to cope with noise and temporal variability. The Dynamic Gated Neuron (DGN) introduces:
- Activity-Dependent Conductance: Membrane conductance evolves dynamically in response to neuronal activity
- Selective Input Filtering: Adaptive noise suppression based on input dynamics
- Stochastic Stability: Enhanced stability guarantees under noisy conditions
- Biological Plausibility: Grounded in real neurophysiological mechanisms (protein phosphorylation, gene expression, calcium signaling)
Biological Inspiration
| Biological Mechanism | Computational Analog | Function |
|---|
| Protein phosphorylation | Activity tracking | State-dependent modulation |
| Immediate early genes (c-fos, ras) | Conductance update | Long-term plasticity |
| Intracellular calcium | Second messenger | Activity-to-conductance coupling |
| Potassium channel modulation | Dynamic conductance | Adaptive filtering |
Technical Framework
Dynamic Gated Neuron Model
The DGN extends the LIF neuron with dynamic conductance:
$$
\tau_m \frac{dv}{dt} = -(v - v_{rest}) - g(t) \cdot v + I_{syn}(t)
$$
$$
\tau_g \frac{dg}{dt} = -g + \alpha \cdot \phi(v_{history})
$$
Where:
- $v$: Membrane potential
- $g(t)$: Dynamic conductance (gating variable)
- $\tau_m, \tau_g$: Time constants for membrane and conductance
- $\phi$: Activity-dependent modulation function
- $\alpha$: Conductance gain
Gating Function
The gating mechanism modulates information flow:
g_t = g_{t-1} + α * tanh(β * v_t - γ) - g_{t-1}/τ_g
I_eff = I_syn / (1 + g_t)
dv = (-(v - v_rest) + I_eff) / τ_m
Key Properties:
- High conductance → Reduced membrane time constant → Fast response to salient inputs
- Low conductance → Extended membrane time constant → Integration of weak signals
- Adaptive threshold: Effectively implements dynamic input filtering
Implementation Guide
Prerequisites
pip install torch snntorch
pip install numpy matplotlib
Step-by-Step
Step 1: Basic DGN Implementation
import torch
import torch.nn as nn
import numpy as np
class DynamicGatedNeuron(nn.Module):
"""
Dynamic Gated Neuron (DGN)
Biologically plausible spiking neuron with dynamic conductance modulation.
"""
def __init__(
self,
tau_m=20.0,
tau_g=100.0,
v_rest=-65.0,
v_thresh=-50.0,
v_reset=-70.0,
alpha=0.1,
beta=0.5,
gamma=0.0,
dt=1.0
):
super().__init__()
self.tau_m = tau_m
self.tau_g = tau_g
self.v_rest = v_rest
self.v_thresh = v_thresh
self.v_reset = v_reset
self.alpha = alpha
self.beta = beta
self.gamma = gamma
self.dt = dt
self.v =
.g =
.spike =
():
.v = torch.full((batch_size,), .v_rest, device=device)
.g = torch.zeros(batch_size, device=device)
.spike = torch.zeros(batch_size, device=device)
():
.v :
.reset_state(I_syn.size(), I_syn.device)
activity = torch.tanh(.beta * (.v - .v_rest) - .gamma)
dg = (-.g + .alpha * activity) / .tau_g * .dt
.g = .g + dg
.g = torch.clamp(.g, =)
I_eff = I_syn / ( + .g)
dv = (-(.v - .v_rest) + I_eff) / .tau_m * .dt
.v = .v + dv
.spike = (.v >= .v_thresh).()
.v = torch.where(
.spike > ,
torch.full_like(.v, .v_reset),
.v
)
.spike
():
.g.clone()
(nn.Module):
():
().__init__()
.n_neurons = n_neurons
.neurons = nn.ModuleList([
DynamicGatedNeuron(**kwargs) _ (n_neurons)
])
():
neuron .neurons:
neuron.reset_state(batch_size, device)
():
spikes = []
i, neuron (.neurons):
spike = neuron(I_syn[:, i])
spikes.append(spike)
torch.stack(spikes, dim=)
Step 2: DGN Network for Pattern Recognition
class DGNSNN(nn.Module):
"""
Spiking Neural Network with Dynamic Gated Neurons
for robust pattern recognition
"""
def __init__(
self,
input_size,
hidden_size,
output_size,
n_time_steps=100
):
super().__init__()
self.n_time_steps = n_time_steps
self.input_fc = nn.Linear(input_size, hidden_size)
self.hidden = DGNLayer(
n_neurons=hidden_size,
tau_m=20.0,
tau_g=50.0,
alpha=0.2
)
self.recurrent = nn.Linear(hidden_size, hidden_size)
self.output_fc = nn.Linear(hidden_size, output_size)
def forward(self, x):
"""
Args:
x: (batch_size, n_time_steps, input_size)
Returns:
output: (batch_size, output_size)
"""
batch_size = x.size(0)
device = x.device
self.hidden.reset_state(batch_size, device)
hidden_spikes = []
for t in range(self.n_time_steps):
I_in = self.input_fc(x[:, t])
t > :
I_rec = .recurrent(hidden_spikes[-])
:
I_rec = torch.zeros_like(I_in)
I_syn = I_in + I_rec
spikes = .hidden(I_syn)
hidden_spikes.append(spikes)
hidden_spikes = torch.stack(hidden_spikes, dim=)
spike_rates = hidden_spikes.(dim=) / .n_time_steps
output = .output_fc(spike_rates)
output
Step 3: Training with Surrogate Gradients
import torch.nn.functional as F
from torch.utils.data import DataLoader
def surrogate_gradient(spike, v, v_thresh, alpha=1.0):
"""
Surrogate gradient for backpropagation through spikes
Using fast sigmoid surrogate
"""
return alpha / (1 + (v - v_thresh).pow(2))
class SurrogateGradient(torch.autograd.Function):
"""Custom surrogate gradient for spiking neurons"""
@staticmethod
def forward(ctx, input):
ctx.save_for_backward(input)
return (input > 0).float()
@staticmethod
def backward(ctx, grad_output):
input, = ctx.saved_tensors
grad_input = grad_output / (1 + input.abs()).pow(2)
return grad_input
def train_dgn_snn(
model,
train_loader,
epochs=50,
lr=1e-3,
device='cuda'
):
"""Train DGN-SNN with surrogate gradients"""
model = model.to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=lr)
epoch (epochs):
model.train()
total_loss =
correct =
total =
batch_idx, (data, target) (train_loader):
data, target = data.to(device), target.to(device)
data.dim() == :
data = data.unsqueeze().repeat(, model.n_time_steps, )
optimizer.zero_grad()
output = model(data)
loss = F.cross_entropy(output, target)
loss.backward()
optimizer.step()
total_loss += loss.item()
pred = output.argmax(dim=)
correct += (pred == target).().item()
total += target.size()
acc = * correct / total
(
)
model
Step 4: Robustness Evaluation
def evaluate_robustness(model, test_loader, noise_levels, device='cuda'):
"""
Evaluate model robustness under different noise conditions
"""
model.eval()
results = {}
for noise_std in noise_levels:
correct = 0
total = 0
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)
if data.dim() == 2:
data = data.unsqueeze(1).repeat(1, model.n_time_steps, 1)
noisy_data = data + torch.randn_like(data) * noise_std
noisy_data = torch.clamp(noisy_data, 0, 1)
output = model(noisy_data)
pred = output.argmax(dim=1)
correct += (pred == target).sum().item()
total += target.size(0)
acc = 100. * correct / total
results[noise_std] = acc
print(f'Noise std = {noise_std:.3f}: Accuracy = {acc:.2f}%')
return results
def compare_with_lif(dgn_model, lif_model, test_loader, device='cuda'):
"""
Compare DGN with standard LIF neuron performance
"""
results = {'DGN': {}, : {}}
name, model [(, dgn_model), (, lif_model)]:
model.()
correct =
total =
torch.no_grad():
data, target test_loader:
data, target = data.to(device), target.to(device)
output = model(data)
pred = output.argmax(dim=)
correct += (pred == target).().item()
total += target.size()
results[name][] = * correct / total
noise_std =
name, model [(, dgn_model), (, lif_model)]:
model.()
correct =
total =
torch.no_grad():
data, target test_loader:
data, target = data.to(device), target.to(device)
noisy_data = data + torch.randn_like(data) * noise_std
output = model(torch.clamp(noisy_data, , ))
pred = output.argmax(dim=)
correct += (pred == target).().item()
total += target.size()
results[name][] = * correct / total
()
(
)
(
)
results
Step 5: Temporal Processing - TIDIGITS
class DGNForAudio(nn.Module):
"""
DGN-based SNN for temporal audio processing
Applied to TIDIGITS dataset
"""
def __init__(
self,
n_freq_bins=40,
hidden_size=256,
output_size=11,
n_time_steps=500
):
super().__init__()
self.n_time_steps = n_time_steps
self.input_proj = nn.Linear(n_freq_bins, hidden_size)
self.hidden = DGNLayer(
n_neurons=hidden_size,
tau_m=10.0,
tau_g=30.0,
alpha=0.3,
beta=0.8,
gamma=-5.0
)
self.recurrent = nn.Linear(hidden_size, hidden_size)
self.readout = nn.Linear(hidden_size, output_size)
def forward(self, mel_spec):
"""
Args:
mel_spec: (batch, time, freq_bins) - Mel spectrogram
Returns:
output: (batch, output_size) - Digit classification
"""
batch_size = mel_spec.size(0)
device = mel_spec.device
.hidden.reset_state(batch_size, device)
hidden_spikes = []
gating_history = []
t ((mel_spec.size(), .n_time_steps)):
I_in = .input_proj(mel_spec[:, t])
t > :
I_rec = .recurrent(hidden_spikes[-])
:
I_rec = torch.zeros_like(I_in)
I_total = I_in + I_rec
spikes = .hidden(I_total)
hidden_spikes.append(spikes)
gating_history.append(.hidden.neurons[].get_gating_strength()[])
hidden_spikes = torch.stack(hidden_spikes, dim=)
spike_sum = hidden_spikes.(dim=)
output = .readout(spike_sum)
output, gating_history
():
torchaudio.datasets TIDIGITS
transform = torchaudio.transforms.MelSpectrogram(
sample_rate=,
n_fft=,
n_mels=
)
TIDIGITS(root=, transform=transform)
Applications
1. Noise-Robust Pattern Recognition
def deploy_robust_classifier(dgn_model, input_signal, noise_profile='moderate'):
"""
Deploy DGN for robust classification under varying noise
"""
noise_config = {
'low': 0.05,
'moderate': 0.15,
'high': 0.30
}
noise_level = noise_config.get(noise_profile, 0.15)
noisy_input = input_signal + torch.randn_like(input_signal) * noise_level
output = dgn_model(noisy_input)
return output
2. Adaptive Filtering
class AdaptiveFilterDGN:
"""Use DGN gating for adaptive signal filtering"""
def __init__(self, n_channels):
self.neurons = [DynamicGatedNeuron() for _ in range(n_channels)]
def filter_signal(self, signal, snr_threshold=10):
"""
Filter noisy signal using DGN gating
The dynamic conductance adapts to signal statistics,
effectively filtering noise based on local SNR
"""
filtered = np.zeros_like(signal)
gating_strength = np.zeros_like(signal)
for t in range(len(signal)):
for ch in range(signal.shape[1]):
spike = self.neurons[ch].forward(
torch.tensor([signal[t, ch]])
)
gating_strength[t, ch] = self.neurons[ch].g.item()
filtered[t, ch] = spike.item()
return filtered, gating_strength
3. Neuromorphic Computing
def deploy_on_neuromorphic(dgn_network, spike_input, hardware='loihi'):
"""
Deployment guidelines for neuromorphic hardware
Hardware compatibility:
- Intel Loihi: Native conductance support
- IBM TrueNorth: Requires conductance approximation
- SpiNNaker: Full DGN support via custom neuron models
"""
if hardware == 'loihi':
config = {
'neuron_type': 'cuba',
'tau_m': dgn_network.tau_m,
'tau_adapt': dgn_network.tau_g,
'adapt_inc': dgn_network.alpha
}
elif hardware == 'spinnaker':
config = {
'neuron_model': 'DGN',
'parameters': dgn_network.get_params()
}
return config
Benchmarks
TIDIGITS Spoken Digit Recognition
| Model | Clean | Noise (σ=0.2) | Noise (σ=0.4) |
|---|
| LIF | 92.5% | 78.3% | 62.1% |
| DGN | 93.1% | 89.7% | 81.4% |
| Improvement | +0.6% | +11.4% | +19.3% |
SHD (Spiking Heidelberg Digits)
| Model | Accuracy | Latency (ms) |
|---|
| LIF | 84.2% | 750 |
| GLIF | 86.7% | 800 |
| DGN | 89.3% | 720 |
Robustness Metrics
| Metric | LIF | DGN | Improvement |
|---|
| SNR Tolerance (dB) | 5 | 12 | +7 dB |
| Temporal Jitter Robustness | Moderate | High | Significant |
| Pattern Completion | Poor | Good | Substantial |
Theoretical Analysis
Stochastic Stability
The DGN exhibits enhanced stochastic stability through its disturbance rejection mechanism:
Theorem (Informal): Under bounded input noise $|\xi(t)| \leq \sigma$, the DGN membrane potential satisfies:
$$\mathbb{E}[|v(t) - v_{target}|^2] \leq \frac{\sigma^2}{2\lambda_{eff}}$$
where $\lambda_{eff} = \lambda_0 + g(t)$ is the effective decay rate enhanced by dynamic conductance.
Connection to LSTM Gates
| Aspect | LSTM | DGN |
|---|
| Forget gate | Sigmoid-controlled | Conductance decay |
| Input gate | Learned weights | Activity-dependent |
| Cell state | Explicit memory | Membrane potential |
| Biological basis | None | Calcium signaling |
| Energy cost | High (MAC ops) | Low (spike events) |
Pitfalls
- Hyperparameter Sensitivity: Conductance time constant $\tau_g$ requires tuning for task temporal scales
- Initial Transient: Dynamic conductance needs warm-up period (first ~100ms)
- Computational Cost: ~15% overhead compared to LIF due to conductance update
- Hardware Constraints: Not all neuromorphic chips support dynamic conductance
- Gradient Flow: Surrogate gradients may be less stable with dynamic parameters
Related Skills
- three-factor-snn-learning
- cognisnn-brain-inspired-snn
- adaptive-spiking-neuron-asn
- spiking-mllm-multimodal-spiking
- working-memory-heterogeneous-delays
References
@article{bai2025dynamic,
title={A Brain-Inspired Gating Mechanism Unlocks Robust Computation in Spiking Neural Networks},
author={Bai, Qianyi and Wang, Haiteng and Yu, Qiang},
journal={arXiv preprint arXiv:2509.03281},
year={2025}
}