在工程信号分析领域,边际谱(Marginal Spectrum)作为希尔伯特-黄变换(HHT)的重要组成部分,提供了一种非平稳信号频域特征分析的有效手段。与传统的傅里叶谱不同,边际谱能够反映信号能量在瞬时频率上的分布情况,特别适用于处理非线性、非平稳信号。
传统傅里叶变换基于全局正弦基函数,而HHT方法通过经验模态分解(EMD)自适应地获得本征模态函数(IMFs),再结合希尔伯特变换得到瞬时频率和幅值。这种局部化分析方法克服了傅里叶变换对非平稳信号的局限性。
边际谱的计算本质上是对希尔伯特谱的时间维度积分,数学表达式为:
[ h(\omega) = \int_{0}^{T} H(\omega,t) dt ]
其中 ( H(\omega,t) ) 表示希尔伯特谱,( T ) 为信号时长。
边际谱在以下场景中表现突出:
我们首先构建一个包含5Hz和10Hz成分的复合信号作为分析对象。采样率设置需遵循奈奎斯特准则:
python复制import numpy as np
import matplotlib.pyplot as plt
# 参数设置
sample_rate = 1000 # 采样率(Hz)
duration = 1.0 # 信号时长(s)
freq1 = 5 # 低频成分(Hz)
freq2 = 10 # 高频成分(Hz)
# 时间序列生成
t = np.linspace(0, duration, int(sample_rate*duration), endpoint=False)
# 信号合成
signal1 = 0.8 * np.sin(2 * np.pi * freq1 * t) # 幅值0.8
signal2 = 1.2 * np.sin(2 * np.pi * freq2 * t) # 幅值1.2
original_signal = signal1 + signal2 + 0.1*np.random.randn(len(t)) # 添加高斯噪声
关键提示:实际应用中建议添加1-5%的随机噪声,更接近真实信号特性。采样率应至少为最高频率成分的2.5倍以上。
EMD分解的核心是筛选过程(Sifting Process),以下是完整实现:
python复制def emd(signal, max_imf=10, threshold=0.05):
imfs = []
residual = signal.copy()
for _ in range(max_imf):
h = residual
std = np.inf
while std > threshold:
# 找极值点
peaks, _ = find_peaks(h)
valleys, _ = find_peaks(-h)
extrema = np.sort(np.concatenate([peaks, valleys]))
if len(extrema) < 2:
break
# 三次样条插值
t_ext = t[extrema]
upper = np.interp(t, t_ext, h[extrema])
lower = -np.interp(t, t_ext, -h[extrema])
# 计算均值曲线
mean = (upper + lower)/2
h_new = h - mean
# 判断停止条件
std = np.sum((h - h_new)**2)/np.sum(h**2)
h = h_new
if len(extrema) < 2:
break
imfs.append(h)
residual = residual - h
return imfs, residual
from scipy.signal import find_peaks
imfs, residual = emd(original_signal)
技术细节:筛选过程中使用三次样条插值构造包络线,通过标准差阈值控制迭代次数。实际应用中建议设置最大IMF数量防止过度分解。
对每个IMF进行希尔伯特变换获取瞬时特征:
python复制from scipy.signal import hilbert
def compute_hilbert_spectrum(imfs, t):
hilbert_spectrum = []
instantaneous_frequencies = []
for imf in imfs:
analytic_signal = hilbert(imf)
amplitude = np.abs(analytic_signal)
phase = np.unwrap(np.angle(analytic_signal))
frequency = np.diff(phase)/(2*np.pi*np.diff(t))
# 对齐数组长度
frequency = np.concatenate([frequency, [frequency[-1]]])
hilbert_spectrum.append(amplitude)
instantaneous_frequencies.append(frequency)
return np.array(hilbert_spectrum), np.array(instantaneous_frequencies)
hilbert_spectrum, ifreq = compute_hilbert_spectrum(imfs, t)
瞬时频率计算采用相位差分方法:
[ \omega(t) = \frac{d\theta(t)}{dt} ]
其中 ( \theta(t) ) 为解析信号的瞬时相位。
python复制def compute_marginal_spectrum(hilbert_spectrum, ifreq, freq_bins=100):
# 确定频率范围
min_freq, max_freq = 0, np.max(ifreq)*1.2
freq_axis = np.linspace(min_freq, max_freq, freq_bins)
# 初始化边际谱
marginal = np.zeros(freq_bins)
# 对每个时间点进行频率分布统计
for t_idx in range(hilbert_spectrum.shape[1]):
for imf_idx in range(hilbert_spectrum.shape[0]):
freq = ifreq[imf_idx, t_idx]
amp = hilbert_spectrum[imf_idx, t_idx]
# 找到最近的频率bin
bin_idx = np.argmin(np.abs(freq_axis - freq))
marginal[bin_idx] += amp
return freq_axis, marginal
freq_axis, marginal = compute_marginal_spectrum(hilbert_spectrum, ifreq)
python复制plt.figure(figsize=(12, 8))
# 原始信号
plt.subplot(3,1,1)
plt.plot(t, original_signal)
plt.title('Original Signal')
plt.xlabel('Time (s)')
# IMFs展示
plt.subplot(3,1,2)
for i, imf in enumerate(imfs):
plt.plot(t, imf+0.3*i, label=f'IMF {i+1}')
plt.legend()
plt.title('Extracted IMFs')
# 边际谱
plt.subplot(3,1,3)
plt.bar(freq_axis, marginal, width=freq_axis[1]-freq_axis[0])
plt.xlim(0, 15)
plt.title('Marginal Spectrum')
plt.xlabel('Frequency (Hz)')
plt.tight_layout()
plt.show()
EMD分解在信号端点处容易出现失真,常用解决方法包括:
改进后的端点处理代码示例:
python复制def extend_signal(signal, n=5):
# 镜像延拓
left_ext = 2*signal[0] - signal[1:n+1][::-1]
right_ext = 2*signal[-1] - signal[-n-1:-1][::-1]
return np.concatenate([left_ext, signal, right_ext])
当信号包含相近频率成分时,可能出现模态混叠现象。解决方案包括:
| 参数 | 推荐值 | 调整建议 |
|---|---|---|
| 筛选次数阈值 | 0.05-0.2 | 值越小分解越精细 |
| 最大IMF数量 | 8-10 | 根据信号复杂度调整 |
| 频率bin数量 | 50-200 | 权衡分辨率与平滑度 |
| 噪声水平 | 0.1-0.3 | 仅EEMD需要设置 |
对于长时间序列信号,可采用以下优化策略:
python复制from numba import jit
@jit(nopython=True)
def fast_hilbert_transform(imf):
# 实现优化的希尔伯特变换
...
边际谱概念可扩展到二维信号处理:
二维EMD实现思路: