第三章:时域信号处理——均值去除、趋势项消除、异常值检测与剔除、数据重采样
各位同学,大家好。我是你们的老朋友,一个在齿轮箱载荷谱分析领域摸爬滚打了十几年的工程师。今天咱们来聊聊时域信号处理。你别看这名字听着挺唬人,其实说白了,就是给原始信号“洗个澡”,把脏东西、坏数据都清理掉,让它干干净净地进入后续分析。
我刚开始做载荷谱那会儿,拿到手的数据直接往里怼,结果算出来的寿命预测偏差大得离谱。后来才明白,原始信号里藏着太多“陷阱”。今天这堂课,就是要把这些坑一个个填平。
核心思想: 原始信号 = 真实信号 + 噪声 + 趋势项 + 异常值。我们的目标就是去掉后三者,保留前者。
3.1 均值去除:把信号拉回零线
先问大家一个问题:你测到的齿轮箱振动信号,平均值一定是零吗?
答案是否定的。传感器本身有零漂,采集电路有偏置,这些都会给信号加上一个直流分量。这个直流分量如果不去掉,后面做雨流计数、计算损伤时,结果会整体偏移。
我个人习惯,拿到数据第一件事就是看均值。用Python做这个操作,一行代码就搞定:
import numpy as np
# 假设 signal 是你的原始时域数据
mean_value = np.mean(signal)
signal_detrended = signal - mean_value
print(f"原始均值: {mean_value:.4f}")
print(f"去除均值后均值: {np.mean(signal_detrended):.4f}")
你看,就这么简单。但要注意,均值去除不是万能的。如果信号本身有物理意义的偏置(比如某个工况下齿轮箱的静态扭矩),那你得想清楚再动手。我在项目中遇到过,有人把齿轮箱的静态扭矩均值也去掉了,结果算出来的疲劳寿命完全不对。嗯,这里要注意区分。
小技巧: 对于长周期信号,可以分段去除均值。比如每10分钟一段,分别减去该段的均值,能更好地消除传感器漂移。
3.2 趋势项消除:别让信号“跑偏”
趋势项是什么?说白了,就是信号整体在缓慢地往上飘或者往下掉。比如温度变化导致传感器特性漂移,或者齿轮箱在启动阶段转速逐渐上升,这些都会产生趋势项。
趋势项如果不消除,在后续的频谱分析中会出现虚假的低频分量,干扰我们对齿轮箱真实故障频率的判断。我曾经吃过这个亏,分析一个齿轮箱的边频带,怎么都对不上,后来发现是趋势项在作怪。
消除趋势项,最常用的方法是最小二乘法拟合多项式。我一般用一阶或二阶多项式就够了,阶数太高反而容易过拟合。
from scipy import signal
# 使用scipy的detrend函数,默认去除线性趋势
signal_detrended = signal.detrend(signal_original)
# 如果想去除二阶趋势,可以这样
import numpy as np
from numpy.polynomial import polynomial as P
x = np.arange(len(signal_original))
coeffs = P.polyfit(x, signal_original, 2) # 2阶多项式拟合
trend = P.polyval(x, coeffs)
signal_detrended = signal_original - trend
你想想看,如果趋势项是线性的,用 signal.detrend() 最省事。如果是非线性的,那就得用多项式拟合了。我个人建议,先用肉眼看看信号波形,判断趋势的形状,再选择合适的方法。
警告: 趋势项消除要谨慎。如果趋势项本身就是物理过程的一部分(比如齿轮箱从冷态到热态的缓慢升温),强行消除会丢失有用信息。一定要结合工况判断。
3.3 异常值检测与剔除:揪出“害群之马”
异常值,就是那些明显偏离正常范围的“野点”。可能是传感器瞬间掉线、电磁干扰、或者齿轮箱真的发生了冲击性故障。
怎么区分是干扰还是真实故障?这是个大问题。我的经验是:先看幅值。如果某个点的幅值超过正常范围的3倍标准差,大概率是异常值。但如果是齿轮箱断齿,冲击幅值也会很大,这时候就要结合时域波形和频谱综合判断。
常用的方法有3σ准则和箱线图法。我给大家写个3σ准则的代码:
import numpy as np
def detect_outliers_3sigma(data, threshold=3):
mean = np.mean(data)
std = np.std(data)
outliers = np.abs(data - mean) > threshold * std
return outliers
# 使用
outliers = detect_outliers_3sigma(signal)
clean_signal = signal[~outliers]
print(f"检测到 {np.sum(outliers)} 个异常值")
箱线图法更稳健一些,因为它基于中位数和四分位数,不受极端值影响。我一般两个方法都跑一遍,对比结果。
def detect_outliers_iqr(data, multiplier=1.5):
q1 = np.percentile(data, 25)
q3 = np.percentile(data, 75)
iqr = q3 - q1
lower_bound = q1 - multiplier * iqr
upper_bound = q3 + multiplier * iqr
outliers = (data < lower_bound) | (data > upper_bound)
return outliers
避坑指南: 我曾经在分析一个风电齿轮箱数据时,用3σ准则剔除了大量“异常值”,结果发现那些点其实是变桨动作引起的正常冲击。从那以后,我养成了一个习惯:剔除异常值之前,一定要先看原始波形,确认这些点是不是真的“异常”。
3.4 数据重采样:让数据“步调一致”
重采样,就是把原本不等间隔或者采样率不合适的数据,变成我们想要的采样率。为什么要做这个?
原因很多。比如你同时采集了振动信号和转速信号,振动是10kHz采样,转速是1kHz采样,要对齐分析就必须重采样。再比如,原始数据量太大,处理起来慢,可以降采样来提速。
重采样最忌讳的是直接抽取——就是每隔N个点取一个。这样会产生混叠效应,高频成分会折叠到低频,造成虚假信号。正确的做法是先低通滤波,再抽取。
Python里用 scipy.signal.resample 或者 pandas.DataFrame.resample 都很方便。我给大家演示一个降采样的例子:
from scipy import signal
# 原始信号,采样率1000Hz,想降到200Hz
original_fs = 1000
target_fs = 200
num_original = len(signal_original)
num_target = int(num_original * target_fs / original_fs)
# resample会自动进行抗混叠滤波
signal_resampled = signal.resample(signal_original, num_target)
# 或者用pandas处理时间序列
import pandas as pd
# 假设你有时间索引
time_index = pd.date_range(start='2024-01-01', periods=len(signal_original), freq='1ms')
series = pd.Series(signal_original, index=time_index)
series_resampled = series.resample('5ms').mean() # 从1ms重采样到5ms
你想想看,重采样后的数据,采样率变了,但信号的能量和频率成分要保持不变。我建议重采样后,对比一下原始信号和重采样信号的频谱,确保没有引入失真。
个人经验: 对于齿轮箱载荷谱,我一般把重采样后的采样率设为最高分析频率的2.56倍。比如你想分析到1000Hz,采样率就设2560Hz。这个比例是工程界的惯例,既保证精度,又不浪费数据。
小结
好了,今天的内容就到这里。均值去除、趋势项消除、异常值检测与剔除、数据重采样,这四个步骤是时域信号处理的“四件套”。每一步都不难,但每一步都马虎不得。
我常说,载荷谱分析,七分在预处理,三分在计算。数据干净了,后面的雨流计数、损伤计算才能得出靠谱的结果。希望大家在实际项目中,能把这些基本功练扎实。
如果你在实操中遇到什么问题,欢迎随时交流。咱们下节课见。