不同维度的python卷积
Posted
技术标签:
【中文标题】不同维度的python卷积【英文标题】:python convolution with different dimension 【发布时间】:2017-01-06 08:25:46 【问题描述】:我正在尝试在 Python 中实现卷积神经网络。 但是,当我使用 signal.convolve 或 np.convolve 时,它不能对 X、Y(X 是 3d,Y 是 2d)进行卷积。 X 是训练小批量。 Y 是过滤器。 我不想为每个训练向量做 for 循环,例如:
for i in xrange(X.shape[2]):
result = signal.convolve(X[:,:,i], Y, 'valid')
....
那么,有什么函数可以用来有效地进行卷积吗?
【问题讨论】:
【参考方案1】: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
)。
【讨论】:
好发现!要获得更快的版本,请使用ndimage.filters.convolve(X,Y[...,None])
可能会进行一些切片?
@Divakar 最好安排时间(如果我有时间我会这样做),但我认为ndimage,filters.convolve
对于大内核大小应该更慢(因为它确实卷积在空间域中,而signal.convolve
在傅立叶域中进行)。 ndimage
过滤器的优点是支持不同的边界条件(不同于傅立叶,我认为根据定义相当于用 0 填充图像)。我会尽快安排时间!
@Divakar 测试完成!我觉得这是某种dejavu。正如您所建议的,ndimage.convolve
通常会更快。我记得在不同的线程中有过类似的对话哈哈
你知道什么是美好的记忆,而不仅仅是似曾相识! ;) 这是我认为您所指的帖子:***.com/a/38232755/3293881
@Divakar 哈哈,没错!那个时候我提议uniform_filter
超过signal.convolve
哈哈。尽管uniform_filter
由于内核的可分离性而更快,但上述结果似乎证实了我们在该线程中得出的结论:对于大内核大小傅里叶(fftconvolve)> 空间,如果不是空间>傅里叶。以上是关于不同维度的python卷积的主要内容,如果未能解决你的问题,请参考以下文章