はじめに
以前の記事でPSDから粗面を計算する際に、粗面高さは実数となるのは自明なのですが、fftでなくrfftを使った方が遥かに楽に計算できました。rfftの使い方、fftとの違いについてまとめます。
ポイントさえ押さえれば、rfftは非常に便利です。
以下の記事で、rfftを使って実際に数値計算を行いました。
Numpyのrfftってなに?
入力が実数の時にrfftを使えます。rはrealの頭文字です。fftは入力が実数だろうが複素数だろうが計算可能です。
何がrfftのメリットでしょうか?
実数のデータをフーリエ変換した結果は、エルミート対称になります。
エルミート対称性は下式で表せるのでした。*は複素共役の意味です。
$$
F(-k_x, -k_y) = F^*(k_x, k_y)
$$
負の周波数成分は正の周波数成分の複素共役になるため、片側だけ持てば十分です。
正の周波数成分だけ保持すれば十分で、rfftを使えばその分メモリが節約できるのです。
入力がN点あったとすると、fftはN点返ってくるのに対してrfftでは$N//2+1$点のデータが返って来るので大体半分程度で済みます。
($N//2$は商の整数部分を表します。)
irfftが役立つ場面
メモリ節約だけだと大きいデータ扱っていてしかも実数入力制限があるときだけしか役にたたないように思いますが、irfft(rfftの逆変換)まで考えると別のメリットがあります。
rfftとirfft(rfftの逆変換)の関係を示します。
実数信号 x
|
rfft
↓
片側スペクトル X
(複素数)
|
irfft
↓
実数信号 x
irfftは計算結果が必ず実数になるため、実数物理量を扱う場合に便利です。
量子力学でエルミート対称性が唐突に出てきますが、扱う演算子の固有値が実数の物理量に対応するためです。
実装上の注意
入力に対してエルミート対称条件を課してfftすることでも理論上は計算可能です。
しかし、条件設定のミスによるバグが入りやすく、計算誤差によって本来不要な複素数成分が残ります。
そのため、計算結果が実数信号となる場合はirfftを使うことをおすすめします。
2Dデータのrfftとハマりどころ
試しに2Dの計算して形状を確認します。rfft2を使ってみましょう。
import numpy as np
x = np.random.rand(1024, 1024)
X = np.fft.rfft2(x)
print(X.shape)変換後のNumpy array形状は下記です。
(1024, 513)
形状が入力の1024×1024が1024×513に変化しました。
513って何?となるかもしれませんが、$1024//2+1 =513$なので、対応しています。
defaultでは「最後の軸(axis=-1)」にrfftが適用される点に注意です。
axis=-1は最後の軸を意味していて2次元だと列方向を意味します。
numpyの2次元以上のrfftでは、指定した軸のみでrfftが行われ、残りの軸ではfftが計算されます。
そのため、どの軸でrfftを実行するか指定できるようになっています。rfftを行う軸方向はaxes引数で指定します。
defaultではaxes=(-2, -1)となっていて、列方向がrfft、行方向がfftされます。
逆にしたければ、axes=(-1, 0)とすればよいです。
出力shapeはrfft実施した方向が$N//2+1$点になります。
実数データをirfft2で復元する場合は、rfft2の出力と同じshape(この例では1024×513)の配列を用意することになります。
まとめ
本記事ではNumpyのrfftについて解説しました。
- 実数入力の場合、FFT結果はエルミート対称になるため、負の周波数成分を省略できる
rfftを使うことでFFT結果を半分程度のサイズで扱うことができるirfftを使うことで、逆変換後の結果を実数として扱える- 2D FFTでは最後に指定した軸に
rfftが適用されるため、出力shapeに注意が必要
特に画像処理や光学シミュレーションなどの2次元データを扱う場合、rfft2の出力shapeを理解しておくことが重要です。
参考文献
Pythonでデータ分析に取り組むなら、手元に置いておきたい一冊です。
本書では、pandas・NumPy・Jupyter Notebook といったデータ分析でよく使われるツールを取り上げ、データの処理や分析の進め方を学べます。これからデータ分析を始めたい方はもちろん、普段使っているコードを見直し、データ処理の基礎を整理したい方にもおすすめです。
フーリエ変換、フーリエ光学を日本語で学びたい方におすすめの一冊です。 線形システム、回折、フーリエ変換も分かりやすく解説しており体系的に理解できます。



コメント