4. 数据采集与预处理:数据采集卡选型、采样频率设置、数据清洗、缺失值处理、异常值检测
各位同学,咱们今天聊点实在的。
做风机叶片故障诊断,说白了就是跟数据打交道。数据要是烂了,后面模型再牛也白搭。我见过太多项目,算法调得飞起,结果一查,原始数据采集就有问题——那真是「垃圾进,垃圾出」。所以这一章,咱们把数据采集和预处理这摊事彻底捋清楚。
核心观点:数据质量决定了诊断系统的上限。采集阶段省下的功夫,会在预处理阶段加倍还回来。
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工频噪声,但振幅看起来还挺正常。这种数据要是喂给模型,后果不堪设想。
我一般做三步清洗:
- 去直流分量:减去信号均值,消除传感器零漂。代码就一行:
signal = signal - np.mean(signal) - 带通滤波:保留0.5Hz-5kHz的有效频段。低于0.5Hz的是温度漂移,高于5kHz的是高频噪声。
- 去趋势项:用多项式拟合去除信号中的缓慢变化趋势。这个在长时间监测中特别重要。
# 我常用的清洗流程
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
💡 我的经验:别一检测到异常就删掉。先看看异常值是不是真的「异常」。有时候叶片裂纹的早期信号,在统计上就是异常值——那正是我们要找的故障特征!我一般会先可视化,人工确认后再决定是删除还是保留。
好了,数据采集和预处理这块就聊到这儿。记住一句话:数据质量决定模型上限。后面咱们讲特征提取和模型训练,但前提是——你的数据得是干净的。