離散フーリエ変換#
離散フーリエ変換#
複素フーリエ級数#
フーリエ係数の複素表示
より、
と書くことができる。
離散フーリエ変換#
円周上を
(1周期が
このサンプル点での
前述のフーリエ係数は連続関数
係数
Show code cell source
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(4, 3))
# 軸を描画
ax.arrow(-1.2, 0, 2.4, 0, head_width=0.05, head_length=0.1, fc='black', ec='black', length_includes_head=True)
ax.arrow(0, -1.2, 0, 2.4, head_width=0.05, head_length=0.1, fc='black', ec='black', length_includes_head=True)
ax.text(1.3, 0, "Re", fontsize=14, color='black')
ax.text(0, 1.3, "Im", fontsize=14, color='black')
ax.set_aspect('equal', adjustable='datalim')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.set(xticks=[], yticks=[])
# 単位円
theta = np.linspace(0, 2*np.pi, 100)
x = np.cos(theta)
y = np.sin(theta)
plt.plot(x, y, 'k-', linewidth=1) # 黒い実線で単位円を描画
# curve
t = 0.3*np.pi
theta = np.linspace(0, t, 100)
x = np.cos(theta) * 0.2
y = np.sin(theta) * 0.2
ax.plot(x, y, 'k--', linewidth=1) # 黒い実線で単位円を描画
# text
m = len(x) // 2
ax.text(x[m], y[m], r"$\theta_l = 2\pi l / N$")
# line
x = np.cos(t)
y = np.sin(t)
ax.plot([0, x], [0, y], color="blue", linestyle='-.', linewidth=0.8)
ax.scatter([x], [y], color="blue")
plt.show()

Tip
書籍によっては
としたり、あるいは
とすることがある
逆フーリエ変換#
ただし
これを使うことで、データ
となる。最後の項のカッコの中は
周期的な添字に拡張する#
取り扱いを便利にするため、以下では
このように拡張すると、総和は任意の連続する
周期関数のサンプリング定理#
帯域制限#
周期
帯域制限された周期関数は、ある間隔より細かくサンプルすればフーリエ係数
離散フーリエ変換
よって、 帯域制限された周期関数は、ある間隔より細かくサンプルすればそのサンプル値の補間によって表現できる。
周期関数のサンプリング定理#
周期関数のサンプリング定理
周期
ただし、
畳み込み和定理#
定義:畳み込み和
周期
畳み込み和定理
周期
証明
パワースペクトル#
パーセバルの式
と定義するとパーセバルの式の第2式は
と書き換えることができる。
データ
Show code cell source
import numpy as np
import matplotlib.pyplot as plt
# サンプルデータを生成する
N = 1000
d = 0.0001 # サンプリング周期
t = np.arange(0, N * d, d) # 時間
f = np.zeros_like(t)
components = [
# (スペクトルF_k, 周期θ)
(1.5, 50),
(2, 100),
(2.5, 200),
(2, 300),
(1, 500),
]
for F_k, frequency_k in components:
f += F_k * np.sin(t * 2 * np.pi * frequency_k)
F = np.fft.fft(f) # フーリエ変換
freq = np.fft.fftfreq(N, d=d) # 周波数スケール
# 振幅スペクトル Amplitude の取得
# 振幅スペクトルは信号をフーリエ変換した結果の絶対値をとったもの
Amp = np.abs(F)
Amp = Amp / (N / 2) # 正規化
Pow = Amp**2
# 結果をプロット
fig, axes = plt.subplots(nrows=2)
axes[0].plot(t, f)
axes[0].set(title=r'Data $\{ f_l \}$', xlabel=r"$l$", ylabel=r"$f_l$")
axes[1].stem(freq, Pow, 'r', markerfmt=" ", basefmt=" ")
# 左右対称なので正の値だけ N//2 で取り出してもいい
# axes[1].stem(freq[:N//2], Amp[:N//2], 'r', markerfmt=" ", basefmt=" ")
axes[1].set(title=f'Power $P_k$', xlabel=r'$k$', ylabel=r'$P_k$', xlim=(-550, 550))
fig.tight_layout()
fig.show()

Show code cell source
import numpy as np
import matplotlib.pyplot as plt
# サンプルデータを生成する
N = 100
d = 0.001 # サンプリング周期
t = np.arange(0, N * d, d) # 時間
f = np.zeros_like(t)
for k in range(2 * N): # 適当にNより大きいkにしてみる
F_k = k
frequency_k = k
f += F_k * np.sin(t * 2 * np.pi * frequency_k)
F = np.fft.fft(f) # フーリエ変換
freq = np.fft.fftfreq(N, d=d) # 周波数スケール
# 振幅スペクトル Amplitude の取得
# 振幅スペクトルは信号をフーリエ変換した結果の絶対値をとったもの
Amp = np.abs(F)
Amp = Amp / (N / 2) # 正規化
Pow = Amp**2
# 結果をプロット
fig, axes = plt.subplots(nrows=2)
axes[0].plot(t, f)
axes[0].set(title=r'Data $\{ f_l \}$', xlabel=r"$l$", ylabel=r"$f_l$")
axes[1].stem(freq, Pow, 'r', markerfmt=" ", basefmt=" ")
# 左右対称なので正の値だけ N//2 で取り出してもいい
# axes[1].stem(freq[:N//2], Amp[:N//2], 'r', markerfmt=" ", basefmt=" ")
axes[1].set(title=f'Power $P_k$', xlabel=r'$k$', ylabel=r'$P_k$')
fig.tight_layout()
fig.show()

自己相関係数#
周期
ウィーナー・ヒンチンの定理#
ウィーナー・ヒンチンの定理
周期
証明
まとめ#
連続のフーリエ変換と同様に、ウィーナー・ヒンチンの定理を使うことでもパワースペクトルを得ることができる。
しかし離散の場合は高速フーリエ変換があるため、ウィーナー・ヒンチンの定理を使うことによる計算量削減などの効果は相対的に低い。実用上は高速フーリエ変換一択になる。