作为数据科学家,是否曾为时间序列分析感到困扰?
是否思考过信号处理技术能否让分析工作变得更轻松?
如果答案是肯定的,那么本文将为您打开新的视角。
处理现实世界中的时间序列数据往往充满挑战。金融曲线、心电图轨迹、神经信号等数据常常呈现为杂乱无章的尖峰,看似毫无规律可循。
在数据科学领域,传统方法通常依赖经典的统计预处理技术:季节性分解、去趋势、平滑处理、移动平均等。这些方法虽然实用,但基于的强假设条件在实际应用中往往难以满足。当这些假设失效时,机器学习模型可能表现不佳或缺乏泛化能力。
本文将深入探讨一类在数据科学培训中鲜少涉及的方法族,它们能彻底改变处理时间数据的方式。
今日内容概览 
传统方法为何难以处理真实世界时间序列
信号处理工具如何提供帮助
经验模态分解的工作原理与局限性
前述经典预处理技术作为入门工具尚可,但其基于对信号行为的固定假设。
大多数方法假设信号是平稳的,即其统计特性(均值、方差、频谱内容)随时间保持恒定。
然而现实中的信号往往具有以下特征:
- 非平稳性(频率成分随时间演变)
- 非线性(无法用简单加法分量解释)
- 含噪声
- 多重振荡混合
信号的本质
信号本质上是随时间变化的物理量(数据科学中常称为时间序列)。
典型示例如下:

图1:脑磁图信号数据示例(作者供图)
信号无处不在,且大多违背经典时间序列模型的假设条件。
它们很少保持“洁净”,单个信号通常是多个过程同时作用的混合体。
在一个信号内部通常包含:
- 缓慢趋势
- 周期性振荡
- 短暂脉冲
- 随机噪声
- 隐藏的节律模式
试想能否直接从数据中分离这些分量,无需假设平稳性,无需指定频带,也无需将信号强制拟合到预设基函数中?
这正是数据驱动的信号分解技术所承诺的能力。
本文是自适应分解系列三部曲的首篇:
- 经验模态分解(本文)
- 变分模态分解(续篇)
- 多元变分模态分解(终篇)
每种方法都较前一种更强大、更稳定,通过本系列学习,将掌握如何用信号处理方法提取洁净、可解释的分量。
经验模态分解
经验模态分解由Huang等人于1998年作为希尔伯特-黄变换的组成部分提出。
其目标简明而强大:将信号分解为若干洁净的振荡分量,即本征模态函数。
每个IMF对应信号中的一个振荡模式,从最快到最慢的趋势依次呈现。
观察下图:
顶部为原始信号,下方显示多个IMF,每个IMF捕获数据中隐藏的不同“层级”振荡。
IMF₁包含最快波动
IMF₂捕获稍慢节律
……
末位IMF与残差代表缓慢趋势或基线
部分IMF对机器学习任务具有价值,其他可能对应噪声、伪影或不相关振荡。

图2:原始信号(顶部)与5个IMF(底部),按高频到低频分量排序(作者供图)
数学原理
EMD将任意信号x(t)分解为:

其中:
- Ci(t)为本征模态函数
- IMF₁捕获最快振荡
- IMF₂捕获较慢振荡,依此类推
- r(t)为残差——缓慢趋势或基线
- 所有IMF与残差相加可精确重构原始信号
IMF是从数据直接获取的洁净振荡,需满足两个基本条件:
- 过零点数量 ≈ 极值点数量
→ 振荡行为规整
- 上下包络线均值近似为零
→ 振荡局部对称,不含长期信息
这两条规则使IMF本质上具有数据驱动和自适应性,与将信号强制拟合预设形式的傅里叶或小波方法形成鲜明对比。
算法直观解析
EMD算法具有惊人的直观性,提取循环如下:
- 从原始信号开始
- 识别所有局部极大值与极小值
- 插值形成上下包络线(见图3)
- 计算双包络线均值
- 从信号中减去该均值
→得到“候选IMF”
- 检验两个IMF条件:
- 过零点与极值点数量是否一致?
- 包络线均值是否近似为零?
若满足 → 成功提取IMF₁
若不满足 → 重复过程(称为筛分)直至符合标准
- 获得IMF₁(最快振荡)后:
- 从原始信号中减去IMF₁
- 余量成为新信号
- 重复过程提取IMF₂、IMF₃……
该过程持续至无显著振荡残留,最终得到残差趋势r(t)。

图3:EMD单次迭代过程。顶部:原始信号(蓝色)。中部:上下包络线(红色)。底部:局部均值(黑色)。(作者供图)
实践应用
为深入理解EMD工作机制,可通过合成信号进行演示。
组合三个分量:
- 低频振荡(约5赫兹)
- 高频振荡(约30赫兹)
- 随机白噪声
将各分量混合为单一杂乱信号后,应用EMD方法进行分解。
import numpy as np
import matplotlib.pyplot as plt
# --- 参数设置 ---
Fs = 500 # 采样频率(赫兹)
t_end = 2 # 持续时间(秒)
N = Fs * t_end # 总样本数
t = np.linspace(0, t_end, N, endpoint=False)
# --- 信号分量 ---
# 1. 低频分量(等效α波段)
f1 = 5
s1 = 2 * np.sin(2 * np.pi * f1 * t)
# 2. 高频分量(等效γ波段)
f2 = 30
s2 = 1.5 * np.sin(2 * np.pi * f2 * t)
# 3. 白噪声
noise = 0.5 * np.random.randn(N)
# --- 复合信号 ---
signal = s1 + s2 + noise
# 绘制合成信号
plt.figure(figsize=(12, 4))
plt.plot(t, signal)
plt.title(f'合成信号(包含{f1}赫兹和{f2}赫兹分量)')
plt.xlabel('时间(秒)')
plt.ylabel('振幅')
plt.grid(True)
plt.tight_layout()
plt.show()

图4:包含多重频率的合成信号(作者供图)
需要注意的关键细节:
EMD自动确定IMF数量
持续分解信号直至满足停止准则——通常当:
- 无法提取更多振荡结构
- 残差变为单调趋势
- 筛分过程趋于稳定
(必要时可设置最大IMF数量,但算法通常会自然终止)
from PyEMD import EMD
# 初始化EMD
emd = EMD()
IMFs = emd.emd(signal, max_imf=10)
# 绘制原始信号与IMF
fig, axes = plt.subplots(IMFs.shape[0] + 1, 1, figsize=(10, 2 * IMFs.shape[0]))
fig.suptitle('EMD分解结果', fontsize=14)
axes[0].plot(t, signal)
axes[0].set_title('原始信号')
axes[0].set_xlim(t[0], t[-1])
axes[0].grid(True)
for n, imf in enumerate(IMFs):
axes[n + 1].plot(t, imf, 'g')
axes[n + 1].set_title(f"IMF {n+1}")
axes[n + 1].set_xlim(t[0], t[-1])
axes[n + 1].grid(True)
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.show()

图5:合成信号的EMD分解结果(作者供图)
技术局限
EMD虽强大,但存在若干缺陷:
- 模态混叠:不同频率成分可能混杂于同一IMF
- 过度分解:自动确定的IMF数量可能过多
- 噪声敏感:微小噪声变化可能彻底改变IMF
- 数学基础薄弱:结果缺乏稳定性与唯一性保证
针对这些局限,已发展出多种改进版本(EEMD、CEEMDAN),但其本质仍属于经验方法。
