传感器采集到的原始监测数据几乎不可能完全干净,温度漂移、电磁干扰、硬件抖动都会让曲线看起来毛刺丛生。如果直接拿这些数据做分析或触发告警,很容易出现误报漏报。处理这类问题的核心思路分两步:先用滤波算法把噪声压下去,再用异常检测手段识别真正的异常点。这两步的目标不同,滤波追求还原真实信号,异常检测追求发现离群事件,混淆两者是数据预处理中常见的误区。

常用滤波算法的原理与选型
最简单的降噪手段是滑动平均滤波,它把最近N个采样点取平均值作为当前输出。这种方式实现简单、计算量小,对高频随机噪声抑制效果明显,缺点是会把信号的突变部分也抹平,响应存在滞后。对于温度、湿度这类变化缓慢的物理量,滑动平均通常足够;但对于振动、压力冲击等需要捕捉突变的场景,就不太合适了。
中值滤波则是对最近N个采样点排序后取中间值。它对脉冲型噪声的抑制能力远强于滑动平均,因为个别极端值在排序后很难成为中位数。比如激光测距偶尔返回一个明显偏离的读数,滑动平均会被拉偏,中值滤波则几乎不受影响。实际工程中经常把中值滤波和滑动平均串联使用:先用中值剔除脉冲,再用滑动平均平滑随机噪声。
def median_then_avg(data, median_win=5, avg_win=3):
# 第一步:中值滤波剔除脉冲噪声
medians = []
for i in range(len(data)):
window = data[max(0, i - median_win + 1): i + 1]
medians.append(sorted(window)[len(window) // 2])
# 第二步:滑动平均平滑随机噪声
result = []
for i in range(len(medians)):
window = medians[max(0, i - avg_win + 1): i + 1]
result.append(sum(window) / len(window))
return result如果系统对实时性和精度要求都比较高,卡尔曼滤波是更优的选择。它基于状态空间模型,通过预测和更新两个步骤递推估计系统状态,能够在噪声已知统计特性的前提下给出理论最优估计。卡尔曼滤波的优势在于滞后再小、平滑效果好,还能融合多传感器数据。代价是需要建立较准确的数学模型并整定过程噪声和观测噪声方差,调参成本较高。对于简单场景,一维卡尔曼滤波几十行代码即可实现,性价比依然很高。
class KalmanFilter1D:
def __init__(self, q=0.01, r=0.5, x0=0.0, p0=1.0):
self.q = q # 过程噪声方差
self.r = r # 观测噪声方差
self.x = x0 # 状态估计值
self.p = p0 # 估计协方差
def update(self, z):
# 预测
self.p = self.p + self.q
# 更新
k = self.p / (self.p + self.r)
self.x = self.x + k * (z - self.x)
self.p = (1 - k) * self.p
return self.x异常检测:从阈值法到智能算法
滤波解决的是噪声问题,而异常检测要回答的问题是:这个数据点是不是真的出了问题。最基础的方法是固定阈值检测,即设定上下限,超出即判为异常。它简单可靠,适合有明确物理边界的量,比如电机温度超过90度就告警。但固定阈值的短板也很明显:无法感知正常工况的动态变化,白天和夜间的温度基线不同,用同一套阈值必然产生误报。
3σ准则是对固定阈值的改进,假设数据服从正态分布,落在均值加减三倍标准差之外的概率只有约0.3%,这些点可以判定为异常。它的进化版本是滑动窗口3σ,即统计量基于最近一段窗口数据动态计算,从而适应基线漂移。再进一步就是基于移动中位数的MAD方法,即用中位数绝对偏差代替标准差,对异常值本身的鲁棒性更强,避免异常点污染统计量导致漏检。
import numpy as np
def mad_anomaly_detect(data, window=100, threshold=3.5):
flags = np.zeros(len(data), dtype=bool)
for i in range(window, len(data)):
seg = data[i - window:i]
med = np.median(seg)
mad = np.median(np.abs(seg - med))
# 避免除零
if mad == 0:
mad = 1e-8
score = 0.6745 * (data[i] - med) / mad
flags[i] = abs(score) > threshold
return flags当数据维度高、模式复杂时,统计方法可能力不从心,此时可以考虑机器学习方案。孤立森林通过随机切分特征空间来隔离样本,异常点因为稀疏、偏离主体分布,往往用很少几刀就能被隔离出来,因此检测速度快、适合流式数据。此外还有基于重构误差的自编码器、基于密度的局部离群因子LOF等。选择时要注意:有监督场景(已有异常标注)优先用分类模型;绝大多数监测场景没有标注,只能走无监督路线,这时孤立森林和LOF是实用起点。
工程实践中的组合策略与注意事项
真实系统里,滤波和异常检测通常不是二选一,而是组合成流水线。一个典型的链路是:原始数据先经过限幅滤波剔除物理上不可能的值,再经中值滤波去除脉冲,然后进入卡尔曼滤波或滑动平均平滑,最后在干净数据上运行动态阈值或孤立森林检测。检测到异常后不宜立即告警,建议加一层持续性判断,比如连续N个周期超限才触发,这样可以把偶发抖动和数据突变区分开。
几个容易踩的坑值得提醒。第一,滤波窗口越大平滑效果越好,但滞后越严重,用于闭环控制时可能引发振荡,窗口大小必须结合采样频率和控制周期权衡。第二,异常数据被剔除后要做标记而非直接删除,后续分析时这些点可能包含重要信息,比如传感器老化前兆。第三,检测算法上线后要持续评估误报率和漏报率,阈值不是一劳永逸的,工况变化、传感器更换后都需要重新校准。第四,尽量保留原始数据,处理后的数据作为衍生数据单独存储,方便算法迭代时回溯对比。
总结来说,监测数据降噪和异常识别是一个分层过滤的过程:噪声靠滤波算法压制,异常靠统计或机器学习方法捕捉,两者配合再加上持续告警和人工复核,才能构建一套稳定可信的监测数据质量保障体系。根据数据特性从简单方法入手,逐步升级算法复杂度,是性价比最高的实践路径。