指数移動平均(Exponential Moving Averages)フィルタの周波数特性

指数移動平均(Exponential Moving Averages;EMA)

入力$x$に対して,平滑化率$\beta$に応じて時系列平滑化を行い$y$を得ることによって時系列データを平滑化する代表的な手法である. 1ステップ前のフィルタリングされたの値と現在の観測値を$\beta$を用いて重み付けし足し合わせることで, 最近のデータを重視するとともに古いデータを完全には切り捨てない仕組みとなっている.

$$y_t=\beta y_{t-1}+(1-\beta)x_t$$

ゲイン特性と位相特性

上式をラプラス変換する.

$$Y(s)=\beta e^{-s}Y(s)+(1-\beta)X(s)$$

式変形し伝達関数を求める.

$$G(s)=\frac{Y(s)}{X(s)}=\frac{\beta}{1+(1-\beta)e^{-s}}$$

$s=jw$とする.

$$G(jw)= \frac{\beta}{1+(1-\beta)e^{-jw}}$$

ゲイン特性と位相特性は以下の様になる.

$$|G(jw)| = \frac{\beta}{\sqrt{1-2(1-\beta) \cos w+(1-\beta)^2}}$$

ゲイン特性

$$\angle G(jw) = \tan^{-1} (\frac{-\sin w}{\cos w-(1-\beta)})$$

位相特性

$\beta$が小さい場合,周波数帯域が狭く強い平滑化を行うことができるが位相遅れが大きくなる. 一方で$\beta$が大きい場合,位相遅れは小さいが平滑化能力が低下することがわかる.

プログラム

import math
import matplotlib.pyplot as plt

BETA = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
LENGE = 300
frequency = [[] for _ in range(len(BETA))]
gain  = [[] for _ in range(len(BETA))]
phase = [[] for _ in range(len(BETA))]

def get_gain(beta, w):
    return beta / math.sqrt(1-2*(1-beta)*math.cos(w)+(1-beta)*(1-beta))

def get_phase(beta, w):
    return math.atan(-math.sin(w)/(math.cos(w)-(1-beta)))

for beta_index in range(len(BETA)):
    for w in range(LENGE):
        frequency[beta_index].append(w/100)
        gain[beta_index].append(get_gain(BETA[beta_index], w/100))
        phase[beta_index].append(get_phase(BETA[beta_index], w/100))

plt.figure()
plt.xlabel('Frequency(rad/s)')
plt.ylabel('Gain[dB]')
for beta_index in range(len(BETA)):
    plt.plot(frequency[beta_index], gain[beta_index], label="beta="+str(BETA[beta_index]))
plt.legend(bbox_to_anchor=(1.05, 1.0), loc='upper left')
plt.show()

plt.figure()
plt.xlabel('Frequency(rad/s)')
plt.ylabel('Phase[deg]')
for beta_index in range(len(BETA)):
    plt.plot(frequency[beta_index], phase[beta_index], label="beta="+str(BETA[beta_index]))
plt.legend(bbox_to_anchor=(1.05, 1.0), loc='upper left')
plt.show()

参考

Tags: