"Neural Decoding of Motor Kinematics using Linear and Non-Linear models" Vidya Sagar Venna USC EE675 Final Project - Fall 2025
This submission contains all code to reproduce the results from Table III of the paper:
- Kalman Filter: R² = 0.572
- PSID: R² = 0.596
- NDM (unsupervised): R² = 0.524
- Mamba (nonlinear): R² = 0.648
submission/
├── README.md # This file
├── RESULTS_VERIFICATION.md # Comparison of paper vs actual results
├── matlab_code/ # MATLAB implementations
│ ├── kalman_project_complete.m # Kalman Filter (Table I-II, Fig 1-4)
│ ├── psid_autotune.m # PSID (Table III, Fig 5-7)
│ ├── PSID.m # PSID helper (reference)
│ └── PSIDPredict.m # Kalman wrapper (reference)
├── python_code/ # Python implementations
│ ├── demo_ndm.py # NDM baseline
│ ├── demo_mamba.py # Mamba decoder
│ ├── mamba_science.py # Robustness analysis (Table IV, Fig 8-10)
│ ├── compare_ndm_mamba.py # Comparative analysis
│ ├── requirements.txt # Python dependencies
│ └── src/ # Supporting modules
│ ├── data/
│ │ └── data_loader.py # Data loading utilities
│ └── models/
│ └── mamba_decoder.py # Mamba implementation
├── data/ # Place dataset here (see below)
└── results/ # Output directory (auto-created)
indy_20160407_02.mat - Motor cortex reaching data from O'Doherty et al. (2017)
Option 1: Modify code paths (recommended)
- Place data file in
submission/data/indy_20160407_02.mat - Update file paths at top of each script (see instructions below)
Option 2: Place in multiple locations
- For MATLAB codes:
submission/matlab_code/indy_20160407_02.mat - For Python codes:
submission/python_code/data/583331/indy_20160407_02.mat
MATLAB files (kalman_project_complete.m, psid_autotune.m):
- Line 14 (Kalman) / Line 21 (PSID): Change
FILENAME = 'indy_20160407_02.mat'; - To:
FILENAME = '../data/indy_20160407_02.mat';
Python files (demo_ndm.py, demo_mamba.py, mamba_science.py):
- Change:
DATA_FILE = 'data/583331/indy_20160407_02.mat' - To:
DATA_FILE = '../data/indy_20160407_02.mat'
- Version: MATLAB R2020a or newer
- Toolboxes: None required (uses only base MATLAB functions)
- Version: Python 3.8 or newer
- Dependencies:
numpy >= 1.20.0 scipy >= 1.7.0 scikit-learn >= 1.0.0 torch >= 2.0.0 h5py >= 3.0.0 matplotlib >= 3.5.0
Installation:
cd python_code
pip install -r requirements.txtcd matlab_code
matlab -batch "kalman_project_complete"- Runtime: ~30-60 seconds
- Outputs: Console results, 6+ figures showing:
- Bin width optimization (Table I)
- Lag tuning and regularization sweeps
- Trajectory comparison (true vs filtered vs smoothed)
- Velocity time series
- Residual diagnostics
- Stability analysis (eigenvalue plot)
- Neuron dropout robustness curve (Table II, Fig 4)
- Expected R²:
- Kalman Filter: 0.572
- RTS Smoother: 0.621
cd matlab_code
matlab -batch "final_psid_project"- Runtime: ~2-5 minutes (grid search over 32 configurations)
- Outputs: 6+ figures showing:
- R² heatmap over (latent dims, history lags)
- 2D velocity trajectories (true vs decoded)
- Time series plots (vx, vy)
- 2D & 3D latent dynamics (colored by speed)
- Singular value spectrum
- Decoder weights visualization
- PSID vs PCA comparison (Fig 7)
- Expected R²: 0.596 (vx: 0.566, vy: 0.625)
- Optimal hyperparameters: nx1=20, lag=500ms
cd python_code
python demo_ndm.py- Runtime: ~5-10 seconds
- Outputs:
- Console results with R² scores
- Velocity decoding time series plots
- Model saved to
results/ndm_results.npy
- Expected R²: 0.524 (vx: 0.471, vy: 0.577)
cd python_code
python demo_mamba.py- Runtime: ~6-10 minutes (50 epochs training)
- Outputs:
- Training progress with loss curves
- Model checkpoint:
results/mamba_model.pth - Metrics:
results/mamba_metrics.json - Comparison figures:
results/figures/mamba_results.png - Velocity scatter plots (predicted vs true)
- Method comparison bar chart
- Expected R²: 0.648 (vx: 0.685, vy: 0.612)
- Note: May vary ±0.02 due to random weight initialization
cd python_code
python mamba_science.py- Runtime: ~10-15 minutes
- Outputs:
- Robustness curve (neuron dropout analysis)
- Regime-stratified error analysis:
- Speed-based (low/medium/high)
- Curvature-based (straight/moderate/sharp)
- Spectral coherence analysis (PSID vs Mamba)
- Hybrid ensemble decoder results
- Saved results:
results/mamba_science_results.json - Figures:
results/mamba_science_analysis.png
- Key findings:
- Robustness: PSID degrades gracefully, Mamba has cliff at 30% dropout
- Nonlinearity: Mamba excels at high-speed, high-curvature movements
- Hybrid: Combines robustness of PSID with precision of Mamba
| Method | R² (Overall) | R² (vx) | R² (vy) | Latent Dim | Training Time |
|---|---|---|---|---|---|
| Kalman Filter | 0.572 | 0.580 | 0.560 | 5 | <1 min |
| PSID | 0.596 | 0.566 | 0.625 | 20 | 2-5 min |
| NDM | 0.524 | 0.471 | 0.577 | 30 | <10 sec |
| Mamba | 0.648 | 0.685 | 0.612 | 16 | 6-10 min |
Performance Hierarchy: NDM < Kalman < PSID < Mamba Clinical Viability: PSID > Kalman > Mamba (based on robustness analysis)
If you see ModuleNotFoundError: No module named 'src':
# Ensure you're running from python_code/ directory
cd python_code
python demo_mamba.pyIf you see Dataset indy_20160407_02.mat not found:
- Check data file is in correct location (see Dataset Setup above)
- Or modify
FILENAMEvariable at top of each .m file
If Python scripts fail with directory errors:
mkdir -p results/figuresIf you see CUDA warnings but have no GPU:
- Code will automatically fall back to CPU
- Training will be slower (~10-15 min instead of 6-10 min)
- Results are identical
Results within ±5% of paper values are considered valid due to stochastic initialization in neural network models.
-
kalman_project_complete.m(336 lines)- Three hyperparameter experiments (bin width, lag, regularization)
- Kalman filter + RTS smoother implementation
- Residual diagnostics, stability analysis, robustness testing
-
psid_autotune.m(657 lines)- Grid search over latent dimensions (2-20) and history lags (250ms-1s)
- PSID algorithm with Kalman filtering
- PSID vs PCA comparison demonstrating behavioral subspace isolation
-
PSID.m,PSIDPredict.m(reference files, not required)
demo_ndm.py- Unsupervised baseline (NDM)demo_mamba.py- Nonlinear state-space decodermamba_science.py- Robustness & regime analysiscompare_ndm_mamba.py- Side-by-side comparisonsrc/data/data_loader.py- Data preprocessing utilitiessrc/models/mamba_decoder.py- Mamba architecture implementation
- Table I: Bin width optimization (250ms optimal)
- Table II: Neuron dropout robustness
- Table III: Method comparison (NDM/Kalman/PSID/Mamba)
- Table IV: Electrode failure (PSID vs Mamba)
- Table V: Computational cost comparison
- Fig 1-3: Kalman hyperparameter sweeps
- Fig 4: Neuron dropout curve
- Fig 5-7: PSID latent dynamics and PCA comparison
- Fig 8: Mamba robustness and regime analysis
- Fig 9: Spectral coherence (frequency domain)
- Fig 10: Hybrid ensemble robustness
- Reproducibility: Kalman, PSID, and NDM are deterministic. Mamba has stochastic initialization (±0.02 variance in R²).
- Computational Resources: All codes run on CPU. Mamba benefits from GPU but not required.
- Figures: Displayed automatically. Save manually or modify code to auto-save.
- Data Format: Code expects .mat file in HDF5 v7.3 format (standard for O'Doherty dataset).
For questions or issues:
- Author: Vidya Sagar Venna
- Email: vvenna@usc.edu
- Course: EE 675 - Data Analysis and Control Techniques for Neurotechnology Design
- Instructor: Prof. Maryam M. Shanechi
- Institution: University of Southern California
- O'Doherty et al. (2017). "Nonhuman primate reaching with multichannel sensorimotor cortex electrophysiology." Zenodo.
- Sani et al. (2021). "Modeling behaviorally relevant neural dynamics enabled by preferential subspace identification." Nature Neuroscience.
- Wu et al. (2006). "Bayesian population decoding of motor cortical activity using a Kalman filter." Neural Computation.
- Gu & Dao (2023). "Mamba: Linear-Time Sequence Modeling with Selective State Spaces."
This code is provided for academic and research purposes. Please cite the paper if you use this code in your work.