C++ Technical Documentation: Hodgkin-Huxley Neural Network for Low‑Pass Filtering
Project: HHMLP – Neuromorphic Low‑Pass Filter Using HH Neurons + Linear Readout Language: C++17 Framework: LibTorch (PyTorch C++ API) Platform: Ubuntu 24.04 / Fedora, CPU/GPU
1. Introduction
This document describes a complete C++ implementation of a neuromorphic low‑pass filter based on a recurrent network of Hodgkin‑Huxley (HH) neurons. The model learns to map a noisy square wave to its ideal low‑pass filtered version, demonstrating the applicability of biologically plausible spiking neural networks to signal processing tasks.
Key features:
- Fully differentiable Hodgkin‑Huxley neuron model
- Recurrent connections among 20 neurons (trainable weights)
- Single linear readout layer with sigmoid activation
- End‑to‑end training using LibTorch’s automatic differentiation
- CPU and GPU support
2. System Architecture
The system consists of four main components:
| HH neuron | Implements HH dynamics (V, m, h, n) | HHNeuronImpl |
| Recurrent HH layer | Manages 20 neurons and recurrent weights | RecurrentHHLayerImpl |
| Full model | Recurrent layer + linear readout + sigmoid | HHMLPFilterImpl |
| Data generation | Generates noisy square wave and filtered target | generate_data() |
2.1 Hodgkin‑Huxley Neuron
State variables: membrane potential
V
V
V, sodium activation
m
m
m, sodium inactivation
h
h
h, potassium activation
n
n
n. Dynamics:
C
m
d
V
d
t
=
I
ext
−
g
Na
m
3
h
(
V
−
E
Na
)
−
g
K
n
4
(
V
−
E
K
)
−
g
L
(
V
−
E
L
)
C_m \\frac{dV}{dt} = I_{\\text{ext}} – g_{\\text{Na}} m^3 h (V-E_{\\text{Na}}) – g_{\\text{K}} n^4 (V-E_{\\text{K}}) – g_{\\text{L}} (V-E_{\\text{L}})
CmdtdV=Iext−gNam3h(V−ENa)−gKn4(V−EK)−gL(V−EL)
Integration: forward Euler with (dt = 0.01) ms. All operations are performed on torch::Tensor, allowing batching and automatic differentiation.
2.2 Recurrent HH Layer
- Number of neurons: 20
- Recurrent weight matrix:
W
rec
∈
R
20
×
20
W_{\\text{rec}} \\in \\mathbb{R}^{20\\times 20}
Wrec∈R20×20 (trainable) - At each time step, input current for neuron
i
i
i:I
ext
,
i
(
t
)
=
I
external
(
t
)
+
∑
j
W
rec
,
j
,
i
⋅
s
j
(
t
−
1
)
I_{\\text{ext},i}(t) = I_{\\text{external}}(t) + \\sum_j W_{\\text{rec},j,i} \\cdot s_j(t-1)
Iext,i(t)=Iexternal(t)+j∑Wrec,j,i⋅sj(t−1) wheres
j
(
t
−
1
)
s_j(t-1)
sj(t−1) is the spike (0/1) from neuronj
j
j at previous step (threshold crossing detection). - Output: membrane potential sequence (batch, T, 20)
2.3 Readout Layer
- Linear layer mapping 20‑dim membrane potential to a single scalar.
- Sigmoid activation to ensure output in ([0,1]) (target normalized range).
- Final output shape: (batch, T).
3. Core Implementation Details
3.1 HH Neuron (HHNeuronImpl)
class HHNeuronImpl : public torch::nn::Module {
public:
HHNeuronImpl(double dt = 0.01);
torch::Tensor forward(torch::Tensor I_ext, int step = 1);
void reset_state(int64_t batch_size = 1);
private:
double dt, Cm, gNa, gK, gL, ENa, EK, EL, V_rest;
torch::Tensor V, m, h, n;
// gate rate functions
torch::Tensor alpha_m(torch::Tensor V);
torch::Tensor beta_m(torch::Tensor V);
// … similar for h, n
};
TORCH_MODULE(HHNeuron);
The forward method performs Euler integration for step time steps and updates internal state.
3.2 Recurrent HH Layer (RecurrentHHLayerImpl)
class RecurrentHHLayerImpl : public torch::nn::Module {
public:
RecurrentHHLayerImpl(int n_neurons, double dt = 0.01);
torch::Tensor forward(torch::Tensor input_current);
private:
int n_neurons;
std::vector<HHNeuron> neurons;
torch::Tensor W_rec; // trainable recurrent weights
};
TORCH_MODULE(RecurrentHHLayer);
- input_current shape: (batch, T, n_neurons)
- Internal loop over time steps:
- Compute recurrent current using previous spikes
- Update each neuron one step
- Detect spikes (V > 0) for next step
- Returns membrane potentials for all time steps.
3.3 Full Model (HHMLPFilterImpl)
class HHMLPFilterImpl : public torch::nn::Module {
public:
HHMLPFilterImpl(int n_neurons = 20, double dt = 0.01);
torch::Tensor forward(torch::Tensor x);
private:
RecurrentHHLayer hh_layer{nullptr};
torch::nn::Linear fc{nullptr};
};
TORCH_MODULE(HHMLPFilter);
Forward pass:
3.4 Data Generation
Function generate_data creates synthetic training data:
- Input: Square wave (1–10 Hz) + Gaussian noise + random impulse noise, clamped to ([-0.8, 0.8]).
- Target: Low‑pass filtered version using a first‑order IIR filter (cutoff 5 Hz).
- Normalization: Input scaled to ([-5, 5]) (suitable for HH neuron current sensitivity). Target remains in ([-0.8, 0.8]) (output sigmoid will be later mapped).
4. Training Pipeline
4.1 Hyperparameters
| Samples | 1500 |
| Time steps | 50 |
| Sampling frequency | 100 Hz |
| Batch size | 64 |
| Epochs | 100 |
| Learning rate | 1e-3 |
| Optimizer | Adam |
| Loss | MSE |
4.2 Training Loop
for (int epoch = 1; epoch <= epochs; ++epoch) {
double total_loss = 0.0;
for (int batch = 0; batch < n_batches; ++batch) {
auto x = inputs.slice(0, start, end);
auto y = targets.slice(0, start, end);
optimizer.zero_grad();
auto pred = model->forward(x);
auto loss = torch::mse_loss(pred, y);
loss.backward();
optimizer.step();
total_loss += loss.item<double>() * (end – start);
}
if (epoch % 10 == 0)
std::cout << "Epoch " << epoch << ", Loss = " << total_loss / n_samples << std::endl;
}
4.3 Model Saving
torch::save(model, "lowpass_model.pt");
Model can be reloaded for inference or further training.
5. Compilation and Execution
5.1 Prerequisites
- LibTorch (CPU or GPU version) – Download
- CMake ≥ 3.18
- C++17 compiler (GCC ≥ 9, Clang ≥ 7)
5.2 CMake Configuration (CMakeLists.txt)
cmake_minimum_required(VERSION 3.18)
project(LowpassTrain)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_PREFIX_PATH "/path/to/libtorch") # e.g., /home/user/libtorch_cpu
find_package(Torch REQUIRED)
add_executable(train_lowpass train_lowpass.cpp)
target_link_libraries(train_lowpass ${TORCH_LIBRARIES})
5.3 Build & Run
g++ -std=c++17 -I/home/x/pro/libtorch/include -I/home/x/pro/libtorch/include/torch/csrc/api/include -I/home/x/pro/BioSight/core -L/home/x/pro/libtorch/lib -Wl,-rpath,/home/x/pro/libtorch/lib train_lowpass.cpp ../core/HHNeuron.cpp -ltorch -ltorch_cpu -lc10 -o train_lowpass
mkdir build && cd build
cmake ..
make
./train_lowpass
Expected output:
Generating data…
Data shape: inputs [1500, 50], targets [1500, 50]
Training…
Epoch 10/100, Loss = 0.0234
…
Epoch 100/100, Loss = 0.00612
Model saved to lowpass_model.pt
Test sample MAE: 0.0456
6. Performance Considerations
- Complexity: Each training epoch processes 1500 samples × 50 time steps × 20 neurons × ~10 floating‑point ops per neuron ≈ 15 million operations. On a modern CPU, 100 epochs take ~5 minutes.
- Parallelization: LibTorch automatically uses OpenMP for tensor operations (e.g., matrix multiplication, element‑wise ops). The HH neuron loop itself is sequential; for larger neuron counts (e.g., 200), one may add #pragma omp parallel for – but for 20 neurons, overhead is negligible.
- GPU acceleration: To use GPU, replace torch::kCPU with torch::kCUDA for tensors and link GPU‑enabled LibTorch. The same code works unchanged thanks to LibTorch’s device abstraction.
7. Extending to Fuzzy Control
The same architecture can be adapted to the fuzzy controller task (Mamdani approximation) by:
- Modifying the data generation to produce (e, edot) inputs and normalized control output.
- Changing the forward pass to accept two scalar inputs instead of a time series.
- The recurrent HH layer still provides temporal dynamics (useful for smoothing).
Example adaptation: remove the time dimension, treat n_inject and n_free stages as in the Python version. The readout remains linear + sigmoid.
8. Conclusion
This C++/LibTorch implementation demonstrates that a small recurrent network of Hodgkin‑Huxley neurons with a single linear readout can learn a low‑pass filtering task end‑to‑end. The code is self‑contained, compiles with standard tools, and serves as a foundation for more complex neuromorphic signal processing and control applications.
Repository: https://gitee.com/waterruby/ANNA.git License: Apache 2.0
Appendix: Complete Code Listing
The full source code (train_lowpass.cpp) is available in the repository under cpp-src/. It includes:
- HHNeuronImpl, RecurrentHHLayerImpl, HHMLPFilterImpl class definitions
- Data generation routine
- Training loop with checkpointing (optional)
- Model saving and evaluation
For the latest version, please refer to the online repository.


