Skip to main content

Bayesian QDA (NimbusQDA)

Python: NimbusQDA | Julia: NimbusQDA
Mathematical Model: Heteroscedastic Gaussian Classifier (HGC)
NimbusQDA is a Bayesian classification model with class-specific covariance matrices, making it more flexible than NimbusLDA for modeling complex class distributions.
Python Personalizer head: use as Personalizer(head="qda"), or standalone as NimbusQDA. See Personalizer & Middleware.
Available in Both SDKs:
  • Python SDK: NimbusQDA class (sklearn-compatible)
  • Julia SDK: NimbusQDA (RxInfer.jl-based)
Both implementations provide class-specific covariances for flexible modeling.

Start Here

Quickstart

Start with SDK setup and first inference workflow.

Model Selection

Compare Nimbus models by data characteristics and use case.

Examples

See practical BCI examples for training and inference.

Overview

Bayesian QDA extends beyond traditional Gaussian classifiers by allowing each class to have its own covariance structure: ✅ Class-specific covariances (unlike Bayesian LDA’s shared covariance)
More flexible modeling of heterogeneous distributions
Posterior probability distributions with uncertainty quantification
Fast inference (~15-25ms per trial)
Training and calibration support
Batch and streaming inference modes

Quick Start

When to Use Bayesian QDA

Bayesian QDA is ideal for:
  • Complex, overlapping class distributions
  • Classes with significantly different variances
  • P300 detection (target/non-target with different spreads)
  • When Bayesian LDA accuracy is unsatisfactory
  • When you need maximum flexibility
Use Bayesian LDA instead if:
  • Classes are well-separated and have similar spreads
  • Speed is critical (Bayesian LDA is faster)
  • Training data is limited (Bayesian LDA needs less data)
  • Memory is constrained (Bayesian LDA uses less memory)

Model Architecture

Mathematical Foundation (Heteroscedastic Gaussian Classifier)

Bayesian QDA implements a Heteroscedastic Gaussian Classifier (HGC), which models class-conditional distributions with class-specific precision matrices:
Where:
  • μ_k = mean vector for class k
  • W_k = class-specific precision matrix (different for each class)
  • Allows different covariance structures per class
Key Difference from Bayesian LDA: Each class can have its own covariance structure, making the model more flexible but also more parameter-heavy.

Hyperparameters

Bayesian QDA supports configurable hyperparameters for optimal performance tuning: Available Hyperparameters (training): Parameter Effects:
  • dof_offset: Controls regularization strength
    • Lower values (1) → More data-driven, less regularization
    • Higher values (3-5) → More regularization, more conservative
  • mean_prior_precision: Controls prior strength on class means
    • Lower values (0.001) → Weaker prior, trusts data more
    • Higher values (0.05-0.1) → Stronger prior, more regularization

Model Structure

RxInfer Implementation

Learning Phase:

Usage

1. Load Pre-trained Model

Python SDK: The Python SDK (nimbus-bci) trains models locally. See Python SDK Quickstart for training examples.

2. Train Custom Model

Training Parameters:
  • iterations: Number of variational inference iterations (default: 50)
    • More iterations = better convergence, typical range: 50-100
  • showprogress: Display progress bar during training
  • name: Model identifier
  • description: Model description
  • dof_offset: Degrees of freedom offset (default: 2, range: [1, 5])
  • mean_prior_precision: Prior precision for means (default: 0.01, range: [0.001, 0.1])

3. Subject-Specific Calibration

Calibration Benefits:
  • Requires only 10-20 trials per class
  • Faster than training from scratch
  • Adapts to subject-specific characteristics
  • Hyperparameters preserved: calibrate_model() automatically uses the same hyperparameters as the base model (v0.2.0+)

4. Batch Inference

5. Streaming Inference

For detailed Python streaming examples, see Python SDK Streaming Inference.

Hyperparameter Tuning (v0.2.0+)

Fine-tune Bayesian QDA for optimal performance on your specific dataset.

When to Tune Hyperparameters

Consider tuning when:
  • Default performance is unsatisfactory
  • You have specific data characteristics (very noisy or very clean)
  • You have limited or extensive training data
  • Working with complex, overlapping class distributions
  • P300 or other paradigms with heterogeneous class variances

Tuning Strategies

For High SNR / Clean Data / Many Trials

Use lower regularization to let the data drive the model:
Use when:
  • SNR > 5 dB
  • 100+ trials per class
  • Clean, artifact-free data
  • Well-controlled experimental conditions

For Low SNR / Noisy Data / Few Trials

Use higher regularization for stability (especially important for QDA with class-specific covariances):
Use when:
  • SNR < 2 dB
  • 40-80 trials per class
  • Noisy data or limited artifact removal
  • Challenging recording conditions
  • Risk of overfitting to class-specific noise

Balanced / Default Settings

The defaults work well for most scenarios:
Use when:
  • Moderate SNR (2-5 dB)
  • 80-150 trials per class
  • Standard BCI recording conditions
  • Starting point for experimentation

P300-Specific Tuning

For P300 paradigms where target/non-target classes have different variances:

Hyperparameter Search Example

Systematically search for optimal hyperparameters:

Quick Tuning Guidelines

Pro Tip: Bayesian QDA’s class-specific covariances can overfit to noise with poor data. When in doubt, start with defaults and increase regularization (dof_offset=3, mean_prior_precision=0.03) if you see overfitting.
Important: Always set predictive_dof_offset to match dof_offset for consistency between training and inference phases.

Training Requirements

Data Requirements

  • Minimum: 40 trials per class (80 total for 2-class)
  • Recommended: 80+ trials per class
  • For calibration: 10-20 trials per class
Bayesian QDA requires at least 2 observations per class to estimate class-specific statistics. Training will fail if any class has fewer than 2 observations.

Feature Normalization

Critical for cross-session BCI performance!Normalize your features before training for 15-30% accuracy improvement across sessions.
See Feature Normalization for the recommended train/test scaling workflow.

Feature Requirements

Bayesian QDA expects preprocessed features, not raw EEG: Required preprocessing:
  • Bandpass filtering (paradigm-specific)
  • Artifact removal
  • Feature extraction (CSP, ERP amplitude, bandpower, etc.)
  • Proper temporal aggregation
NOT accepted:
  • Raw EEG channels
  • Unfiltered data
See Preprocessing Requirements.

Performance Characteristics

Computational Performance

Slightly slower than NimbusLDA due to class-specific covariances.

Classification Accuracy

Bayesian QDA typically provides 2-5% higher accuracy than Bayesian LDA when class covariances differ significantly, at the cost of ~5-10ms additional latency.

Model Inspection

View Model Parameters

Accessing model parameters: The SDK stores full posterior distributions (not just point estimates) for proper Bayesian inference. To get point estimates, use mean(posterior) to extract the mean of the posterior distribution. For precision matrices, use mean(precision_posterior) to get the expected precision matrix.

Visualize Class Differences

Advantages & Limitations

Advantages

Flexible Modeling: Each class has its own covariance
Better for Complex Data: Handles heterogeneous distributions
Higher Accuracy: 2-5% improvement when classes differ significantly
Uncertainty Quantification: Full Bayesian posteriors
Production-Ready: Battle-tested in P300 applications

Limitations

More Parameters: Requires more training data than NimbusLDA
Slower Inference: ~15-25ms vs ~10-15ms for NimbusLDA
Higher Memory: Stores n_classes precision matrices
More Complex: Longer training time

Model Selection Context

Use NimbusQDA when the task is stationary but classes have different spreads, covariance structure, or overlapping distributions. If speed and simple class structure matter more, start with NimbusLDA. If the boundary is non-Gaussian, consider NimbusSoftmax in Python or NimbusProbit in Julia. If class distributions drift over time, use NimbusSTS in Python. For the canonical side-by-side comparison, see Model Specification.

Practical Examples

P300 Detection

When Bayesian LDA Fails

Next Read

Bayesian LDA (NimbusLDA)

Faster model with shared covariance

NimbusSoftmax (Python)

Python non-Gaussian static classifier for complex decision boundaries

NimbusProbit (Julia)

Julia non-Gaussian static classifier for complex decision boundaries

Bayesian STS (NimbusSTS)

Adaptive model for non-stationary data

Training Guide

Complete training tutorial

Code Examples

Working examples

References

Implementation: Theory:
  • Bishop, C. M. (2006). “Pattern Recognition and Machine Learning” (Quadratic discriminant analysis and Gaussian classifiers)
  • Heteroscedastic Gaussian Classifier (HGC) with class-specific covariances
BCI Applications:
  • Farwell, L. A., & Donchin, E. (1988). “Talking off the top of your head”
  • Lotte et al. (2018). “A review of classification algorithms for EEG-based BCI”