アルゴリズムの背景
経験的モード分解(略して EMD) は、1998 年に NASA の NE Huangらによって創造的に提案された新しい適応信号時間周波数処理方法であり、線形非定常信号の非解析処理に特に適しています。
アルゴリズムによるプロセス分析
- ふるい分け
- 極値点を見つけて、 ピーク検索アルゴリズムを通じて信号シーケンスの
极大值
総和を取得します。极小值
- 信号シーケンスの
极大值
合計グループ を通じて包絡線をフィッティングし、 2 つの滑らかなピーク/トラフ フィッティング曲線、つまり信号と信号の合計を取得します。极小值
三次样条插值法
上包络线
下包络线
- 平均包絡線は、 2 つの極値曲線を平均して取得します。
平均包络线
- 中間信号の元の信号から平均包絡線を減算して、
中间信号
- 固有係数関数 (IMF) の判定 IMF は次の 2 つの条件を満たす必要があります。 1) データ セグメント全体で、極値点の数とゼロクロッシング点の数が等しいか、その差が最大 1 を超えてはなりません。2)極大点により形成される上部包絡線と極小点により形成される下部包絡線の平均値はいかなる瞬間においても0、すなわち時間軸に関して局所的に対称である。
- IMF 1によって取得された IMF 条件を満たす最初の中間信号 は、元の信号の最初の固有モード関数コンポーネント
IMF 1
(負の極大値と正の極小値がある場合は、元のデータから包絡線平均を減算した後の新しいデータ) です。これは、これが固有モード関数ではなく、引き続き「スクリーニング」する必要があることを示します。)- 上記の方法を使用して最初の IMF を取得した後、新しい元の信号として元の信号から IMF1 を減算し、上記のスクリーニング分析を通じて IMF2 を取得するなどして、EMD 分解を完了します。
1. 極値点を見つける
from scipy.signal import argrelextrema
# 通过Scipy的argrelextrema函数获取信号序列的极值点
data = np.random.random(100)
max_peaks = argrelextrema(data, np.greater)
min_peaks = argrelextrema(data, np.less)
# 绘制极值点图像
plt.figure(figsize = (18,6))
plt.plot(data)
plt.scatter(max_peaks, data[max_peaks], c='r', label='Max Peaks')
plt.scatter(min_peaks, data[min_peaks], c='b', label='Max Peaks')
plt.legend()
plt.xlabel('time (s)')
plt.ylabel('Amplitude')
plt.title("Find Peaks")
2. エンベロープ関数のフィッティング
このステップは EMD の中核ステップであり、固有モード関数 IMF を分解するための前提条件でもあります。
from scipy.signal import argrelextrema
data = np.random.random(100)-0.5
index = list(range(len(data)))
# 获取极值点
max_peaks = list(argrelextrema(data, np.greater)[0])
min_peaks = list(argrelextrema(data, np.less)[0])
# 将极值点拟合为曲线
ipo3_max = spi.splrep(max_peaks, data[max_peaks],k=3) #样本点导入,生成参数
iy3_max = spi.splev(index, ipo3_max) #根据观测点和样条参数,生成插值
ipo3_min = spi.splrep(min_peaks, data[min_peaks],k=3) #样本点导入,生成参数
iy3_min = spi.splev(index, ipo3_min) #根据观测点和样条参数,生成插值
# 计算平均包络线
iy3_mean = (iy3_max+iy3_min)/2
# 绘制图像
plt.figure(figsize = (18,6))
plt.plot(data, label='Original')
plt.plot(iy3_max, label='Maximun Peaks')
plt.plot(iy3_min, label='Minimun Peaks')
plt.plot(iy3_mean, label='Mean')
plt.legend()
plt.xlabel('time (s)')
plt.ylabel('microvolts (uV)')
plt.title("Cubic Spline Interpolation")
新しい信号は、元の信号から平均包絡線を減算することによって取得されます。新しい信号に負の極大値と正の極小値がある場合、これは固有モード関数ではなく、続行する必要があることを意味します。フィルター」
固有モード関数の取得 (IMF)
def sifting(data):
index = list(range(len(data)))
max_peaks = list(argrelextrema(data, np.greater)[0])
min_peaks = list(argrelextrema(data, np.less)[0])
ipo3_max = spi.splrep(max_peaks, data[max_peaks],k=3) #样本点导入,生成参数
iy3_max = spi.splev(index, ipo3_max) #根据观测点和样条参数,生成插值
ipo3_min = spi.splrep(min_peaks, data[min_peaks],k=3) #样本点导入,生成参数
iy3_min = spi.splev(index, ipo3_min) #根据观测点和样条参数,生成插值
iy3_mean = (iy3_max+iy3_min)/2
return data-iy3_mean
def hasPeaks(data):
max_peaks = list(argrelextrema(data, np.greater)[0])
min_peaks = list(argrelextrema(data, np.less)[0])
if len(max_peaks)>3 and len(min_peaks)>3:
return True
else:
return False
# 判断IMFs
def isIMFs(data):
max_peaks = list(argrelextrema(data, np.greater)[0])
min_peaks = list(argrelextrema(data, np.less)[0])
if min(data[max_peaks]) < 0 or max(data[min_peaks])>0:
return False
else:
return True
def getIMFs(data):
while(not isIMFs(data)):
data = sifting(data)
return data
# EMD函数
def EMD(data):
IMFs = []
while hasPeaks(data):
data_imf = getIMFs(data)
data = data-data_imf
IMFs.append(data_imf)
return IMFs
# 绘制对比图
data = np.random.random(1000)-0.5
IMFs = EMD(data)
n = len(IMFs)+1
# 原始信号
plt.figure(figsize = (18,15))
plt.subplot(n, 1, 1)
plt.plot(data, label='Origin')
plt.title("Origin ")
# 若干条IMFs曲线
for i in range(0,len(IMFs)):
plt.subplot(n, 1, i+2)
plt.plot(IMFs[i])
plt.ylabel('Amplitude')
plt.title("IMFs "+str(i+1))
plt.legend()
plt.xlabel('time (s)')
plt.ylabel('Amplitude')
これまでのところ、経験的モード分解 (EMD)の基本プロセスは 完了しました。