Rewrite HF model card with YAML front matter
Browse files- Add proper HF YAML front matter (language, license, tags, pipeline_tag)
- Personal narrative: concussion story, BCI vision
- Architecture specs, merged v2 parameters, Q8.8 format docs
- Usage examples in Python, Rust, Julia, Verilog
- Known limitations: monotonic weights, missing inhibitory connections
- License: dual MIT/Apache-2.0
- Remove framework version fields from config.json
- README.md +176 -24
- config.json +1 -6
README.md
CHANGED
|
@@ -1,39 +1,191 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
-
|
| 7 |
|
| 8 |
-
|
| 9 |
-
Spikenaut-SNN-v2 is my research-grade Spiking Neural Network (SNN) model designed for high-frequency data processing and autonomous decision-making in noisy environments.
|
| 10 |
|
| 11 |
-
|
| 12 |
-
Hardware-Driven Learning: Utilizing real-world telemetry from hardwareβspecifically my Dynex mining baselineβto drive STDP (Spike-Timing-Dependent Plasticity).
|
| 13 |
|
| 14 |
-
|
| 15 |
|
| 16 |
-
|
| 17 |
|
| 18 |
-
|
| 19 |
-
This research is developed and trained locally on my Ship of Theseus workstation running Fedora 43. My codebase is organized under the Eagle-Lander framework.
|
| 20 |
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
-
|
| 24 |
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
-
|
| 28 |
-
[x] Initial Prototype (Dynex SNN)
|
| 29 |
|
| 30 |
-
|
| 31 |
|
| 32 |
-
|
| 33 |
|
| 34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
|
| 36 |
-
|
| 37 |
-
This model and its associated logic are released under the GNU General Public License v3.0 (GPL-3.0).
|
| 38 |
|
| 39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
language:
|
| 3 |
+
- python
|
| 4 |
+
- rust
|
| 5 |
+
- julia
|
| 6 |
+
license:
|
| 7 |
+
- mit
|
| 8 |
+
- apache-2.0
|
| 9 |
+
tags:
|
| 10 |
+
- spiking-neural-networks
|
| 11 |
+
- neuromorphic
|
| 12 |
+
- fpga
|
| 13 |
+
- q88-fixed-point
|
| 14 |
+
- leaky-integrate-and-fire
|
| 15 |
+
- e-prop
|
| 16 |
+
- ottt
|
| 17 |
+
pipeline_tag: other
|
| 18 |
+
model_name: Spikenaut-SNN-v2
|
| 19 |
+
---
|
| 20 |
|
| 21 |
+
# Spikenaut-SNN-v2
|
| 22 |
|
| 23 |
+
A 16-neuron Leaky-Integrate-and-Fire (LIF) Spiking Neural Network trained on live cryptocurrency mining, high-frequency trading, and blockchain sync node telemetry. Designed for Xilinx Artix-7 FPGA deployment at 97 mW.
|
|
|
|
| 24 |
|
| 25 |
+
## The Story
|
|
|
|
| 26 |
|
| 27 |
+
In 2013, a severe concussion left me unable to process the world's data the way I used to. Without access to neuro-rehabilitation, I decided to build my own. As an Electrical Engineering student at Texas State University focusing on micro/nano devices, I started building what would become Spikenaut -- a neuromorphic system that learns from the raw signals of the machines I run every day.
|
| 28 |
|
| 29 |
+
The name comes from "spike" (neural firing) and "naut" (navigator). This model is the brain -- the trained neural weights that turn raw telemetry into decisions.
|
| 30 |
|
| 31 |
+
## Architecture
|
|
|
|
| 32 |
|
| 33 |
+
| Spec | Value |
|
| 34 |
+
|------|-------|
|
| 35 |
+
| Neuron model | Leaky-Integrate-and-Fire (LIF) |
|
| 36 |
+
| Neurons | 16 |
|
| 37 |
+
| Input channels | 16 |
|
| 38 |
+
| Weight format | Q8.8 fixed-point |
|
| 39 |
+
| Learning rules | E-prop, OTTT, reward-modulated STDP |
|
| 40 |
+
| Clock | 1 kHz (1ms resolution) |
|
| 41 |
+
| Training speed | 35 us/tick |
|
| 42 |
+
| Memory footprint | 1.6 KB |
|
| 43 |
+
| FPGA power | 97 mW (25 mW dynamic, 72 mW static) |
|
| 44 |
+
| FPGA target | Xilinx Artix-7 xc7a35tcpg236-1 (Basys3) |
|
| 45 |
|
| 46 |
+
### 16-Channel Input Map
|
| 47 |
|
| 48 |
+
| Channels | Data Source | Function |
|
| 49 |
+
|----------|------------|----------|
|
| 50 |
+
| 0-1 | DNX (Dynex) | PoUW solver health and neural baselines |
|
| 51 |
+
| 2-3 | Quai | Live on-chain reflex and sync confidence |
|
| 52 |
+
| 4-5 | Qubic | Epoch and tick cadence monitoring |
|
| 53 |
+
| 6-7 | Kaspa | High-frequency DAG settlement tracking |
|
| 54 |
+
| 8-9 | XMR (Monero) | Node stability and CPU L3 cache contention |
|
| 55 |
+
| 10-11 | Ocean | Data liquidity and staking prep |
|
| 56 |
+
| 12-13 | Verus | CPU-heavy validator tracking (AVX-512) |
|
| 57 |
+
| 14-15 | Thermal | Pain receptors -- power and temperature |
|
| 58 |
|
| 59 |
+
Channels 14-15 are the network's pain receptors. When the GPU crosses 85C, the SNN receives negative reward and learns to avoid states that could damage the hardware.
|
|
|
|
| 60 |
|
| 61 |
+
## Merged v2 Parameters
|
| 62 |
|
| 63 |
+
This model ships with a merged parameter set combining the best of three training sources:
|
| 64 |
|
| 65 |
+
| Parameter | Source | Values |
|
| 66 |
+
|-----------|--------|--------|
|
| 67 |
+
| Thresholds (16) | Real trained weights | Graduated 1.125 to 1.594 per neuron |
|
| 68 |
+
| Decay rates (16) | Converted parameters | Graduated 0.80 to 0.95 per neuron |
|
| 69 |
+
| Hidden weights (256) | Real trained weights | Range 0.75 to 1.04, 76 unique values |
|
| 70 |
+
| Output weights (48) | Real trained weights | Signed: -0.164 to +0.258 (inhibitory + excitatory) |
|
| 71 |
|
| 72 |
+
### Q8.8 Fixed-Point Format
|
|
|
|
| 73 |
|
| 74 |
+
All `.mem` files use Q8.8 fixed-point encoding. Each line is one 4-digit hex value:
|
| 75 |
+
|
| 76 |
+
```
|
| 77 |
+
Hex: 0100 β Decimal: 256 β Float: 256/256 = 1.0
|
| 78 |
+
Hex: 00DA β Decimal: 218 β Float: 218/256 = 0.852
|
| 79 |
+
Hex: 00CC β Decimal: 204 β Float: 204/256 = 0.797
|
| 80 |
+
```
|
| 81 |
+
|
| 82 |
+
Negative values use two's complement: `FFF9` = -0.027.
|
| 83 |
+
|
| 84 |
+
## Files
|
| 85 |
+
|
| 86 |
+
```
|
| 87 |
+
dataset/merged_v2/
|
| 88 |
+
βββ parameters.mem # 16 neuron thresholds (Q8.8 hex)
|
| 89 |
+
βββ parameters_decay.mem # 16 decay rates (Q8.8 hex)
|
| 90 |
+
βββ parameters_weights.mem # 16x16 weight matrix (Q8.8 hex)
|
| 91 |
+
βββ parameters_output_weights.mem # Output layer weights (signed Q8.8)
|
| 92 |
+
βββ snn_model.json # Full model definition (float values)
|
| 93 |
+
```
|
| 94 |
+
|
| 95 |
+
## Usage
|
| 96 |
+
|
| 97 |
+
### Python
|
| 98 |
+
|
| 99 |
+
```python
|
| 100 |
+
import json
|
| 101 |
+
|
| 102 |
+
# Load model
|
| 103 |
+
with open("dataset/merged_v2/snn_model.json") as f:
|
| 104 |
+
model = json.load(f)
|
| 105 |
+
|
| 106 |
+
for i, neuron in enumerate(model["neurons"]):
|
| 107 |
+
print(f"Neuron {i}: threshold={neuron['threshold']}, decay={neuron['decay_rate']}")
|
| 108 |
+
print(f" Weights: {neuron['weights']}")
|
| 109 |
+
```
|
| 110 |
+
|
| 111 |
+
### Verilog
|
| 112 |
+
|
| 113 |
+
```verilog
|
| 114 |
+
// Load thresholds from Q8.8 hex file
|
| 115 |
+
reg [15:0] threshold_ram [0:15];
|
| 116 |
+
initial $readmemh("dataset/merged_v2/parameters.mem", threshold_ram);
|
| 117 |
+
|
| 118 |
+
// Load weights from Q8.8 hex file
|
| 119 |
+
reg [15:0] weight_ram [0:255];
|
| 120 |
+
initial $readmemh("dataset/merged_v2/parameters_weights.mem", weight_ram);
|
| 121 |
+
```
|
| 122 |
+
|
| 123 |
+
### Rust
|
| 124 |
+
|
| 125 |
+
```rust
|
| 126 |
+
use std::fs;
|
| 127 |
+
|
| 128 |
+
fn load_q88(path: &str) -> Vec<f32> {
|
| 129 |
+
fs::read_to_string(path)
|
| 130 |
+
.unwrap()
|
| 131 |
+
.lines()
|
| 132 |
+
.filter(|l| !l.is_empty())
|
| 133 |
+
.map(|l| u16::from_str_radix(l.trim(), 16).unwrap() as f32 / 256.0)
|
| 134 |
+
.collect()
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
let thresholds = load_q88("dataset/merged_v2/parameters.mem");
|
| 138 |
+
let decay = load_q88("dataset/merged_v2/parameters_decay.mem");
|
| 139 |
+
let weights = load_q88("dataset/merged_v2/parameters_weights.mem");
|
| 140 |
+
```
|
| 141 |
+
|
| 142 |
+
### Julia
|
| 143 |
+
|
| 144 |
+
```julia
|
| 145 |
+
function load_q88(path::String)
|
| 146 |
+
[parse(Int, line, base=16) / 256.0 for line in eachline(path) if !isempty(line)]
|
| 147 |
+
end
|
| 148 |
+
|
| 149 |
+
thresholds = load_q88("dataset/merged_v2/parameters.mem")
|
| 150 |
+
decay = load_q88("dataset/merged_v2/parameters_decay.mem")
|
| 151 |
+
weights = load_q88("dataset/merged_v2/parameters_weights.mem")
|
| 152 |
+
```
|
| 153 |
+
|
| 154 |
+
## Training Results
|
| 155 |
+
|
| 156 |
+
| Metric | Value |
|
| 157 |
+
|--------|-------|
|
| 158 |
+
| Architecture | Julia-Rust hybrid |
|
| 159 |
+
| Algorithm | E-prop + OTTT |
|
| 160 |
+
| Accuracy | 95.2% |
|
| 161 |
+
| Convergence | 20 epochs |
|
| 162 |
+
| Training speed | 35 us/tick |
|
| 163 |
+
| IPC overhead | 0.8 us |
|
| 164 |
+
| Memory usage | 1.6 KB |
|
| 165 |
+
| Training date | 2026-03-22 |
|
| 166 |
+
| Data sources | Kaspa mainnet, Monero mainnet |
|
| 167 |
+
|
| 168 |
+
## Known Limitations
|
| 169 |
+
|
| 170 |
+
- **Monotonic hidden weight pattern**: The 256 hidden weights show a systematic linear ramp within each neuron (each weight increases by exactly 0x0001 Q8.8 ticks). This artifact is under investigation -- it may stem from the GPU-to-FPGA export pipeline or from telemetry data quality issues during training. The output weights do not show this pattern and appear correctly trained.
|
| 171 |
+
|
| 172 |
+
- **Purely excitatory hidden layer**: All 256 hidden weights are positive. The network lacks inhibitory connections (negative weights) and recurrent feedback, which limits its capacity for noise suppression and temporal memory. A future training run should add ~4 inhibitory neurons and recurrent connections.
|
| 173 |
+
|
| 174 |
+
## Hardware Baseline
|
| 175 |
+
|
| 176 |
+
| Component | Spec |
|
| 177 |
+
|-----------|------|
|
| 178 |
+
| CPU | AMD Ryzen 9 9950X |
|
| 179 |
+
| GPU | NVIDIA RTX 5080 (Blackwell SM_120) |
|
| 180 |
+
| FPGA | Digilent Basys3 (Xilinx Artix-7 xc7a35tcpg236-1) |
|
| 181 |
+
| FPGA Power | 97 mW total |
|
| 182 |
+
| FPGA LUTs | 1,063 / 20,800 (5.11%) |
|
| 183 |
+
| FPGA Registers | 1,091 / 41,600 (2.62%) |
|
| 184 |
+
| Timing WNS | 3.727 ns (37.27% margin) |
|
| 185 |
+
| OS | Fedora 43 |
|
| 186 |
+
|
| 187 |
+
## License
|
| 188 |
+
|
| 189 |
+
Dual-licensed under MIT and Apache-2.0. Developed independently by Raul Montoya Cardenas, Texas State University, Electrical Engineering (Spring 2026).
|
| 190 |
+
|
| 191 |
+
*"The mind is not a vessel to be filled, but a fire to be kindled."* -- Plutarch
|
config.json
CHANGED
|
@@ -11,11 +11,6 @@
|
|
| 11 |
"ipc_overhead_us": 0.8,
|
| 12 |
"memory_bytes": 1638,
|
| 13 |
"fpga_power_mw": 97,
|
| 14 |
-
"neuromod_version": "0.2.1",
|
| 15 |
-
"spikenaut_reward_version": "0.1.0",
|
| 16 |
-
"spikenaut_encoder_version": "0.1.0",
|
| 17 |
-
"spikenaut_backend_version": "0.1.0",
|
| 18 |
-
"spikenaut_fpga_version": "0.1.0",
|
| 19 |
"framework": "julia-rust-hybrid",
|
| 20 |
-
"license": "
|
| 21 |
}
|
|
|
|
| 11 |
"ipc_overhead_us": 0.8,
|
| 12 |
"memory_bytes": 1638,
|
| 13 |
"fpga_power_mw": 97,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
"framework": "julia-rust-hybrid",
|
| 15 |
+
"license": ["mit", "apache-2.0"]
|
| 16 |
}
|