Scipy 实现了标准的 N 维卷积,使得要卷积的矩阵和内核都是 N 维的。
一个快速的解决方法是向Y 添加一个额外的维度,以便Y 是3 维的:
result = signal.convolve(X, Y[..., None], 'valid')
我在这里假设最后一个轴对应于图像索引,如您的示例[width, height, image_idx](或[height, width, image_idx])。如果反过来并且图像在第一个轴上被索引(因为它在 C 排序数组中更常见),则应将 Y[..., None] 替换为 Y[None, ...]。
Y[..., None] 线将为Y 添加一个额外的轴,使其成为 3 维 [kernel_width, kernel_height, 1],从而将其转换为有效的 3 维卷积核。
注意:这假设您的所有输入小批量都具有相同的width x height,这是 CNN 的标准。
编辑:@Divakar 建议的一些时间安排。
测试框架设置如下:
def test(S, N, K):
""" S: image size, N: num images, K: kernel size"""
a = np.random.randn(S, S, N)
b = np.random.randn(K, K)
valid = [slice(K//2, -K//2+1), slice(K//2, -K//2+1)]
%timeit signal.convolve(a, b[..., None], 'valid')
%timeit signal.fftconvolve(a, b[..., None], 'valid')
%timeit ndimage.convolve(a, b[..., None])[valid]
查找以下针对不同配置的测试:
-
改变图像大小S:
>>> test(100, 50, 11) # 100x100 images
1 loop, best of 3: 909 ms per loop
10 loops, best of 3: 116 ms per loop
10 loops, best of 3: 54.9 ms per loop
>>> test(1000, 50, 11) # 1000x1000 images
1 loop, best of 3: 1min 51s per loop
1 loop, best of 3: 16.5 s per loop
1 loop, best of 3: 5.66 s per loop
-
不同数量的图像N:
>>> test(100, 5, 11) # 5 images
10 loops, best of 3: 90.7 ms per loop
10 loops, best of 3: 26.7 ms per loop
100 loops, best of 3: 5.7 ms per loop
>>> test(100, 500, 11) # 500 images
1 loop, best of 3: 9.75 s per loop
1 loop, best of 3: 888 ms per loop
1 loop, best of 3: 727 ms per loop
-
改变内核大小K:
>>> test(100, 50, 5) # 5x5 kernels
1 loop, best of 3: 217 ms per loop
10 loops, best of 3: 100 ms per loop
100 loops, best of 3: 11.4 ms per loop
>>> test(100, 50, 31) # 31x31 kernels
1 loop, best of 3: 4.39 s per loop
1 loop, best of 3: 220 ms per loop
1 loop, best of 3: 560 ms per loop
所以,简而言之,ndimage.convolve 总是更快,除非内核非常大(如上次测试中的K = 31)。