TECHNICAL BLOG

Deep Dives for Engineers

Detailed technical articles covering the real problems we solve in embedded systems, AI, and robotics engineering.

Anomaly Detection in Industrial IoT Sensor Data Using Machine Learning
Machine Learning

Anomaly Detection in Industrial IoT Sensor Data Using Machine Learning

Worksprout Team Feb 14, 2025 10 min read

Practical approaches to detecting anomalies in high-frequency IoT sensor streams — from statistical baselines to LSTM autoencoders — with deployment considerations for edge and cloud.

The Anomaly Detection Challenge in IoT

Industrial IoT deployments generate continuous streams of sensor data — temperature, vibration, current draw, pressure, flow rate — at frequencies from 1 Hz to 10 kHz. Anomalies in these streams often precede equipment failures by hours or days. Detecting them reliably requires algorithms that handle temporal correlations, non-stationary distributions, and heavily imbalanced datasets where normal data vastly outnumbers anomalous events.

Establishing Baselines: Statistical Methods

Before reaching for deep learning, validate simpler statistical approaches. Z-score detection on a rolling window is often sufficient for sensors with near-Gaussian distributions:

import pandas as pd
import numpy as np

def rolling_zscore_anomaly(series: pd.Series, window: int = 60, threshold: float = 3.5) -> pd.Series:
    rolling_mean = series.rolling(window, center=True).mean()
    rolling_std = series.rolling(window, center=True).std()
    z_scores = (series - rolling_mean) / (rolling_std + 1e-8)
    return z_scores.abs() > threshold

df["anomaly"] = rolling_zscore_anomaly(df["temperature_c"], window=120, threshold=3.0)

For multivariate sensors, Isolation Forest provides strong unsupervised baseline performance with minimal tuning:

from sklearn.ensemble import IsolationForest

model = IsolationForest(n_estimators=200, contamination=0.01, random_state=42)
df["anomaly_score"] = model.fit_predict(df[["temp", "vibration", "current"]])

LSTM Autoencoder for Temporal Anomalies

When anomalies manifest as pattern deviations over time — a motor that gradually increases vibration over 30 minutes before failure — LSTM autoencoders are effective. They learn to reconstruct normal sequences; reconstruction error spikes on anomalous inputs.

import torch
import torch.nn as nn

class LSTMAutoencoder(nn.Module):
    def __init__(self, input_size: int, hidden_size: int, num_layers: int):
        super().__init__()
        self.encoder = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
        self.decoder = nn.LSTM(hidden_size, input_size, num_layers, batch_first=True)

    def forward(self, x):
        _, (h, c) = self.encoder(x)
        # Repeat context vector for each timestep
        context = h[-1].unsqueeze(1).repeat(1, x.size(1), 1)
        output, _ = self.decoder(context)
        return output

def compute_anomaly_score(model, sequence, threshold):
    with torch.no_grad():
        reconstruction = model(sequence)
        mse = nn.functional.mse_loss(reconstruction, sequence, reduction="none")
        score = mse.mean(dim=[1, 2])
        return score > threshold

Setting the Threshold

Threshold selection is where most anomaly detection systems fail in production. Setting it too low floods on-call teams with false positives; too high misses real failures. Best practice:

  • Collect reconstruction errors over a representative normal period
  • Set threshold at the 99.5th percentile — this yields approximately 0.5% false positive rate on normal data
  • Validate against any labeled historical failure events if available
  • Use a hysteresis band: alert when N consecutive windows exceed the threshold, not on a single spike

Edge vs Cloud Deployment

For low-latency anomaly detection that must act before a cloud round-trip, deploy the model at the edge. Export the trained model to ONNX and run it on the Jetson Nano or Raspberry Pi:

import onnxruntime as ort
import numpy as np

session = ort.InferenceSession("autoencoder.onnx")
input_name = session.get_inputs()[0].name

def detect_anomaly_edge(window: np.ndarray) -> bool:
    reconstruction = session.run(None, {input_name: window[np.newaxis, ...]})[0]
    mse = np.mean((reconstruction - window) ** 2)
    return mse > THRESHOLD

Use cloud models for deeper historical analysis and threshold calibration, edge models for real-time response.

Conclusion

Start with statistical methods and Isolation Forest — they provide strong baselines with minimal data requirements and are interpretable. Add LSTM autoencoders when temporal pattern learning is needed. Always invest heavily in threshold calibration and production monitoring. An anomaly detection system that cries wolf is worse than none — it trains operators to ignore it.

Share

Worksprout Team

The Worksprout engineering team specialises in embedded Linux, RDK-B broadband platforms, edge AI, and robotics systems. Based in Rajshahi, Bangladesh, we design and deploy production embedded intelligence for clients across South Asia and beyond.

Related Posts

Continue reading — handpicked articles you might enjoy