Honours dissertation project comparing temporal neural network architectures for EEG-based visual digit classification using the MindBigData open dataset.
This project investigates how well different deep learning architectures can decode which digit (0–9) a person is thinking about from raw EEG brain signals. Four consumer EEG headsets are evaluated across seven model architectures and two classification tasks.
Classification tasks:
- 10-class: Identify which digit (0–9) the subject was visualising
- Binary: Distinguish digit-evoked EEG from non-digit background activity
EEG devices:
| Device | Headset | Sample Rate | Channels |
|---|---|---|---|
| EP | Emotiv EPOC | 128 Hz | 14 |
| MW | NeuroSky MindWave | 512 Hz | 1 |
| MU | InteraXon Muse | 220 Hz | 4 |
| IN | Emotiv Insight | 128 Hz | 5 |
Models compared:
| Model | Architecture |
|---|---|
lstm |
Stacked Bidirectional LSTM |
cnn1d |
5-layer 1D Convolutional Network |
eegnet |
EEGNet (compact depthwise spatial convolution) |
tcn |
Temporal Convolutional Network (dilated causal) |
tcan |
TCN + Temporal Attention |
eegtcn |
EEGNet spatial stem → TCN backbone |
eegtcan |
EEGNet spatial stem → TCAN backbone |
mindbigdata-classifier/
├── src/
│ ├── txt_to_hdf5.py # Parse raw MindBigData TXT → HDF5
│ ├── data/
│ │ ├── preprocess.py # Filtering, normalisation, band power extraction
│ │ ├── dataset.py # tf.data pipeline
│ │ ├── band_power.py # Spectral band power (Delta–Gamma)
│ │ └── preprocessing.py # Butterworth filter, winsorise, z-score
│ ├── models/
│ │ ├── base.py # BaseTemporalModel (all models inherit)
│ │ ├── lstm.py, cnn1d.py, eegnet.py, tcn.py, tcan.py
│ │ ├── eegtcn.py, eegtcan.py, eeg_stem.py
│ │ └── metrics.py # SparseMacroF1 metric
│ ├── training/
│ │ ├── train.py # Main training CLI
│ │ ├── run_all.py # Batch runner (all models × devices × configs)
│ │ └── callbacks.py # TensorBoard, EarlyStopping, LR scheduling
│ ├── evaluation/
│ │ ├── confusion.py # Confusion matrix and classification reports
│ │ └── parse_experiments.py # Export experiment JSONs → CSV
│ └── tracking/
│ └── logger.py # Structured experiment JSON logging
├── configs/ # Training hyperparameters (JSON)
│ ├── config_10class_timeseries.json
│ ├── config_10class_bandpower.json
│ ├── config_binary_timeseries.json
│ └── config_binary_bandpower.json
├── experiments/ # Per-experiment artefacts (JSON, weights, TensorBoard logs)
├── results/ # Parsed CSVs for analysis and dashboard
├── notebooks/ # Jupyter analysis notebooks
├── eeg-dashboard/ # Next.js interactive results dashboard
├── data/
│ ├── raw/ # Raw MindBigData TXT files (not tracked)
│ ├── interim/ # Parsed HDF5, unfiltered (not tracked)
│ └── processed/ # Filtered, normalised HDF5 (not tracked)
├── docker-compose.yml # CPU, GPU, and TensorBoard services
├── Dockerfile
└── requirements.txt
Two input representations are supported, selectable via config:
Time-series (raw filtered waveform) Input shape after 2-second epoch extraction:
- EP:
(256, 14)— 2.0 s × 128 Hz × 14 channels - MW:
(1024, 1)— 2.0 s × 512 Hz × 1 channel - MU:
(440, 4)— 2.0 s × 220 Hz × 4 channels - IN:
(256, 5)— 2.0 s × 128 Hz × 5 channels
Band power (spectral features) Sliding-window FFT over 5 EEG bands (Delta, Theta, Alpha, Beta, Gamma):
- EP:
(25, 70)— 25 windows × (14 channels × 5 bands) - MW:
(25, 5)— 25 windows × (1 channel × 5 bands) - MU:
(24, 20)— 24 windows × (4 channels × 5 bands) - IN:
(25, 25)— 25 windows × (5 channels × 5 bands)
All signals are preprocessed offline before training:
- Notch filter (IN device only) — removes 50 Hz mains noise (other devices have hardware notch)
- Bandpass filter — 0.5–45 Hz, 4th-order Butterworth (zero-phase)
- Band power extraction (optional) — sliding-window periodogram → log₁₀ power per band
- Epoch extraction — resample to fixed 2-second window per device
- Winsorise — clip to 5th–95th percentile per channel per trial
- Z-score normalisation — per-device per-channel, using training set statistics only
Every training run produces a self-contained directory under experiments/:
experiments/EP_tcn_10class_timeseries_001/
├── EP_tcn_10class_timeseries_001.json # Full metadata, metrics, training history
├── model_summary.txt
├── model_architecture.png
├── best_model.keras
└── logs/ # TensorBoard event files
Experiment IDs follow the pattern: {device}_{model}_{dataset}_{representation}_{NNN}, or with an optional suffix: {device}_{model}_{dataset}_{representation}_{suffix}_{NNN} (pass --suffix to train.py).
An interactive Next.js dashboard visualises all experiment results. It reads CSVs exported by parse_experiments.py and provides:
- Overview comparisons across models and devices
- Per-experiment metrics (accuracy, macro-F1, AUC, loss)
- Training curves
- Confusion matrices
- Efficiency analysis (FLOPs, parameters, inference latency)
See INSTRUCTIONS_MAC.md or INSTRUCTIONS_WINDOWS.md for full pipeline setup guides.
See the platform-specific instruction files for complete setup:
- macOS / Linux: INSTRUCTIONS_MAC.md
- Windows (Docker): INSTRUCTIONS_WINDOWS.md
- Python 3.10+
- TensorFlow 2.15
- Node.js 18+ (dashboard only)
- CUDA 12.x + NVIDIA GPU (recommended for training; CPU supported)
Raw data is not included in this repository. Download the MindBigData dataset from mindbigdata.com/opendb and place the .txt files in data/raw/.
Research project — not licensed for commercial use.