下面我們只考慮圓周卷積的情況, * 代表圓周卷積,
對於一維列向量,a 和 b, 假設c = a*b
由於卷積是一個有限維度的線性運算,那么可以表達為矩陣向量的乘法形式
這里面 M 是一個 Circulant Matrix,而Circulant Matrix 是一種特殊的 Toeplitz Matrix 可以被 DFT Matrix 對角化。
那么
從右往左看這里面
是b 的傅里葉變換,
是逐點相乘,FLOPS很便宜,
是逆傅里葉變換。 這里面由於傅里葉變換的屬性,我們存在快速解法, MIT 著名線性代數教授Gilbert Strang 曾經描述過FFT 算法可能是我們一生當中最重要的數值方法,他從
降低到了
。這樣子我們每一步都能有一個比較省flops 的操作,那么整體上我們能夠有一種相對快的方法。
但是實際生活當中用zero padding FFT 作快卷積,不一定快,尤其是當卷積一方比較 小的時候,或者為了滿足類似
這樣的 zero padding使得padding 長度過大,那么fft 做卷積都是慢的。只有當兩者長度可比擬時候fft的優勢才能體現出來。
所以由此延伸出更好的overlap discard, overlap save等快速卷積方法,可以改善上述問題: https://en.wikipedia.org/wiki/Overlap%E2%80%93save_method
備注 1: FFT 其實是一種特殊的范德蒙矩陣, 范德蒙矩陣的一類子集都存在矩陣向量相乘的快速數值方法,比如Fast Walsh Hadmard Transform等 https://en.wikipedia.org/wiki/Fast_Walsh%E2%80%93Hadamard_transform
備注 2: 但是!但是! 所有上述推導都是純理論的flops比較,但是實際上flops小的速度並不一定快!!!!我的數值線性代數教授反復給我們強調過這一點!!!!
是否能夠減少overhead, 還有能否充分調用CPU/GPU 性能, 是否高度可並行化很多時候才能在實際生活中真正決定速度,紙上得來終覺淺哈,理論固然重要,但是不要輕易相信任何數值方法給的結論,最重要的是真的在實際生活中在對應的硬件軟件平台上跑一跑才知道的。
這是一個DFT:
- k表示每N個樣本的循環次數;
- N表示信號的長度;
- 表示信號在樣本n處的值。
一個信號可以表示為所有正弦信號的和。
yk是一個復值,它給出了信號x中頻率為k的正弦信號的信息;從yk我們可以計算正弦的振幅和相位。
換成矩陣式,它就變成了這樣:
這里給出了特定值k的傅里葉值。
不過通常情況下,我們要計算全頻譜,即k從[0,1,…N-1]的值,這可以用一個矩陣來表示(k按列遞增,n按行遞增):
簡化后得到
