Bu ek cevabı fft kullanırken sivri uçların yayılmasının kökenlerini açıklamak için yazıyorum ve özellikle bir noktada katılmadığım scipy.fftpack öğreticisini tartışıyorum .
Bu örnekte kayıt süresi tmax=N*T=0.75
. Sinyal sin(50*2*pi*x)+0.5*sin(80*2*pi*x)
. Frekans sinyali, frekanslarda 50
ve 80
amplitüdlerde 1
ve 0.5
. Bununla birlikte, analiz edilen sinyalde tam sayı periyot sayısı yoksa, sinyalin kesilmesi nedeniyle difüzyon ortaya çıkabilir:
- Pike 1:
50*tmax=37.5
=> frekans 50
, 1/tmax
=> Bu frekanstaki sinyal kesilmesinden dolayı difüzyonun bir katı değildir .
- Pike 2:
80*tmax=60
=> frekans 80
, 1/tmax
=> Bu frekanstaki sinyal kesilmesinden dolayı difüzyonun bir katıdır .
İşte öğreticide ( sin(50*2*pi*x)+0.5*sin(80*2*pi*x)
) aynı sinyali analiz eden ancak küçük farklılıklar içeren bir kod :
- Orijinal scipy.fftpack örneği.
- Tam sayı sinyal periyotları içeren orijinal scipy.fftpack örneği ( kesilme difüzyonunu önlemek
tmax=1.0
yerine 0.75
).
- Tam sayı sinyal periyotları içeren ve tarihlerin ve frekansların FFT teorisinden alındığı orijinal scipy.fftpack örneği.
Kod:
import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack
N = 600
tmax = 3/4
T = tmax / N
x1 = np.linspace(0.0, N*T, N)
y1 = np.sin(50.0 * 2.0*np.pi*x1) + 0.5*np.sin(80.0 * 2.0*np.pi*x1)
yf1 = scipy.fftpack.fft(y1)
xf1 = np.linspace(0.0, 1.0/(2.0*T), N//2)
tmax = 1
T = tmax / N
x2 = np.linspace(0.0, N*T, N)
y2 = np.sin(50.0 * 2.0*np.pi*x2) + 0.5*np.sin(80.0 * 2.0*np.pi*x2)
yf2 = scipy.fftpack.fft(y2)
xf2 = np.linspace(0.0, 1.0/(2.0*T), N//2)
tmax = 1
T = tmax / N
x3 = T * np.arange(N)
y3 = np.sin(50.0 * 2.0*np.pi*x3) + 0.5*np.sin(80.0 * 2.0*np.pi*x3)
yf3 = scipy.fftpack.fft(y3)
xf3 = 1/(N*T) * np.arange(N)[:N//2]
fig, ax = plt.subplots()
ax.plot(xf1, 2.0/N * np.abs(yf1[:N//2]), label='fftpack tutorial')
ax.plot(xf2, 2.0/N * np.abs(yf2[:N//2]), label='Integer number of periods')
ax.plot(xf3, 2.0/N * np.abs(yf3[:N//2]), label='Correct positionning of dates')
plt.legend()
plt.grid()
plt.show()
Çıktı:
Burada olabileceği gibi, tamsayı sayıda periyot kullanılsa bile bir miktar difüzyon kalır. Bu davranış, scipy.fftpack öğreticisindeki tarihlerin ve sıklıkların kötü konumlandırılmasından kaynaklanmaktadır. Bu nedenle, ayrık Fourier dönüşümleri teorisinde:
- sinyal,
t=0,T,...,(N-1)*T
T'nin örnekleme periyodu ve sinyalin toplam süresinin olduğu tarihlerde değerlendirilmelidir tmax=N*T
. Durduğumuzu unutmayın tmax-T
.
- ilişkili frekanslar , örnekleme frekansının
f=0,df,...,(N-1)*df
olduğu yerdir df=1/tmax=1/(N*T)
. Yayılmayı önlemek için sinyalin tüm harmonikleri örnekleme frekansının çok katı olmalıdır.
Yukarıdaki örnekte, arange
yerine kullanımının linspace
frekans spektrumunda ek difüzyonu önlemeyi sağladığını görebilirsiniz . Dahası, linspace
versiyonun kullanılması, aynı zamanda, olması gerekenden biraz daha yüksek frekanslarda bulunan sivri uçların kaymasına da yol açar, bu sivri uçların frekansların biraz sağında olduğu ilk resimde görüldüğü gibi 50
ve 80
.
Sadece kullanım örneğinin aşağıdaki kodla değiştirilmesi gerektiği sonucuna varacağım (ki bu benim görüşüme göre daha az yanıltıcıdır):
import numpy as np
from scipy.fftpack import fft
N = 600
T = 1.0 / 800.0
x = T*np.arange(N)
y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)
yf = fft(y)
xf = 1/(N*T)*np.arange(N//2)
import matplotlib.pyplot as plt
plt.plot(xf, 2.0/N * np.abs(yf[0:N//2]))
plt.grid()
plt.show()
Çıktı (ikinci artış artık dağınık değil):
Bence bu yanıt, ayrık Fourier dönüşümünün doğru şekilde nasıl uygulanacağına dair bazı ek açıklamalar getirmeye devam ediyor. Açıkçası, cevabım çok uzun ve her zaman söylenecek ek şeyler var (@ewerlopes örneğin kısaca takma addan bahsetti ve pencereleme hakkında çok şey söylenebilir ) bu yüzden duracağım. Bunu uygularken ayrık Fourier dönüşümü ilkelerini derinlemesine anlamanın çok önemli olduğunu düşünüyorum çünkü hepimiz istediklerini elde etmek için onu uygularken buraya ve oraya faktör ekleyen çok fazla insan biliyoruz.