今回は、ローパスフィルタを使って見てどんな挙動になるのか調べて見ました。
まず、簡単にローパスフィルタ(LPF)について説明します。
私も専門家というわけではないので簡単に!
ローパスフィルタと聞いて真っ先に思い浮かぶのはRC回路ではないでしょうか。
例えばエンコーダとか加速度センサとかを使うことを考えます。どのようなセンサも必ずノイズというものが乗ります。どれほどの量が乗るかはそのセンサによってまちまちだと思います。
また、全く同じ型番の製品でも個体差があるため、全く同じ挙動を示すセンサというものは実質ないと言えます。
ノイズとして例をあげると、部屋の蛍光灯とか家電製品から発せられる電磁波もノイズになります。
ローパスフィルタとはこのノイズの中で、高周波成分を取り除いて低周波成分のみを通すようなフィルタと思ってください。名前からも低周波成分(Low)を通す(pass)フィルタ(filter)ということですwww
もっと詳しく知りたい人はインターネットで調べればたくさん資料が出てくると思います。
では本題に戻ります。今回は離散信号のローパスフィルタを考えるのですが、その式は次のように書くことができます。
$$y[t]=\alpha y[t-1] +(1-\alpha)x[t]$$
ここで、$x[t]$は入力信号、$y[t]$は出力信号です。いい変えれば、「センサからゲットした値が$x[t]$で、フィルタをかけた後の値が$y[t]$」ということになります。一般的には$\alpha=0.8~0.9$くらいに設定するそうです。(この辺りは今回は詳しく調べていません)
どのような値を設定するべきかは、システムをモデル化して周波数成分を考えてカットオフ周波数を基準とすればいいと思いますが、今回は割愛です。
では、Pythonでノイズを乗せた元の関数を再現できるか実験して見ます。今回の実験条件としては次のようなものを考えてみたいと思います。
- 入力:$x[t]=t$、ノイズ:$e[t]=t^2{\rm sin^2}(t)$
- 入力:$x[t]=t^2$、ノイズ:$e[t]=t^2{\rm sin^2}(t)$
- 入力:$x[t]=t^3$、ノイズ:$e[t]=t^2{\rm sin^2}(t)$
今回はノイズを一定にして、線形、二次関数、三次関数について$0\leq t \leq 10000$の範囲で計算してみました。実際に使ったコードは次のものになります。なお、ローパスフィルタの係数は一律$\alpha = 0.8$としています。
import numpy as np
import matplotlib.pyplot as pat
x=np.array([i for i in range(10000)])
#フィルタ適用後のデータ格納用配列
_y1=np.array([i for i in range(10000)])
_y2=np.array([i for i in range(10000)])
_y3=np.array([i for i in range(10000)])
#真値
y1_true=x
y2_true=x**2
y3_true=x**3
#ノイズを乗せた後の値
y1_error=y1_true+x*x*(np.sin(x)**2)
y2_error=y2_true+x*x*(np.sin(x)**2)
y3_error=y3_true+x*x*(np.sin(x)**2)
#low pass
for i in range(10000):
if i==0:
_y1[i]=y1_error[0]
_y2[i]=y2_error[0]
_y3[i]=y3_error[0]
continue
_y1[i]=0.2*y1_error[i] + 0.8*_y1[i-1]
_y2[i]=0.2*y2_error[I] + 0.8*_y2[i-1]
_y3[i]=0.2*y3_error[i] + 0.8*_y3[i-1]
fig=plt.figure(figsize=(15,5))
ax1=fig.add_subplot(1,3,1)
ax2=fig.add_subplot(1,3,2)
ax3=fig.add_subplot(1,3,3)
ax1.plot(x,y1_error,color="g")
ax1.plot(x,_y1,color="b")
ax1.plot(x,y1_true,color="r",linewidth=2)
ax2.plot(x,y2_error,color="g")
ax2.plot(x,_y2,color="b")
ax2.plot(x,y2_true,color="r")
ax3.plot(x,y3_error,color="g")
ax3.plot(x,_y3,color="b")
ax3.plot(x,y3_true,color="r")
plt.show()
このコードを実行すると次のような結果となります。
今回ノイズとしてのせたデータは2次の誤差だったので、3時関数に対しては小さい誤差量だったためかほぼほぼ一致していました。緑の線は誤差を乗せた信号、青い線はフィルタを施した信号、赤い線は真値です。線形データに対しては誤差量が大きいので真値に近ずくことは難しいですが、かなり振動を抑えられていると考えられます。
今回はかなり大雑把な実験でしたが、実際に手を動かして実験したことで、どのような条件の場合にローパスフィルタを使えば良いかについて再度考えさせられました。
今後はハイパスフィルタなども使ってみたいと思います。