2011-03-08 28 views
13

我有兩個具有相同第一軸尺寸的二維陣列。在python中,我想只將這兩個矩陣沿着第二個軸進行卷積。我想在下面得到C而不是沿第一軸計算卷積。僅沿一個軸進行卷積

import numpy as np 
import scipy.signal as sg 

M, N, P = 4, 10, 20 
A = np.random.randn(M, N) 
B = np.random.randn(M, P) 

C = sg.convolve(A, B, 'full')[(2*M-1)/2] 

有沒有快速的方法?

回答

3

隨着ndimage.convolve1d,您可以指定軸......

+1

感謝您指出。然而,「權重」的論點需要是一維的。在我的情況下,它是二維的。 – Paul 2011-03-10 19:04:04

+0

@Paul:上下文是什麼? B的權重是多少? – Benjamin 2011-03-10 19:39:47

+0

A中的每一行都被B中的相應行過濾。我可以像這樣實現它,只是認爲可能有更快的方法。 A的大小爲10 GB,我使用overlap-add。 – Paul 2011-03-11 05:50:26

8

您可以使用np.apply_along_axis沿所需軸適用np.convolve。這裏是施加矩形波串濾波器爲2D陣列的例子:

import numpy as np 

a = np.arange(10) 
a = np.vstack((a,a)).T 

filt = np.ones(3) 

np.apply_along_axis(lambda m: np.convolve(m, filt, mode='full'), axis=0, arr=a) 

這是一種簡單的方法來概括不具有一個axis參數的許多功能。

+3

這是否有任何加速比vs沿每一行的循環? – endolith 2014-04-05 19:32:44

+0

@endolith不,它不是。見[this](http://stackoverflow.com/a/23849233/525169)answer ... – Praveen 2016-08-06 00:57:40

+0

'np.apply_along_axis'實際上不能在這裏使用,因爲OP希望它在兩個數組上迭代。要做到這一點的方法是簡單地使用循環,如[這裏]所述( HTTP://計算器。COM /問題/ 28898858 /蟒申請-沿軸的-多陣列)。 – Praveen 2016-08-06 01:50:42

3

np.apply_along_axis不會真的幫到你,因爲你試圖遍歷兩個數組。實際上,您必須使用循環,如here所述。

現在,如果你的數組很小,循環就很好,但是如果N和P很大,那麼你可能想用FFT來代替。

但是,你需要適當的零墊的陣列首先,讓你的「滿」卷積有預期形狀:

M, N, P = 4, 10, 20 
A = np.random.randn(M, N) 
B = np.random.randn(M, P) 

A_ = np.zeros((M, N+P-1), dtype=A.dtype) 
A_[:, :N] = A 
B_ = np.zeros((M, N+P-1), dtype=B.dtype) 
B_[:, :P] = B 

A_fft = np.fft.fft(A_, axis=1) 
B_fft = np.fft.fft(B_, axis=1) 
C_fft = A_fft * B_fft 

C = np.real(np.fft.ifft(C_fft)) 

# Test 
C_test = np.zeros((M, N+P-1)) 
for i in range(M): 
    C_test[i, :] = np.convolve(A[i, :], B[i, :], 'full') 

assert np.allclose(C, C_test) 
2

二維陣列,功能scipy.signal.convolve2d更快,SciPy的.signal.fftconvolve可以更快(取決於陣列的尺寸):

這裏相同的代碼具有N = 100000

import time  
import numpy as np 
import scipy.signal as sg 

M, N, P = 10, 100000, 20 
A = np.random.randn(M, N) 
B = np.random.randn(M, P) 

T1 = time.time() 
C = sg.convolve(A, B, 'full') 
print(time.time()-T1) 

T1 = time.time() 
C_2d = sg.convolve2d(A, B, 'full') 
print(time.time()-T1) 

T1 = time.time() 
C_fft = sg.fftconvolve(A, B, 'full') 
print(time.time()-T1) 

>>> 12.3 
>>> 2.1 
>>> 0.6 

答案都是由於使用不同的計算方法(例如,fft vs直接乘法,但我不知道什麼exaclty convolve2d使用),所以略有差異:

print(np.max(np.abs(C - C_2d))) 
>>>7.81597009336e-14 

print(np.max(np.abs(C - C_fft))) 
>>>1.84741111298e-13