第四章:振动信号分析与特征工程
各位同学,今天我们来聊聊振动信号分析。说实话,这是风电运维里最「硬核」的部分之一。我刚开始接触这个领域时,面对一堆传感器数据,完全不知道从哪下手。后来踩了不少坑,才慢慢摸出门道。
振动信号里藏着设备的「健康密码」。齿轮磨损、轴承故障、叶片裂纹……这些隐患都会在振动信号里留下痕迹。关键是你得知道怎么看。
核心思路:把原始振动信号,转换成能反映设备状态的特征。这就是特征工程要做的事。
我习惯把特征分成三类:时域、频域、时频域。咱们一个一个来。
4.1 时域特征:最直观的「体检报告」
时域特征,说白了就是直接看信号波形算出来的统计量。你想想看,一个振动信号随时间变化,它的均值、峰值、峭度这些指标,就像人的体温、血压一样,能反映基本状态。
4.1.1 均值
均值反映信号的直流分量。对于旋转机械,均值通常接近零。如果均值明显偏移,说明可能有静摩擦或安装问题。我在项目里遇到过一台风机,均值持续偏高,后来发现是轴承座松动。
4.1.2 峰值
峰值就是信号的最大绝对值。这个指标对冲击很敏感。齿轮断齿、轴承点蚀,都会让峰值突然变大。但要注意,峰值容易受噪声干扰,我一般会结合其他指标一起看。
4.1.3 峭度
峭度是衡量信号分布「尖锐程度」的指标。正常振动信号接近正态分布,峭度值在3左右。如果峭度明显大于3,说明信号里有冲击成分——这往往是早期故障的信号。
我的经验:峭度对早期故障非常敏感,但容易误报。我习惯用「峭度+有效值」组合来判断。如果峭度高但有效值正常,可能是早期故障;如果两者都高,故障已经比较明显了。
import numpy as np
def time_domain_features(signal):
"""计算时域特征"""
features = {}
features['mean'] = np.mean(signal) # 均值
features['peak'] = np.max(np.abs(signal)) # 峰值
features['rms'] = np.sqrt(np.mean(signal**2)) # 有效值
features['kurtosis'] = np.mean((signal - features['mean'])**4) / (features['rms']**4) # 峭度
return features
# 示例
signal = np.random.randn(1000) # 模拟正常信号
print(time_domain_features(signal))
4.2 频域特征:用FFT看「频谱指纹」
时域信号看着乱糟糟的,但转到频域就清晰多了。每个设备都有自己特定的「频谱指纹」——正常运行时,哪些频率成分占主导,都是有规律的。
4.2.1 FFT(快速傅里叶变换)
FFT是把时域信号转换到频域的基本工具。我习惯先看频谱的整体形状,再关注特定频率的幅值变化。比如齿轮箱的啮合频率、轴承的故障特征频率,这些在频谱上都有对应位置。
注意:FFT有个「分辨率」问题。采样时间越长,频率分辨率越高。我曾经为了省存储空间,采样时间设得太短,结果两个相近的频率成分根本分不开。后来我定了个规矩:至少采集10个旋转周期的数据。
4.2.2 包络谱
包络谱是处理冲击信号的利器。它的原理是先对信号做包络解调,再对包络做FFT。这样能把高频冲击信号里的低频调制信息提取出来。
我记得有个项目,轴承外圈有早期裂纹,直接看FFT根本看不出异常。但用包络谱一看,故障特征频率清清楚楚。从那以后,包络谱就成了我工具箱里的常备工具。
from scipy import signal
import numpy as np
def envelope_spectrum(signal, fs):
"""计算包络谱"""
# 希尔伯特变换求包络
analytic_signal = signal.hilbert(signal)
envelope = np.abs(analytic_signal)
# 对包络做FFT
freqs = np.fft.rfftfreq(len(envelope), 1/fs)
spectrum = np.fft.rfft(envelope)
return freqs, np.abs(spectrum)
# 模拟轴承故障信号
t = np.linspace(0, 1, 1000)
fault_signal = np.sin(2*np.pi*50*t) * (1 + 0.5*np.sin(2*np.pi*10*t))
freqs, spec = envelope_spectrum(fault_signal, 1000)
4.3 时频域特征:小波变换的「显微镜」
FFT有个局限:它假设信号是平稳的。但实际振动信号往往是非平稳的——故障发生时,频率成分会随时间变化。这时候就需要时频分析。
4.3.1 小波变换
小波变换就像一把「变焦显微镜」。它用不同尺度的小波基函数去匹配信号,既能看清低频的长期趋势,又能捕捉高频的瞬态冲击。
我常用连续小波变换(CWT)做时频谱图。你看那个图,横轴是时间,纵轴是频率,颜色深浅代表能量大小。故障发生时,图上会出现明显的「能量团」——位置、时间、频率都一目了然。
小波变换 vs FFT:FFT告诉你「信号里有哪些频率」,小波变换告诉你「这些频率在什么时候出现」。对于风电这种工况多变的场景,小波变换往往更实用。
import pywt
import numpy as np
def wavelet_analysis(signal, wavelet='cmor', scales=np.arange(1, 128)):
"""连续小波变换"""
coefficients, frequencies = pywt.cwt(signal, scales, wavelet, sampling_period=0.001)
return coefficients, frequencies
# 模拟非平稳信号
t = np.linspace(0, 1, 1000)
non_stationary = np.sin(2*np.pi*10*t) + np.sin(2*np.pi*50*t)*(t>0.5)
coeffs, freqs = wavelet_analysis(non_stationary)
4.4 特征选择与降维
特征不是越多越好。我见过有人提取了上百个特征,结果模型反而更差。为什么?因为很多特征是冗余的,或者跟故障无关。
我个人习惯分三步走:
- 初步筛选:去掉方差接近零的特征(这些特征没有区分度)
- 相关性分析:计算特征之间的相关系数,去掉高度相关的冗余特征
- 重要性排序:用随机森林或XGBoost的特征重要性,保留Top-N
避坑指南:我曾经一股脑把所有特征都扔进模型,结果训练时间长了10倍,准确率反而下降了2%。后来用特征选择一筛,只保留20个关键特征,效果反而更好。记住:少即是多。
4.5 实战建议
说了这么多,最后给几条实在的建议:
- 先看时域,再看频域:时域特征能快速判断「有没有问题」,频域特征能定位「问题在哪」
- 包络谱是轴承故障的「照妖镜」:遇到轴承问题,优先用包络谱
- 小波变换适合变工况:如果风机经常启停或变转速,小波变换比FFT更靠谱
- 特征工程要迭代:没有一套特征能通吃所有场景,多试、多验证
好了,这一章的内容就到这里。振动信号分析是个实践性很强的领域,光看理论没用,得动手去跑数据、看图谱。慢慢来,你会找到感觉的。