2013-02-28 73 views
2

我使用numpy和matplotlib來分析我模擬的數據輸出。有一個(明顯的)不一致,我找不到根源。它有以下幾種:(numpy)FFT數組的錯誤幅度(?)?

我有一個信號,具有給定的能量a^2〜1。當我使用rfft進行傅里葉變換並計算傅里葉空間中的能量時,它會變得更大。排尿給我的數據等的細節,這裏是一個簡單的正弦波的例子:

from pylab import * 
xx=np.linspace(0.,2*pi,128) 
a=np.zeros(128) 
for i in range(0,128): 
    a[i]=sin(xx[i]) 
aft=rfft(a) 
print mean(abs(aft)**2),mean(a**2) 

原則上這兩個數字應該是相同的(至少在數字意義上的),但是這是我擺脫這種代碼:

62.523081632 0.49609375 

我試圖去通過numpy.fft文檔,但無法找到任何東西。這裏的一個搜索提供了以下但我無法理解的解釋有:

Big FFT amplitude difference between the existing (synthesized) signal and the filtered signal

我缺少/誤解?任何幫助/指針在這方面將不勝感激。

謝謝!

+0

[Parseval's theorem in Python]可能的重複(http://stackoverflow.com/questions/14011506/parsevals-theorem-in-python) – Jaime 2013-03-01 00:19:35

回答

6

亨利是非正常化的一部分,但有一點點它,因爲你使用的是rfft而不是fft。以下是他的回答是一致的:

>>> x = np.linspace(0, 2 * np.pi, 128) 
>>> y = 1 - np.sin(x) 
>>> fft = np.fft.fft(y) 
>>> np.mean((fft * fft.conj()).real) 
191.49999999999991 
>>> np.mean(y**2) 
1.4960937500000004 
>>> fft = fft/np.sqrt(len(fft)) 
>>> np.mean((fft * fft.conj()).real) 
1.4960937499999991 

但如果你現在rfft嘗試同樣的事情也不太工作了:

>>> rfft = np.fft.rfft(y) 
>>> np.mean((rfft * rfft.conj()).real) 
314.58462009358772 
>>> rfft /= np.sqrt(len(rfft)) 
>>> np.mean((rfft * rfft.conj()).real) 
4.8397633860551954 
65 
>>> np.mean((rfft * rfft.conj()).real)/len(rfft) 
4.8397633860551954 

下不正常,但:

>>> (rfft[0] * rfft[0].conj() + 
... 2 * np.sum(rfft[1:] * rfft[1:].conj())).real/len(y) 
1.4960937873636722 

當你使用rfft你得到的是不正確的DFT你的數據,但只有它的正半數,因爲負將是對稱的tric到它。爲了計算平均值,您需要考慮除DC分量兩次以外的每個值,這是最後一行代碼的作用。

+0

謝謝傑米!這非常有幫助!我不記得文檔中奇怪的標準化方案。來自IDL,我習慣於通過fft例程自動完成。現在我知道在某些情況下我開始使用某種其他語言會更好。 – toylas 2013-03-01 03:35:22

+0

這不是奇怪的,它是DFT。根據[本IDL文檔](http://www.exelisvis.com/docs/FFT.html),在正向操作時會應用完整的標準化,因此您仍然會得到不正確的功率測量結果。 – 2013-03-01 11:25:57

+0

顯然,在此期間'rfft'的規範化已經發生了變化。給定的規範化不再適用於numpy 1.8.2。 – fuesika 2016-09-01 11:23:33

3

在大多數FFT庫中,各種DFT風味不是orthogonalnumpy.fft庫僅在逆變換過程中應用必要的歸一化。

考慮Wikipedia description of the DFT;逆DFT具有DFT不具有的1/N項(其中N是變換的長度)。要製作DFT的正交版本,您需要將非歸一化DFT的結果縮放1/sqrt(N)。在這種情況下,變換是正交的(即,如果我們將正交DFT定義爲F,則逆DFT是F的共軛或厄密轉置)。

在你的情況,你可以簡單地通過1.0/sqrt(len(a))縮放aft得到正確的答案(注意,N從長度發現變換;真正的FFT只是拋出一半左右的值了,所以它的a長度這很重要)。

我懷疑離開標準化到最後的原因是在大多數情況下,這並不重要,因此您可以節省執行兩次標準化的計算成本。事實上,非常快速的FFTW library不會在任何方向進行任何標準化,並且完全由用戶來處理。

編輯:只是要清楚,上面的解釋是不完全正確的。以這種簡單的縮放比例不會得到正確的答案,因爲在您的情況下,DC分量將被添加兩次,儘管1.0/sqrt(len(a))仍然是產生幺正變換的正確比例。

+0

對於缺少標準化因素,您是非常正確的。但是關於如何從'rfft'獲得正確結果的評論是非常錯誤的,因爲簡單地嘗試一下就會顯示出來。 – Jaime 2013-03-01 00:18:58

+1

*非常錯誤*不誠實;縮放是正確的。我錯了,但只是在我所說的縮放比例足夠的情況下。我想這會教會我用時差來寫答案。 – 2013-03-01 11:20:16

+0

如果我的評論過於苛刻,請接受我的道歉。但不幸的是,你仍然錯了。 'rfft',除了重複的條件被排除在外,幾乎2倍的加速,返回的結果與你從'fft'中得到的完全一樣。因此它必須以相同的方式進行縮放以獲得幺正變換:通過數據長度的平方根,而不是變換中唯一值的平方根。無論輸入的性質如何,[Parseval定理](http://en.wikipedia.org/wiki/Discrete_Fourier_transform#The_Plancherel_theorem_and_Parseval.27s_theorem)都是相同的。 – Jaime 2013-03-01 14:24:27