Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Numpy FFT卷积如何以及为什么比直接卷积更快?_Numpy_Image Processing_Matrix_Signals_Fft - Fatal编程技术网

Numpy FFT卷积如何以及为什么比直接卷积更快?

Numpy FFT卷积如何以及为什么比直接卷积更快?,numpy,image-processing,matrix,signals,fft,Numpy,Image Processing,Matrix,Signals,Fft,我读到过卷积在频域计算时速度更快,因为它“只是”一个矩阵乘法(在2D中),而在时域它是很多小矩阵乘法 所以我做了这段代码,我们可以看到FFT卷积比“正常”卷积更复杂。 很明显,我的假设有问题 怎么了? 来自Symphy导入exp、日志、符号、初始打印、lambdify 初始打印(使用_latex='matplotlib') 将numpy作为np导入 将matplotlib.pyplot作为plt导入 定义复杂度(n): “”“大小为(n,n)的2个矩阵的MatMul的复杂性” #看https:/

我读到过卷积在频域计算时速度更快,因为它“只是”一个矩阵乘法(在2D中),而在时域它是很多小矩阵乘法

所以我做了这段代码,我们可以看到FFT卷积比“正常”卷积更复杂。 很明显,我的假设有问题

怎么了?
来自Symphy导入exp、日志、符号、初始打印、lambdify
初始打印(使用_latex='matplotlib')
将numpy作为np导入
将matplotlib.pyplot作为plt导入
定义复杂度(n):
“”“大小为(n,n)的2个矩阵的MatMul的复杂性”
#看https://en.wikipedia.org/wiki/Matrix_multiplication_algorithm
返回n**2.5
def _复数fft(n):
“”“fft和ifft的复杂性”“”
#看https://en.wikipedia.org/wiki/Fast_Fourier_transform
返回n*log(n)
def fft_mult_fft(n,m):
“”“频率空间中卷积的复杂度。
fft->M和内核之间的mult->ifft
"""
返回复fft(n)*2+复fft(n)
def conv(n,m):
“时空卷积的复杂性。
对于M的每n,我们执行2(M,M)矩阵的MatMul
"""
返回n*_复数(m)
n=符号('n')#M的大小=(n,n)
m=符号('m')#内核大小=(m,m)
M=np.linspace(1,1e3+1,1e1)
内核大小=np.linspace(2,7,7-2+1)**2
fft=fft\u mult\u fft(n,m)
离散=conv(n,m)
f1=lambdify(n,fft,'numpy')
f2=lambdify([n,m],离散的'numpy')
图,ax=plt.子批(1,len(内核大小),figsize=(30,10))
f1_computed=f1(M)#独立wrt M,不要每次都计算它
对于i,枚举中的大小(内核大小):
ax[i].绘图(M,f1_计算,c='red',label='freq domain(fft)'
ax[i].绘图(M,f2(M,大小),c='蓝色',标签='时域(正常)'
ax[i]。图例(loc='左上角')
ax[i].set_title(“内核大小={}”。格式(大小))
ax[i].集xlabel(“矩阵大小”)
ax[i].set_ylabel(“复杂性”)
以下是输出:(单击以缩放)


正如@user545424所指出的,问题在于我计算的是
n*复杂度(MatMul(kernel))
而不是
n²*复杂度(MatMul(kernel))
的“正常”卷积

我终于得到了:(其中n是输入的大小,m是内核的大小)


下面是最终代码和新图表

来自Symphy导入exp、日志、符号、初始打印、lambdify
初始打印(使用_latex='matplotlib')
将numpy作为np导入
将matplotlib.pyplot作为plt导入
定义复杂度(n):
“”“大小为(n,n)的2个矩阵的MatMul的复杂性”
#看https://en.wikipedia.org/wiki/Matrix_multiplication_algorithm
返回n**2.5
def _复数fft(n):
“”“fft和ifft的复杂性”“”
#看https://stackoverflow.com/questions/6514861/computational-complexity-of-the-fft-in-n-dimensions#comment37078975_6516856
返回4*(n**2)*日志(n)
def fft_mult_fft(n,m):
“”“频率空间中卷积的复杂度。
fft->M和内核之间的mult->ifft
"""
返回复fft(n)*2+复fft(n)
def conv(n,m):
“时空卷积的复杂性。
对于M的每个n*n单元,我们执行2(M,M)矩阵的MatMul
"""
返回n*n*_复数(m)
n=符号('n')#M的大小=(n,n)
m=符号('m')#内核大小=(m,m)
M=np.linspace(1,1e3+1,1e1)
内核大小=np.linspace(2,7,7-2+1)**2
fft\u symb=fft\u mult\u fft(n,m)
离散符号=conv(n,m)
fft_func=lambdify(n,fft_symb,'numpy')
dicrete_func=lambdify([n,m],离散符号,'numpy')
图,ax=plt.子批(1,len(内核大小),figsize=(30,10))
图贴片设置颜色(“灰色”)
对于i,枚举中的大小(内核大小):
ax[i].绘图(M,fft_func(M),c='red',label='freq domain(fft)'
ax[i].绘图(M,dicrete_func(M,size),c='blue',label='time domain(normal)'
ax[i]。图例(loc='左上角')
ax[i].set_title(“内核大小={}”。格式(大小))
ax[i].集xlabel(“矩阵大小”)
ax[i].set_ylabel(“复杂性”)

您正在经历两个众所周知的事实:

  • 对于较小的内核大小,空间方法更快

  • 对于较大的内核大小,频率方法可以更快


您的内核和图像太小,无法观察FFT的好处。

真是个有趣的问题!我不知道完整的答案,但只要看看2D FFT的复杂性:,
\u complex\u FFT
不应该是n^2 log(n)?而且,在
\u conv
中,我认为你必须将一个m x m矩阵乘以n^2倍,因为它是2D。你是对的,这就解决了它。你称它的大小是多少?n或n²???如代码中所述
n=符号('n')#M的大小=(n,n)
;内核大小是m,其中m=row*col(对于平方过滤器,这就是为什么我尝试使用2的幂)