簡體   English   中英

Numpy中的卷積比Matlab慢嗎?

[英]Is convolution slower in Numpy than in Matlab?

Matlab中的卷積似乎是Numpy中卷積的兩倍。

Python代碼(我的機器需要19秒):

import numpy as np
from scipy import ndimage
import time

img = np.ones((512,512,512))
kernel = np.ones((5,5,5))/125

start_time = time.time()
ndimage.convolve(img,kernel,mode='constant')
print "Numpy execution took ", (time.time() - start_time), "seconds"

Matlab代碼(在我的機器上花費8.7秒):

img = ones(512,512,512);
kernel = ones(5,5,5) / 125;
tic
convn(img, kernel, 'same');
toc

兩者給出相同的結果。

有沒有辦法改善Numpy以匹配或擊敗Matlab的表現?

有趣的是,這個因素或運行時間的差異在許多輸入大小是一致的。

你在做什么准確的手術? 如果您不需要一般的Nd卷積, ndimage提供許多優化。

例如,您當前的操作:

img = np.ones((512,512,512))
kernel = np.ones((5,5,5))/125
result = ndimage.convolve(img, kernel)

相當於:

img = np.ones((512,512,512))
result = ndimage.uniform_filter(img, 5)

但是,執行速度差異很大:

In [22]: %timeit ndimage.convolve(img, kernel)
1 loops, best of 3: 25.9 s per loop

In [23]: %timeit ndimage.uniform_filter(img, 5)
1 loops, best of 3: 8.69 s per loop

這種差異是由uniform_filter沿每個軸uniform_filter形成1-d卷積而不是通用3D卷積引起的。

在內核是對稱的情況下,您可以進行這些簡化並顯着加快速度。

我不確定convn ,但是如果您的輸入數據符合某些標准,matlab的函數通常會在幕后進行這些優化。 Scipy更常用的是每個函數一個算法,並希望用戶知道在哪種情況下選擇哪一個。


你提到了一個“高斯拉普拉斯”濾波器。 我總是對這里的術語感到困惑。

我認為你想要的ndimage函數是scipy.ndimage.gaussian_laplacescipy.ndimage.gaussian_filterorder=2 (由高斯的二階導數過濾)。

無論如何,兩者都將操作簡化為每個軸上的1-d卷積,這應該提供顯着的(2-3倍)加速。

不是anwer; 只是評論:

在比較性能之前,您需要確保兩個函數返回相同的結果:

如果Matlab的convn返回與Octave的convn相同的結果,那么convnndimage.convolve不同:

octave> convn(ones(3,3), ones(2,2))
ans =

   1   2   2   1
   2   4   4   2
   2   4   4   2
   1   2   2   1

In [99]: ndimage.convolve(np.ones((3,3)), np.ones((2,2)))
Out[99]: 
array([[ 4.,  4.,  4.],
       [ 4.,  4.,  4.],
       [ 4.,  4.,  4.]])

ndimage.convolve有其他模式, 'reflect','constant','nearest','mirror', 'wrap' ,但這些模式都不匹配convn的默認(“full”)行為。


對於2D數組, scipy.signal.convolve2dscipy.signal.convolve更快。

對於3D數組, scipy.signal.convolve似乎與convn(A,B)具有相同的行為:

octave> x = convn(ones(3,3,3), ones(2,2,2))
x =

ans(:,:,1) =

   1   2   2   1
   2   4   4   2
   2   4   4   2
   1   2   2   1

ans(:,:,2) =

   2   4   4   2
   4   8   8   4
   4   8   8   4
   2   4   4   2

ans(:,:,3) =

   2   4   4   2
   4   8   8   4
   4   8   8   4
   2   4   4   2

ans(:,:,4) =

   1   2   2   1
   2   4   4   2
   2   4   4   2
   1   2   2   1

In [109]: signal.convolve(np.ones((3,3,3), dtype='uint8'), np.ones((2,2,2), dtype='uint8'))
Out[109]: 
array([[[1, 2, 2, 1],
        [2, 4, 4, 2],
        [2, 4, 4, 2],
        [1, 2, 2, 1]],

       [[2, 4, 4, 2],
        [4, 8, 8, 4],
        [4, 8, 8, 4],
        [2, 4, 4, 2]],

       [[2, 4, 4, 2],
        [4, 8, 8, 4],
        [4, 8, 8, 4],
        [2, 4, 4, 2]],

       [[1, 2, 2, 1],
        [2, 4, 4, 2],
        [2, 4, 4, 2],
        [1, 2, 2, 1]]], dtype=uint8)

請注意, np.ones((n,m,p))默認創建一個float數組。 Matlab ones(n,m,p)似乎創建了一個int數組。 為了進行良好的比較,您應該嘗試將numpy數組的dtype與Matlab矩陣的類型相匹配。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM