3. 特征工程(上):时域特征提取与频域特征提取

大家好,我是老张。干风电运维这些年,我最大的体会就是:数据本身不会说话,但特征会。你拿到的振动信号、功率曲线,原始数据看着都差不多,但一旦把特征提出来,好机组和坏机组立马现原形。

今天咱们聊特征工程的上半部分——时域和频域特征提取。说白了,就是教你怎么从一堆乱糟糟的波形里,揪出能反映机组健康状态的关键指标。

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

时域特征,就是直接对时间序列信号做统计计算。我习惯把它比作人的体检报告——血压、心率、体温,这些基础指标虽然简单,但能快速判断你有没有问题。

3.1.1 均值与标准差

均值反映信号的“中心趋势”。比如齿轮箱振动加速度的均值,正常情况下应该稳定在某个值附近。如果均值突然漂移,说明可能有静载荷变化或者传感器零偏。

标准差(也叫均方根值)反映信号的“波动程度”。我在项目中遇到过一台机组,振动均值正常,但标准差越来越大。后来拆开一看,轴承保持架已经碎了。你想想看,均值没变但波动大了,说明内部结构在松动。

核心公式:

  • 均值:\(\bar{x} = \frac{1}{N}\sum_{i=1}^{N}x_i\)
  • 标准差:\(\sigma = \sqrt{\frac{1}{N}\sum_{i=1}^{N}(x_i - \bar{x})^2}\)
import numpy as np

# 假设有一段振动信号
vibration = np.random.normal(0, 1, 1000)  # 模拟正常信号

mean_val = np.mean(vibration)
std_val = np.std(vibration)

print(f"均值: {mean_val:.3f}, 标准差: {std_val:.3f}")

# 实际项目中,我会用滑动窗口计算
window_size = 100
rolling_mean = np.convolve(vibration, np.ones(window_size)/window_size, mode='valid')

3.1.2 峰值与峰峰值

峰值就是信号的最大绝对值。对于风电叶片,峰值能反映瞬时冲击。我记得有一次做叶片裂纹检测,正常叶片峰值在5g以内,有裂纹的那片峰值直接飙到12g。

峰峰值是最大值减最小值。这个指标对旋转机械特别敏感。我曾经用峰峰值判断过齿轮箱的齿面磨损——正常时峰峰值稳定在2mm/s,磨损后涨到8mm/s,现场人员还不信,结果停机检查发现齿面已经剥落了一大片。

我的经验:峰值容易受噪声干扰,建议先做低通滤波再提取。我一般用3阶巴特沃斯滤波器,截止频率设到信号主频的2倍。

3.1.3 峭度与偏度

这两个指标比较“高级”,但非常有用。

  • 峭度:衡量信号分布的“尖峭程度”。正常振动信号接近正态分布,峭度≈3。如果峭度突然变大(比如>5),说明有冲击性故障。我在主轴轴承故障诊断中,峭度是最灵敏的指标之一。
  • 偏度:衡量分布的不对称性。偏度不为0,说明信号有偏斜,可能意味着不对中或松动。
from scipy.stats import kurtosis, skew

# 计算峭度和偏度
kurt_val = kurtosis(vibration)
skew_val = skew(vibration)

print(f"峭度: {kurt_val:.3f}, 偏度: {skew_val:.3f}")

# 注意:scipy的峭度默认减去了3(正态分布为0)
# 如果你想要“原始峭度”,加3即可
raw_kurt = kurtosis(vibration, fisher=False)
print(f"原始峭度: {raw_kurt:.3f}")

3.1.4 其他常用时域特征

特征名称 计算公式 典型应用场景
均方根值 \(\sqrt{\frac{1}{N}\sum x_i^2}\) 整体振动能量评估
波形因子 RMS / 均值绝对值 区分磨损与冲击
峰值因子 峰值 / RMS 早期故障预警
脉冲因子 峰值 / 均值绝对值 冲击性故障检测
裕度因子 峰值 / 方根幅值 轴承磨损评估

避坑指南:我曾经犯过一个错误——把所有时域特征一股脑全算出来,然后扔进模型。结果模型过拟合得一塌糊涂。后来我学乖了:先做相关性分析,去掉冗余特征。比如峰值因子和脉冲因子相关性很高,留一个就行。

3.2 频域特征提取:看穿信号的“频谱密码”

时域特征只能告诉你“信号有多大”,但频域特征能告诉你“信号里有什么频率成分”。说白了,就像听音乐——时域是音量大小,频域是音调高低。

3.2.1 傅里叶变换(FFT)基础

FFT是频域分析的基石。它的作用是把时域信号分解成不同频率的正弦波。我刚开始学的时候也觉得公式复杂,但后来发现,你只要记住三点:

  1. 采样率:决定了你能看到的最高频率(奈奎斯特频率 = 采样率/2)
  2. 数据长度:决定了频率分辨率(Δf = 采样率 / 数据点数)
  3. 频谱泄漏:信号不是整周期截断时,能量会“泄漏”到相邻频率
import numpy as np
import matplotlib.pyplot as plt

# 生成模拟信号:50Hz + 120Hz + 噪声
fs = 1000  # 采样率 1000Hz
t = np.arange(0, 1, 1/fs)
signal = 0.7*np.sin(2*np.pi*50*t) + 1.2*np.sin(2*np.pi*120*t) + 0.5*np.random.randn(len(t))

# FFT
N = len(signal)
fft_vals = np.fft.fft(signal)
freqs = np.fft.fftfreq(N, 1/fs)

# 只取正频率部分
pos_mask = freqs >= 0
fft_mag = np.abs(fft_vals[pos_mask]) / N * 2  # 幅值谱
fft_freqs = freqs[pos_mask]

# 找峰值频率
peak_idx = np.argsort(fft_mag)[-5:]  # 取前5个最大峰值
print("主要频率成分 (Hz):", fft_freqs[peak_idx])
print("对应幅值:", fft_mag[peak_idx])

3.2.2 频谱分析的关键指标

拿到频谱后,不能只看图,要提取量化特征。我常用的频域特征有:

  • 重心频率:频谱的“重心”位置,反映信号主频的偏移。齿轮箱磨损时,重心频率会向高频移动。
  • 频率方差:频谱的分散程度。故障越严重,频率成分越复杂,方差越大。
  • 边频带能量:在啮合频率两侧找边频带。这是齿轮故障的“金标准”。

实战技巧:做频谱分析时,别忘了加窗函数。我习惯用汉宁窗,它能有效抑制频谱泄漏。不加窗的话,你可能会看到一些“假频率”,误导判断。

# 加汉宁窗再做FFT
window = np.hanning(N)
signal_windowed = signal * window

fft_windowed = np.fft.fft(signal_windowed)
fft_mag_windowed = np.abs(fft_windowed[pos_mask]) / np.sum(window) * 2

# 计算重心频率
total_energy = np.sum(fft_mag_windowed)
centroid_freq = np.sum(fft_freqs * fft_mag_windowed) / total_energy
print(f"重心频率: {centroid_freq:.2f} Hz")

3.2.3 包络谱分析

这个技术特别适合轴承故障诊断。原理很简单:先对信号做希尔伯特变换得到包络,再对包络做FFT。包络谱能放大故障特征频率,让早期故障无处遁形。

我记得有一次,某风场连续三台机组报“轴承温度高”,但振动时域信号看不出异常。我做了包络谱分析,发现外圈故障频率的边频带非常明显。后来拆机验证,外圈果然有裂纹。从那以后,包络谱成了我工具箱里的常备武器。

from scipy.signal import hilbert

# 包络谱分析
analytic_signal = hilbert(signal)
envelope = np.abs(analytic_signal)

# 对包络做FFT
env_fft = np.fft.fft(envelope)
env_mag = np.abs(env_fft[pos_mask]) / N * 2

# 找故障特征频率(假设轴承外圈故障频率为 3.5倍转频)
rotational_freq = 25  # 假设转频25Hz
fault_freq = 3.5 * rotational_freq  # 87.5Hz

# 在故障频率附近搜索峰值
freq_range = (fault_freq - 2, fault_freq + 2)
mask = (fft_freqs >= freq_range[0]) & (fft_freqs <= freq_range[1])
if np.any(mask):
    peak_val = np.max(env_mag[mask])
    print(f"故障频率 {fault_freq:.1f}Hz 附近包络幅值: {peak_val:.3f}")

3.3 知识体系总览

说了这么多,我画了一张图帮你理清思路。这张图是我做特征工程时的“作战地图”,每次提取特征前都会看一眼,避免遗漏。

特征工程(上):时域与频域特征提取 原始振动/电流信号 时域特征提取 频域特征提取 均值、标准差、峰值、峰峰值 峭度、偏度、波形因子等 FFT频谱、幅值谱、功率谱 重心频率、边频带、包络谱 特征向量 → 输入模型

嗯,这张图把今天的核心内容串起来了。左边是时域特征,右边是频域特征,最终汇合成特征向量,喂给后续的评估模型。

3.4 实战中的几点忠告

最后,结合我这些年的经验,给你几个实用建议:

  • 不要迷信单一特征:时域和频域特征要配合使用。我见过有人只看峭度,结果把正常信号误判为故障——因为传感器松动也会导致峭度变大。
  • 注意数据质量:坏数据提不出好特征。我每次做特征提取前,都会先做数据清洗——剔除停机段、限功率段、传感器故障段。
  • 特征要可解释:别为了追求模型精度,提取一堆物理意义不明的特征。你想想看,如果特征提取出来连你自己都解释不了,怎么跟现场运维人员沟通?

我的习惯:每次提取完特征,我都会画一张特征分布图——正常样本和故障样本的特征分布有没有明显分离?如果重叠严重,说明这个特征区分度不够,需要换一个。

好了,时域和频域特征提取就聊到这儿。这些方法看着简单,但真正用好需要大量实践。下次你拿到一段振动数据,不妨先算算均值、标准差,再做一次FFT,看看频谱里有没有异常频率。多练几次,你就能找到感觉了。


专注资料整理