经验模态分解(Empirical Mode Decomposition,EMD)法是黄锷(N. E. Huang)在美国国家宇航局与其他人于1998年创造性地提出的一种新型自适应信号时频处理方法,特别适用于非线性非平稳信号的分析处理。
EMD其实就是一种对信号进行分解的方法,与傅里叶变换、小波变换的核心思想一致,大家都想将信号分解为各个相互独立的成分的叠加;只不过傅里叶变换以及小波变换都要求要有基函数,而EMD却完全抛开了基函数的束缚,仅仅依据数据自身的时间尺度特征来进行信号分解,具备自适应性。由于无需基函数,EMD几乎可以用于任何类型信号的分解,尤其是在非线性、非平稳信号的分解上具有明显的优势。
EMD的目的是将信号分解为多个本征模函数(IMF)的叠加。IMF必需要满足以下两个条件:
(1)函数在整个时间范围内,局部极值点和过零点的数目必须相等,或最多相差一个;
(2)在任意时刻点,局部最大值的包络(上包络线)和局部最小值的包络(下包络线) 平均必须为零。
EMD方法是基于如下假设基础上的:
(1)信号至少有两个极值点,一个极大值和一个极小值;
(2)特征时间尺度通过两个极值点之间的时间定义;
(3)若数据缺乏极值点但有形变点,则可通过数据微分一次或几次获得极值点,然后再通过积分来获得分解结果。
算法流程如下所示:
EMD算法的不足:EMD算法能将原始信号不断进行分解,获取符合一定条件下的IMF分量。这些 IMF 分量之间的频率往往不同,这就为其在谐波检测方向的使用提供了一种思路。EMD 算法以其正交性、收敛性等特点被广泛用于信号处理等领域,但并不像小波分析或者神经网络那样,有固定的数学模型,因此它的一些重要性质仍还没有通过缜密的数学方法证明出。而且对模态分量 IMF 的定义也尚未统一,仅能从信号的零点与极值点的联系与信号的局部特征等综合描述。EMD 从理论到实际运用仍有很长的一段路要走。
EMD 具体的不足体现在以下几个方面:IMF 分解时存在着模态混叠现象,也就是说一个IMF中会包含不同时间尺度的特征成分。一方面是由于信号本身的原因,另一方面是EMD算法本身的缺陷;在分解出IMF的过程中需要迭代很多次,而停止迭代的条件缺乏一个标准,所以不同的停止迭代的条件得到的IMFs也是不同的。
import pandas as pd
import numpy as np
from PyEMD import EMD, Visualisation # 可视化
import tensorflow as tf
# 调用GPU加速
gpus = tf.config.experimental.list_physical_devices(device_type='GPU')
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
def emd_signal(Signal):
emd = EMD() # EMD分解
emd.emd(Signal, max_imf=3) # max_imf=3最大分解层数
imfs,res = emd.get_imfs_and_residue() # 获得分量+残余分量
print(len(imfs)) # 分量的个数
# 分解序列可视化
vis = Visualisation()
t = np.arange(0, len(Signal), 1) # t表示横轴的取值范围
vis.plot_imfs(imfs=imfs, residue=res, t=t, include_residue=True) # IMF分解序列可视化
vis.plot_instant_freq(t=t, imfs=imfs) # IMF分解序列频率可视化
vis.show()
# 保存分量+残余分量
for i in range(len(imfs)):
a = imfs[i]
dataframe = pd.DataFrame({'imf{}'.format(i + 1): a})
dataframe.to_csv(r"imf-%d.csv" % (i + 1), index=False, sep=',')
# 保存残余分量
dataframe = pd.DataFrame(res)
dataframe.to_csv(r"res.csv", index=False, sep=',')
if __name__ == "__main__":
data = pd.read_csv(r'文件路径', engine="python")
Signal = np.array(data).ravel()
emd_signal(Signal)
EEMD方法实质上是对EMD算法的一种改进,主要是根据白噪声均值为零的特性,在信号中对此加入白噪声,仍然用EMD进行分解,对分解的结果进行平均处理,平均处理的次数越多噪声给分解结果带来的影响就越小。设信号为x(t),具体的分解步骤如下:
步骤1:将x(t)设定平均处理次数为M,初始i=1,2,……,M;
步骤2:给x(t)添加具有一定幅值的随机白噪声n_i (t),组成新的一系列信号;
步骤3:将新的序列号x_i (t)进行EMD分解。n为EMD分解IMF的数量,c_(i,n) (t)是IMFs, r_(i,n) (t)是残余分量;
步骤4:重复2步骤、3步骤M次,每次添加不同幅值的白噪声,获得一系列IMFs。通过IMFs平均值,求得EEMD的IMF分量c_n (t);
EEMD和EMD性能对比. EMD算法过程中出现模态混叠的两种现象:
1)不同的时间尺度成分出现在同一个IMF分量当中。
2)相同的尺度分布在不同的IMF分量当中。
此现象会导致时频分布错误,使IMF分量失去真实的物理意义。EEMD分解算法基于白噪声频谱均衡的分布特点来均衡噪声,使得频率的分布趋于均匀。添加的白噪声不同信号的幅值分布点带来的模态混叠效应。
import pandas as pd
import numpy as np
from PyEMD import EEMD, Visualisation # 可视化
import tensorflow as tf
# 调用GPU加速
gpus = tf.config.experimental.list_physical_devices(device_type='GPU')
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
def eemd_signal(Signal):
eemd = EEMD() # EMD分解
eemd.eemd(Signal, max_imf=3) # max_imf=3最大分解层数
imfs,res = eemd.get_imfs_and_residue() # 获得分量+残余分量
print(len(imfs)) # 分量的个数
# 分解序列可视化
vis = Visualisation()
t = np.arange(0, len(Signal), 1) # t表示横轴的取值范围
vis.plot_imfs(imfs=imfs, residue=res, t=t, include_residue=True) # IMF分解序列可视化
vis.plot_instant_freq(t=t, imfs=imfs) # IMF分解序列频率可视化
vis.show()
# 保存分量+残余分量
for i in range(len(imfs)):
a = imfs[i]
dataframe = pd.DataFrame({'imf{}'.format(i + 1): a})
dataframe.to_csv(r"imf-%d.csv" % (i + 1), index=False, sep=',')
# 保存残余分量
dataframe = pd.DataFrame(res)
dataframe.to_csv(r"res.csv", index=False, sep=',')
if __name__ == "__main__":
data = pd.read_csv(r'文件路径', engine="python")
Signal = np.array(data).ravel()
eemd_signal(Signal)
互补集合经验模态分解CEEMD, 该方法向原始信号中加入正负成对的辅助白噪声,在集合平均时相消,能有效提高分解效率,克服EEMD重构误差大、分解完备性差的问题。
自适应噪声的完整集合经验模态分解CEEMDAN, 在分解过程中添加的是白噪声经EMD分解得到的各阶IMF分量,最后重构信号中的噪声残余(比EEMD的结果)更小,降低了筛选次数。
另一方面,各组信号经CEEMDAN分解出第一阶固有模态分量后立即进行集合平均,避免了CEEMD中各组IMF分解结果差异造成最后集合平均难以对齐的问题,也避免了其中某一阶IMF分解效果不好时,将影响传递给下一阶,影响后续分解。
import pandas as pd
import numpy as np
from PyEMD import CEEMDAN, Visualisation # 可视化
import tensorflow as tf
# 调用GPU加速
gpus = tf.config.experimental.list_physical_devices(device_type='GPU')
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
def ceemdan_signal(Signal):
ceemdan = CEEMDAN() # EMD分解
ceemdan.ceemdan(Signal, max_imf=3) # max_imf=3最大分解层数
imfs,res = ceemdan.get_imfs_and_residue() # 获得分量+残余分量
print(len(imfs)) # 分量的个数
# 分解序列可视化
vis = Visualisation()
t = np.arange(0, len(Signal), 1) # t表示横轴的取值范围
vis.plot_imfs(imfs=imfs, residue=res, t=t, include_residue=True) # IMF分解序列可视化
vis.plot_instant_freq(t=t, imfs=imfs) # IMF分解序列频率可视化
vis.show()
# 保存分量+残余分量
for i in range(len(imfs)):
a = imfs[i]
dataframe = pd.DataFrame({'imf{}'.format(i + 1): a})
dataframe.to_csv(r"imf-%d.csv" % (i + 1), index=False, sep=',')
# 保存残余分量
dataframe = pd.DataFrame(res)
dataframe.to_csv(r"res.csv", index=False, sep=',')
if __name__ == "__main__":
data = pd.read_csv(r'文件路径', engine="python")
Signal = np.array(data).ravel()
ceemdan_signal(Signal)
EMD将信号进行平稳化处理的过程中存在模态混叠,影响该方法的性能及应用。
EEMD虽然能有效抑制模态混叠,但在分解过程中添加的辅助白噪声最终需要增加集合平均次数来抵消,计算耗时长,重构误差大。
CEEMD在抑制模态混叠的同时正负成对噪声相消,部分降低了残留噪声的影响,减轻了集合平均抑制添加白噪声的负担,提高了计算效率。
CEEMDAN及其改进方法在每次分解时添加白噪声的IMF分量,添加噪声逐级减少,固有模态分量中残留噪声更少,有效减小了重构误差,且在分解的每个阶段都有一个全局停止标准,分解效率最高。