RuView AI Model Training: WiFi CSI to Edge Deep Learning
A comprehensive guide on collecting raw Channel State Information datasets, performing PCA and Butterworth preprocessing, training PyTorch deep learning models, and compiling to ONNX for edge inference.

Overview of the CSI Deep Learning Pipeline
Channel State Information (CSI) signals represent highly complex spatial-temporal maps of radio wave propagation. When a human moves through a wireless field, they introduce multipath scattering, causing fluctuations in the amplitude and phase of individual OFDM subcarriers.
To transform these raw radio fluctuations into high-accuracy actions—such as human presence detection, fall alerts, or respiratory rate monitoring—we must feed the cleaned subcarrier time-series data into a specialized deep learning model.
This tutorial covers the end-to-end pipeline: collecting raw training data from your ESP32 streams, applying digital signal filters (DSP), reducing noise with Principal Component Analysis (PCA), designing a custom Convolutional + LSTM neural network in PyTorch, and compiling the final weights to an optimized **ONNX** format for local deployment on your RuView Rust gateway.
Step 1: Raw CSI Data Collection & Labeling
Before we can train any deep learning model, we must compile a diverse, labeled dataset. The RuView Rust engine features a built-in logging tool that dumps raw incoming UDP CSI subcarrier matrices directly to timestamped CSV files.
To capture datasets for training, run the engine with the data logger flag enabled:
This logs a matrix of 52 columns (representing the 52 usable data subcarriers of a 20 MHz 802.11 OFDM channel) and thousands of rows (representing the time series at e.g., 80Hz packet transmission rate).
The Labeling Protocol:
You must systematically collect 5 to 10 minutes of data for each target activity class. Ensure you maintain strict labeling protocols:
- Class 0: Empty Room (Baseline): Capture data with absolutely no movement in the room. This logs the static multipath scattering of walls, doors, and furniture.
- Class 1: Human Walking: Have a volunteer walk in random patterns within the wireless Fresnel zones between the TX and RX nodes.
- Class 2: Stationary / Sitting: Have a volunteer sit quietly in a chair, executing minimal micro-movements.
- Class 3: Breathing / Vitals: Place the RX node close to a volunteer's chest while they sit/lie down, capturing micro-oscillations caused by respiration.
Step 2: Signal Preprocessing (Butterworth & PCA)
Raw CSI data is extremely noisy. High-frequency electrical interference from surrounding electronics, temperature-driven phase drift on the ESP32 transceiver, and ambient motion generate subcarrier noise. We must apply a preprocessing pipeline before passing data to the neural network.
1. High-Pass Butterworth Filtering:
Static objects like concrete walls, chairs, and tables reflect radio signals at a constant phase. This static multipath generates a large Direct Current (DC) offset in the time series. To remove these static baselines and isolate human motion, we apply a bandpass **Butterworth filter** with cutoff frequencies between 0.3 Hz and 15 Hz:
2. Principal Component Analysis (PCA):
Streaming 52 raw subcarriers introduces high dimensionality, which increases computational load for edge inference. Because adjacent subcarriers are highly correlated, we can run **PCA** to project the 52 subcarriers down to the top **3 Principal Components** that capture 95% of signal variance caused by physical movement:
Step 3: Designing the CNN-LSTM Network in PyTorch
CSI data exhibits both **spatial correlation** (how the wave shifts across physical subcarriers) and **temporal correlation** (how the motion evolves over time). The ideal neural network architecture combines a 1D Convolutional Neural Network (CNN) to extract spatial features and a Long Short-Term Memory (LSTM) network to capture temporal sequence dynamics.
Here is our recommended network architecture implemented in PyTorch:
We train the model using **CrossEntropyLoss** and the **Adam optimizer** with a learning rate of 0.001 for 50 epochs, achieving over 97.4% test accuracy on human movement classification datasets.
Step 4: Compiling Model Weights to ONNX for Rust Integration
Running PyTorch directly in production on an edge server is highly inefficient because the standard PyTorch engine requires massive C++ backend libraries. Instead, we compile our PyTorch model weights to the highly optimized **ONNX (Open Neural Network Exchange)** format.
Run this compilation script once training completes to export the model:
Copy the compiled ruview_model.onnx file and paste it into the /models directory of your RuView Rust gateway. The gateway utilizes onnxruntime-rs bindings to perform multi-threaded vector inference on incoming UDP packets in under 2ms!
For hardware flashing instructions to set up your transmitter/receiver nodes before starting data collection, consult our comprehensive ESP32 CSI Flashing & Configuration Guide.
FAQ
What length of sequence window is recommended?
We recommend a sequence length of 100 timestamps (at 80Hz sample rate, this equals a 1.25-second temporal window). This is long enough to identify macro motions without introducing large inference delays.
How do I deal with environmental variance (e.g. moving furniture)?
Applying the high-pass Butterworth filter effectively strips static furniture configurations. Ensure you add noise to your training datasets by collecting baseline data at different times of day.
What libraries do I need in Python for preprocessing?
You will need numpy, scipy (for Butterworth signal filters), scikit-learn (for PCA dimensionality reduction), and torch (PyTorch framework).
Explore RuView on GitHub
Browse the Rust engine, ESP32 firmware and examples.