#Project

Edge-Deployable Anomaly Detection for Industrial IoT

December 2025

My Bachelor’s thesis, built as an Undergraduate Research Fellow at the ICOM Research Group, University of Oviedo. It tests whether a machine-learning intrusion detector for Industrial IoT traffic can stay accurate under class imbalance, survive losing capture-specific features, catch attacks it was never trained on, and still run on edge hardware — four experiments on the Edge-IIoTset dataset, each isolating one constraint.

Supervised baseline: near-perfect, for the wrong reason

Tree-based ensembles (XGBoost, LightGBM, Extra Trees), tuned with SMOTE against the dataset’s heavy class imbalance, reach near-perfect scores on held-out traffic:

ModelAccuracyF1 (weighted)ROC AUC
XGBoost0.99750.99750.9999
LightGBM0.99740.99740.9999
Extra Trees0.99770.99771.0000
Binary classification (normal vs. attack) on Edge-IIoTset, full feature set.

SHAP analysis showed why: the top-ranked feature across all three models was frame.time.order — a property of the packet capture, not of the attack. Dropping it, along with the equally testbed-specific frame.time.delta and source/destination IP categories, cost every model about 2.6 accuracy points, quantifying how much of that near-perfect score was really about memorizing the network rather than detecting intrusions.

Reframing for zero-days: unsupervised anomaly detection

A supervised classifier can only recognize attack types it was trained on. The thesis’s central experiment reframes detection as unsupervised anomaly detection instead: each model sees only normal traffic during training and flags anything that deviates from it at test time.

DetectorAUROCAUPRCF1PrecisionRecall
Sliding-window statistics0.97540.99340.96830.98670.9505
Autoencoder0.83530.85010.69540.90940.5630
K-Means0.81540.79950.59830.87180.4554
Isolation Forest0.52660.64350.14840.66760.0835
Zero-day detection: models trained only on normal traffic, evaluated on the full normal+attack mix.

The best configuration doesn’t need a neural network at all: a sliding-window statistical baseline — z-scoring an aggregated window of live traffic against a normal-traffic profile — reaches 98.6% precision and 95.0% recall without a single attack label ever shown to the model.

Making it run on the edge

Both detector families were benchmarked on a Raspberry Pi 4 (8GB, no GPU):

DetectorTotal time (full test set)Per-packet costThroughput
Sliding-window statistics664 ms≈0.00033 ms≈3.07M packets/s
Autoencoder-based detector148,113 ms0.073 ms≈13.7K packets/s
Inference throughput on Raspberry Pi 4 (8GB RAM, no GPU).

The sliding-window detector is roughly 200× faster and needs nothing but NumPy — but the comparison isn’t apples-to-apples. It scores fixed-size blocks of 520 packets at a time, so it can only react once a whole window has filled, capping its reaction latency at that block size. The autoencoder-based detector scores every packet the instant it arrives, with no such lag, at the cost of a heavier per-sample computation and a neural-network runtime (ideally with hardware acceleration). Both are legitimate edge choices for different placements: the sliding-window detector suits a deeply constrained sensor node buried in high-traffic segments, while the autoencoder-based detector fits better at an edge gateway that needs per-packet reaction and can host a heavier runtime.

Full methodology, code, and reproducible figures are in the companion repository.

Resources