使用 scipy fft 计算信号的自相关给出与直接计算不同的答案
Using scipy fft to calculate autocorrelation of a signal gives different answer from the direct calculation
我正在尝试使用 属性 计算信号的自相关,自相关是功率谱的逆傅立叶变换。但是,当我使用 scipy (或 numpy) fft 来执行此操作并与自相关函数的直接计算进行比较时,我得到了错误的答案,具体来说,fft 版本在一个小的负值处趋于平稳,延迟较大次,这显然是错误的。
下面是我的 MWE,以及输出。我使用的 fft 错了吗?
import numpy as np
import matplotlib.pyplot as pl
from scipy.fftpack import fft, ifft
def autocorrelation(x) :
xp = (x - np.average(x))/np.std(x)
f = fft(xp)
p = np.absolute(f)**2
pi = ifft(p)
return np.real(pi)[:len(xp)/2]/(len(xp))
def autocorrelation2(x):
maxdelay = len(x)/5
N = len(x)
mean = np.average(x)
var = np.var(x)
xp = (x - mean)/np.sqrt(var)
autocorrelation = np.zeros(maxdelay)
for r in range(maxdelay):
for k in range(N-r):
autocorrelation[r] += xp[k]*xp[k+r]
autocorrelation[r] /= float(N-r)
return autocorrelation
def autocorrelation3(x):
xp = (x - np.mean(x))/np.std(x)
result = np.correlate(xp, xp, mode='full')
return result[result.size/2:]/len(xp)
def main():
t = np.linspace(0,20,1024)
x = np.exp(-t**2)
pl.plot(t[:200], autocorrelation(x)[:200],label='scipy fft')
pl.plot(t[:200], autocorrelation2(x)[:200],label='direct autocorrelation')
pl.plot(t[:200], autocorrelation3(x)[:200],label='numpy correlate')
pl.legend()
pl.show()
if __name__=='__main__':
main()
离散 FT 假设信号是周期性的。因此,在基于 fft
的代码中,您正在计算环绕自相关。为避免这种情况,您必须执行某种形式的 0
-padding:
def autocorrelation(x):
xp = ifftshift((x - np.average(x))/np.std(x))
n, = xp.shape
xp = np.r_[xp[:n//2], np.zeros_like(xp), xp[n//2:]]
f = fft(xp)
p = np.absolute(f)**2
pi = ifft(p)
return np.real(pi)[:n//2]/(np.arange(n//2)[::-1]+n//2)
我正在尝试使用 属性 计算信号的自相关,自相关是功率谱的逆傅立叶变换。但是,当我使用 scipy (或 numpy) fft 来执行此操作并与自相关函数的直接计算进行比较时,我得到了错误的答案,具体来说,fft 版本在一个小的负值处趋于平稳,延迟较大次,这显然是错误的。
下面是我的 MWE,以及输出。我使用的 fft 错了吗?
import numpy as np
import matplotlib.pyplot as pl
from scipy.fftpack import fft, ifft
def autocorrelation(x) :
xp = (x - np.average(x))/np.std(x)
f = fft(xp)
p = np.absolute(f)**2
pi = ifft(p)
return np.real(pi)[:len(xp)/2]/(len(xp))
def autocorrelation2(x):
maxdelay = len(x)/5
N = len(x)
mean = np.average(x)
var = np.var(x)
xp = (x - mean)/np.sqrt(var)
autocorrelation = np.zeros(maxdelay)
for r in range(maxdelay):
for k in range(N-r):
autocorrelation[r] += xp[k]*xp[k+r]
autocorrelation[r] /= float(N-r)
return autocorrelation
def autocorrelation3(x):
xp = (x - np.mean(x))/np.std(x)
result = np.correlate(xp, xp, mode='full')
return result[result.size/2:]/len(xp)
def main():
t = np.linspace(0,20,1024)
x = np.exp(-t**2)
pl.plot(t[:200], autocorrelation(x)[:200],label='scipy fft')
pl.plot(t[:200], autocorrelation2(x)[:200],label='direct autocorrelation')
pl.plot(t[:200], autocorrelation3(x)[:200],label='numpy correlate')
pl.legend()
pl.show()
if __name__=='__main__':
main()
离散 FT 假设信号是周期性的。因此,在基于 fft
的代码中,您正在计算环绕自相关。为避免这种情况,您必须执行某种形式的 0
-padding:
def autocorrelation(x):
xp = ifftshift((x - np.average(x))/np.std(x))
n, = xp.shape
xp = np.r_[xp[:n//2], np.zeros_like(xp), xp[n//2:]]
f = fft(xp)
p = np.absolute(f)**2
pi = ifft(p)
return np.real(pi)[:n//2]/(np.arange(n//2)[::-1]+n//2)