4. 数据采集与预处理:数据采集卡选型、采样频率设置、数据清洗、缺失值处理、异常值检测

各位同学,咱们今天聊点实在的。

做风机叶片故障诊断,说白了就是跟数据打交道。数据要是烂了,后面模型再牛也白搭。我见过太多项目,算法调得飞起,结果一查,原始数据采集就有问题——那真是「垃圾进,垃圾出」。所以这一章,咱们把数据采集和预处理这摊事彻底捋清楚。

核心观点:数据质量决定了诊断系统的上限。采集阶段省下的功夫,会在预处理阶段加倍还回来。

数据采集与预处理 采集卡选型 通道数/分辨率/采样率 采样频率设置 奈奎斯特/抗混叠 数据清洗 去噪/滤波/格式统一 缺失值/异常值处理 插补/3σ/IQR 高质量数据 → 可靠诊断模型

4.1 数据采集卡选型——别在这上面省钱

采集卡这东西,我踩过坑。刚入行那会儿,图便宜买了个USB接口的采集卡,结果现场一接,信号漂得跟心电图似的。后来换了工业级PCIe采集卡,世界清净了。

选型时,我建议你盯死三个参数:

  • 通道数:叶片振动监测一般需要3-6个加速度传感器通道。别卡着边买,留1-2个备用通道。我习惯多买4通道,万一哪个坏了不用拆机。
  • 分辨率:至少16位,推荐24位。分辨率不够,微弱裂纹信号根本抓不到。你想想看,叶片早期裂纹的振动幅值可能只有正常信号的1/1000,分辨率低了直接淹没在量化噪声里。
  • 采样率:后面会细讲,但选型时至少按目标频率的5倍留余量。
参数 入门级 工业级 我推荐
通道数 4 8-16 8
分辨率 12位 16-24位 24位
最大采样率 100 kS/s 500 kS/s以上 200 kS/s
接口 USB PCIe/PXI PCIe

⚠ 避坑指南:我曾经在项目里用了某品牌的「通用采集卡」,结果现场电磁干扰严重,信号里全是50Hz工频噪声。后来换了带隔离的工业采集卡,问题才解决。记住:风机现场环境恶劣,隔离和抗干扰能力比参数更重要。

4.2 采样频率设置——不是越高越好

采样频率这事,很多新手容易走极端。要么觉得越高越好,直接上最高档;要么随便设个1kHz,觉得够用就行。其实都不对。

核心原则就一条:满足奈奎斯特采样定理,同时考虑实际信号带宽。

叶片故障的振动信号,主要能量集中在0-5kHz。我一般这样设:

  • 常规监测:采样率10kHz(5倍于最高频率)
  • 早期裂纹检测:采样率20kHz(留足余量)
  • 齿轮箱/轴承复合故障:采样率50kHz以上

为什么会这样?因为实际信号不是理想的正弦波。叶片裂纹会产生冲击信号,高频分量很丰富。你采样率设低了,这些冲击特征就丢了。我有个项目,客户坚持用5kHz采样,结果裂纹信号全被滤掉了,模型死活学不出来。后来改成20kHz,准确率直接从60%飙到92%。

💡 我的习惯:设置采样率时,先做一次预采集,看看信号的频谱分布。如果高频段还有能量,就提高采样率。别怕数据量大——现在硬盘便宜,数据丢了可就找不回来了。

4.3 数据清洗——把脏数据挡在门外

数据清洗,说白了就是「去伪存真」。我见过最离谱的数据:传感器线缆松动,采集到的信号全是50Hz工频噪声,但振幅看起来还挺正常。这种数据要是喂给模型,后果不堪设想。

我一般做三步清洗:

  1. 去直流分量:减去信号均值,消除传感器零漂。代码就一行:signal = signal - np.mean(signal)
  2. 带通滤波:保留0.5Hz-5kHz的有效频段。低于0.5Hz的是温度漂移,高于5kHz的是高频噪声。
  3. 去趋势项:用多项式拟合去除信号中的缓慢变化趋势。这个在长时间监测中特别重要。
# 我常用的清洗流程
import numpy as np
from scipy import signal as sg

def clean_vibration(data, fs=10000):
    # 1. 去直流
    data = data - np.mean(data)
    
    # 2. 带通滤波
    b, a = sg.butter(4, [0.5/(fs/2), 5000/(fs/2)], btype='band')
    data = sg.filtfilt(b, a, data)
    
    # 3. 去趋势
    data = sg.detrend(data, type='linear')
    
    return data

注意:滤波时一定要用filtfilt(零相位滤波),别用普通的lfilter。否则滤波后的信号会有相位偏移,时域特征全乱了。我刚开始就犯过这个错,后来被导师骂了一顿才改过来。

4.4 缺失值处理——别让空值毁了模型

风机运行中,传感器偶尔会掉线,或者通信中断,导致数据出现缺失。缺失值处理不当,模型训练时就会报错,或者学到错误规律。

我常用的三种方法:

  • 线性插值:缺失段较短(<10个点)时用。简单有效,不引入额外误差。
  • 前向填充:缺失段在信号平稳区时用。比如风机稳定运行时的振动数据,前后差异不大。
  • 删除整段:缺失段较长(>100个点)时,直接删掉。别心疼,强行插值反而会引入虚假特征。
# 缺失值处理示例
import pandas as pd

# 线性插值
df['vibration'] = df['vibration'].interpolate(method='linear')

# 前向填充
df['vibration'] = df['vibration'].fillna(method='ffill')

# 删除长缺失段
df = df.dropna(thresh=len(df.columns))

⚠ 我曾经踩过的坑:有个项目,我偷懒用了全局均值填充缺失值。结果模型训练时收敛很快,但测试时一塌糊涂。后来发现,均值填充把故障特征全抹平了。记住:缺失值处理没有万能方法,一定要根据数据特点来选。

4.5 异常值检测——揪出「害群之马」

异常值,就是那些明显偏离正常范围的数据点。可能是传感器受到撞击,也可能是电磁干扰。如果不处理,模型会把这些异常当成正常模式来学。

我常用的检测方法:

  • 3σ原则:超出均值±3倍标准差的数据视为异常。简单粗暴,适合正态分布的数据。
  • IQR方法:四分位距法。超出Q1-1.5*IQR或Q3+1.5*IQR的数据视为异常。对非正态分布更鲁棒。
  • 滑动窗口法:在局部窗口内计算均值和标准差,检测局部异常。适合非平稳信号。
# IQR异常检测
def detect_outliers_iqr(data):
    Q1 = np.percentile(data, 25)
    Q3 = np.percentile(data, 75)
    IQR = Q3 - Q1
    lower = Q1 - 1.5 * IQR
    upper = Q3 + 1.5 * IQR
    outliers = (data < lower) | (data > upper)
    return outliers

💡 我的经验:别一检测到异常就删掉。先看看异常值是不是真的「异常」。有时候叶片裂纹的早期信号,在统计上就是异常值——那正是我们要找的故障特征!我一般会先可视化,人工确认后再决定是删除还是保留。

好了,数据采集和预处理这块就聊到这儿。记住一句话:数据质量决定模型上限。后面咱们讲特征提取和模型训练,但前提是——你的数据得是干净的。