加速 numpy 3D 数组的卷积循环?

2024-01-18

沿着 3d numpy 数组的 Z 向量执行卷积,然后对结果进行其他操作,但由于现在实现的原因,速度很慢。是 for 循环让我慢下来还是卷积?我尝试重塑为一维向量并在 1 遍中执行卷积(就像我在 Matlab 中所做的那样),而不使用 for 循环,但它并没有提高性能。我的 Matlab 版本比我在 Python 中能想到的任何版本快大约 50%。相关代码部分:

convolved=np.zeros((y_lines,x_lines,z_depth))
for i in range(0, y_lines):
    for j in range(0, x_lines):
        convolved[i,j,:]= fftconvolve(data[i,j,:], Gauss) #80% of time here
        result[i,j,:]= other_calculations(convolved[i,j,:]) #20% of time here

有没有比 for 循环更好的方法来做到这一点?听说过 Cython,但到目前为止我对 Python 的经验有限,我的目标是最简单的解决方案。


The fftconvolve您正在使用的函数可能来自SciPy http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.fftconvolve.html。如果是这样,请注意它需要 N 维数组。因此,进行卷积的更快方法是生成 3d 内核,该内核对应于在x and y维度并进行一维高斯卷积z.

下面是一些代码和计时结果。在我的机器上并使用一些玩具数据,这导致了 10 倍的加速,如您所见:

import numpy as np
from scipy.signal import fftconvolve
from scipy.ndimage.filters import gaussian_filter

# use scipy filtering functions designed to apply kernels to isolate a 1d gaussian kernel
kernel_base = np.ones(shape=(5))
kernel_1d = gaussian_filter(kernel_base, sigma=1, mode='constant')
kernel_1d = kernel_1d / np.sum(kernel_1d)

# make the 3d kernel that does gaussian convolution in z axis only
kernel_3d = np.zeros(shape=(1, 1, 5,))
kernel_3d[0, 0, :] = kernel_1d

# generate random data
data = np.random.random(size=(50, 50, 50))

# define a function for loop based convolution for easy timeit invocation
def convolve_with_loops(data):
    nx, ny, nz = data.shape
    convolved=np.zeros((nx, ny, nz))
    for i in range(0, nx):
        for j in range(0, ny):
            convolved[i,j,:]= fftconvolve(data[i, j, :], kernel_1d, mode='same') 
    return convolved

# compute the convolution two diff. ways: with loops (first) or as a 3d convolution (2nd)
convolved = convolve_with_loops(data)
convolved_2 = fftconvolve(data, kernel_3d, mode='same')

# raise an error unless the two computations return equivalent results
assert np.all(np.isclose(convolved, convolved_2))

# time the two routes of the computation
%timeit convolved = convolve_with_loops(data)
%timeit convolved_2 = fftconvolve(data, kernel_3d, mode='same')

timeit结果:

10 loops, best of 3: 198 ms per loop
100 loops, best of 3: 18.1 ms per loop
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

加速 numpy 3D 数组的卷积循环? 的相关文章

随机推荐