%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
= 1000
N = 1.0 / 800.0
dt = np.linspace(0.0, N*dt, N)
x = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x) + 0.2*np.sin(300.0 * 2.0*np.pi*x)
y
plt.plot(x, y)'Time')
plt.xlabel('Signal')
plt.ylabel('Initial signal')
plt.title("signal.pdf") plt.savefig(
= np.fft.fft(y)
yf = np.linspace(0.0, 1.0/(2.0*dt), N//2)
xf 2.0/N * np.abs(yf[0:N//2])) #Note: N/2 to N will give negative frequencies
plt.plot(xf, 'Frequency')
plt.xlabel('Amplitude')
plt.ylabel('Discrete Fourier transform')
plt.title("fourier.pdf") plt.savefig(
Быстрое преобразование Фурье
#FFT vs full matvec
import time
import numpy as np
import scipy as sp
import scipy.linalg
= 10000
n = sp.linalg.dft(n)
F = np.random.randn(n)
x
= F.dot(x)
y_full
= %timeit -q -o F.dot(x)
full_mv_time print('Full matvec time =', full_mv_time.average)
= np.fft.fft(x)
y_fft = %timeit -q -o np.fft.fft(x)
fft_mv_time print('FFT time =', fft_mv_time.average)
print('Relative error =', (np.linalg.norm(y_full - y_fft)) / np.linalg.norm(y_full))
Full matvec time = 0.02279096011857142
FFT time = 6.669329407142856e-05
Relative error = 1.5259489891556028e-12
Быстрый матвек с помощью БПФ
import numpy as np
import scipy as sp
import scipy.linalg
def circulant_matvec(c, x):
return np.fft.ifft(np.fft.fft(c) * np.fft.fft(x))
= 5000
n = np.random.random(n)
c = sp.linalg.circulant(c)
C = np.random.randn(n)
x
= C.dot(x)
y_full = %timeit -q -o C.dot(x)
full_mv_time print('Full matvec time =', full_mv_time.average)
= circulant_matvec(c, x)
y_fft = %timeit -q -o circulant_matvec(c, x)
fft_mv_time print('FFT time =', fft_mv_time.average)
print('Relative error =', (np.linalg.norm(y_full - y_fft)) / np.linalg.norm(y_full))
Full matvec time = 0.0033902745214286207
FFT time = 0.00010840322321428581
Relative error = 1.5542845153415997e-15
Свертки и фильтры
from scipy import signal
%matplotlib inline
import matplotlib.pyplot as plt
= 0.01
alpha = np.repeat([0., 1., 0.], 100)
sig = np.exp(-alpha * (np.arange(100)-50)**2)
filt = signal.convolve(sig, filt, mode='same') / sum(filt)
filtered
= plt.subplots(3, 1, sharex=True)
fig, (ax_orig, ax_filt, ax_filtered)
ax_orig.plot(sig)0, 0.1)
ax_orig.margins(
ax_filt.plot(filt)0, 0.1)
ax_filt.margins(
ax_filtered.plot(filtered)0, 0.1)
ax_filtered.margins(
'Original signal')
ax_orig.set_title('Filter')
ax_filt.set_title('Convolution')
ax_filtered.set_title(
fig.tight_layout()