第三章:时域信号处理——均值去除、趋势项消除、异常值检测与剔除、数据重采样

各位同学,大家好。我是你们的老朋友,一个在齿轮箱载荷谱分析领域摸爬滚打了十几年的工程师。今天咱们来聊聊时域信号处理。你别看这名字听着挺唬人,其实说白了,就是给原始信号“洗个澡”,把脏东西、坏数据都清理掉,让它干干净净地进入后续分析。

我刚开始做载荷谱那会儿,拿到手的数据直接往里怼,结果算出来的寿命预测偏差大得离谱。后来才明白,原始信号里藏着太多“陷阱”。今天这堂课,就是要把这些坑一个个填平。

核心思想: 原始信号 = 真实信号 + 噪声 + 趋势项 + 异常值。我们的目标就是去掉后三者,保留前者。

时域信号处理知识体系 原始时域信号 均值去除 趋势项消除 异常值检测与剔除 数据重采样 干净的载荷谱数据

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。这个比例是工程界的惯例,既保证精度,又不浪费数据。

小结

好了,今天的内容就到这里。均值去除、趋势项消除、异常值检测与剔除、数据重采样,这四个步骤是时域信号处理的“四件套”。每一步都不难,但每一步都马虎不得。

我常说,载荷谱分析,七分在预处理,三分在计算。数据干净了,后面的雨流计数、损伤计算才能得出靠谱的结果。希望大家在实际项目中,能把这些基本功练扎实。

如果你在实操中遇到什么问题,欢迎随时交流。咱们下节课见。


蓝海数据掘金营,专注资料整理