3. 信号处理与特征提取

各位同事,咱们搞风电运维的,每天面对的就是一堆传感器数据。振动、温度、电流……这些原始信号就像病人的心电图,光看波形是看不出名堂的。你得会“翻译”,把信号里的故障特征给揪出来。

我个人习惯把特征提取分成三大类:时域、频域、时频域。说白了,就是三个不同的“放大镜”,各有各的用处。今天咱们就一个一个捋清楚。

核心逻辑:信号处理的目的,是把高维、冗余的原始数据,压缩成低维、敏感的特征向量,喂给后面的诊断模型。这一步做不好,后面全是白搭。

信号处理与特征提取知识体系 原始振动/电流信号 时域特征 频域特征 时频域特征 均值/方差 峭度/偏度 峰值因子 FFT频谱 包络谱 边频分析 小波变换 EMD分解 希尔伯特谱 特征选择与降维:PCA / t-SNE

3.1 时域特征:最直观的“体检报告”

时域特征,就是直接在时间轴上算统计量。你想想看,一个健康的轴承,振动波形应该是平稳的、随机的。一旦出现故障,波形就会“炸毛”。

常用的时域指标:

特征 物理意义 故障敏感度
均值 信号的平均水平,反映静态分量 低(对磨损不敏感)
方差/标准差 信号的能量波动,反映振动剧烈程度 中(能看出整体恶化)
峭度 信号分布的“尖峰”程度 高(对早期冲击故障非常敏感)
偏度 信号分布的不对称性 中(反映磨损方向性)
峰值因子 峰值与有效值的比值 高(识别冲击性故障)

我的经验:峭度这个指标,我建议你重点关注。我在项目中遇到过好几次,轴承早期出现点蚀时,有效值还没什么变化,峭度已经飙升了。它就像个“侦察兵”,能提前预警。

举个例子,计算峭度的Python代码很简单:

import numpy as np

def calculate_kurtosis(signal):
    # 信号去均值
    x = signal - np.mean(signal)
    # 计算四阶矩
    n = len(x)
    kurt = (np.sum(x**4) / n) / (np.var(signal)**2) - 3
    return kurt

# 假设你采集了一段振动数据
vibration_data = np.random.randn(1024)  # 模拟健康信号
print(f"峭度值: {calculate_kurtosis(vibration_data):.2f}")

3.2 频域特征:把信号“掰开揉碎”看成分

时域看不出来的东西,换到频域就一目了然。比如齿轮的啮合频率、轴承的故障特征频率,在频谱上就是一根根“谱线”。

FFT(快速傅里叶变换)是最基础的工具。但我要提醒你,直接做FFT有个坑——它假设信号是平稳的。风电的转速经常变,直接做FFT会得到一堆“糊”在一起的频谱。

避坑指南:我曾经在变桨轴承诊断上吃过亏。直接用原始振动信号做FFT,频谱上全是干扰。后来我加了阶次跟踪,把时域信号重采样到角度域,才把故障特征频率清晰地分离出来。记住:变转速工况下,先做阶次跟踪,再做FFT。

包络谱是另一个利器。它专门用来解调高频冲击信号。比如轴承内圈故障,冲击会调制在高频共振上。包络谱能把那个“调制信号”解出来,看到清晰的故障频率。

from scipy import signal
import numpy as np

def envelope_spectrum(data, fs):
    # 希尔伯特变换求包络
    analytic_signal = signal.hilbert(data)
    envelope = np.abs(analytic_signal)
    # 对包络做FFT
    freqs = np.fft.rfftfreq(len(envelope), 1/fs)
    spectrum = np.fft.rfft(envelope)
    return freqs, np.abs(spectrum)

3.3 时频域特征:给信号拍“CT”

时域和频域各有局限。时域看不到频率成分,频域看不到时间变化。时频域分析,就是给信号拍“CT”,同时看到时间和频率两个维度。

小波变换是我个人比较喜欢的方法。它用不同尺度的“小波”去匹配信号,能同时捕捉到突变和缓变。比如叶片开裂瞬间的冲击,小波能精确定位到发生时刻。

经验模态分解(EMD)则更“智能”。它不需要预设基函数,完全根据信号自身的时间尺度来分解。我处理非平稳信号时,经常先用EMD把信号拆成几个本征模态函数(IMF),再对每个IMF做频谱分析。

实用建议:小波变换适合已知故障频率范围的情况(比如齿轮啮合频率附近)。EMD更适合未知故障模式,但要注意端点效应和模态混叠。我一般两个都试,看哪个效果更好。

3.4 特征选择与降维:别让“垃圾特征”淹没了真相

你想想看,时域算10个特征,频域算20个,时频域再算30个……加起来五六十个特征。这么多特征直接扔给模型,不仅计算慢,还会引入噪声。

PCA(主成分分析)是最经典的降维方法。它把原始特征投影到几个“主成分”方向上,保留方差最大的成分。说白了,就是抓住主要矛盾。

t-SNE则更适合可视化。它能把高维特征映射到2D或3D空间,让同类故障聚在一起,不同故障分开。我经常用t-SNE来快速判断:我提取的特征到底能不能区分不同故障类型?

from sklearn.decomposition import PCA
from sklearn.manifold import TSNE

# 假设 features 是 (样本数, 特征数) 的矩阵
# PCA降维到10维
pca = PCA(n_components=10)
features_pca = pca.fit_transform(features)

# t-SNE可视化到2维
tsne = TSNE(n_components=2, perplexity=30)
features_tsne = tsne.fit_transform(features_pca)

我的习惯:先做PCA降维到10-20维,保留95%以上的方差。然后用t-SNE看看聚类效果。如果不同故障类型在t-SNE图上混在一起,说明特征提取没做好,得回去重新选特征。

嗯,信号处理这块内容比较多,但核心就一句话:选对特征,事半功倍;选错特征,白费力气。 你在实际项目中,不妨多试几种方法,找到最适合你那个机组、那个故障类型的特征组合。


公众号:蓝海资料掘金营,微信deep3321