2013-05-28 54 views
6

我知道在1-d情況下,兩個矢量a,b之間的卷積可以被計算爲 conv(a,b),而且作爲T_ab之間的乘積,其中T_a是相應的Toeplitz矩陣爲a2-d卷積作爲基質 - 矩陣乘法

是否有可能將此想法擴展到2-D?

鑑於a=[5 1 3;1 1 2;2 1 3]b=[4 3;1 2],是有可能a轉換在託普利茲矩陣,並計算T_ab作爲之間的矩陣矩陣產物在1-d的情況下?

回答

7

是的,這是可能的,你也應該使用一個雙塊循環矩陣(這是矩陣的一個特例Toeplitz)。我將給你一個小內核和輸入的例子,但是可以爲任何內核構造Toeplitz矩陣。所以你有一個2d輸入x和2d內核k,你想計算卷積x * k。我們還假設k已翻轉。我們還假設x的尺寸爲nxn,而k的尺寸爲mxm

因此,您將k展開爲大小爲(n-m+1)^2 X n^2的稀疏矩陣,並將x展開爲長向量n^2 X 1。你計算這個稀疏矩陣與一個向量的乘積,並將結果向量(它的大小爲(n-m+1)^2 X 1)轉換成一個n-m+1方陣。

我很確定這很難從閱讀中理解。所以這裏是2x2內核和3x3輸入的例子。

enter image description here * enter image description here

這裏是與載體構建的矩陣:

enter image description here

其等於enter image description here

而這與通過k的滑動窗口超過x所得到的結果相同。

+1

有必須是某種在年底重塑正確的?最後一個向量是4 x 1,但是卷積的結果是2 x 2 – jvans

+0

@jvans是的,最後你應該重塑你的向量。它寫在這裏:**將得到的向量(其大小(n-m + 1)^ 2 X 1)轉換爲n-m + 1方陣** –

2

如果你解開k以我^ 2載體,展開X,你會再拿到:

  • 一個m**2矢量k
  • 一個((n-m)**2, m**2)矩陣unrolled_X

其中unrolled_X可能通過以下Python代碼獲得:

from numpy import zeros 


def unroll_matrix(X, m): 
    flat_X = X.flatten() 
    n = X.shape[0] 
    unrolled_X = zeros(((n - m) ** 2, m**2)) 
    skipped = 0 
    for i in range(n ** 2): 
     if (i % n) < n - m and ((i/n) % n) < n - m: 
      for j in range(m): 
       for l in range(m): 
        unrolled_X[i - skipped, j * m + l] = flat_X[i + j * n + l] 
     else: 
      skipped += 1 
    return unrolled_X 

展開X而不是k允許爲每個X使用更緊湊的表示(更小的矩陣) - 但您需要展開每個X.您可能更願意展開k,具體取決於您想要執行的操作。

在這裏,unrolled_X不稀疏,而unrolled_k將是稀疏的,但大小爲((n-m+1)^2,n^2)作爲@Salvador Dali提到。

展開k可以這樣進行:

from scipy.sparse import lil_matrix 
from numpy import zeros 
import scipy 


def unroll_kernel(kernel, n, sparse=True): 

    m = kernel.shape[0] 
    if sparse: 
     unrolled_K = lil_matrix(((n - m)**2, n**2)) 
    else: 
     unrolled_K = zeros(((n - m)**2, n**2)) 

    skipped = 0 
    for i in range(n ** 2): 
     if (i % n) < n - m and((i/n) % n) < n - m: 
      for j in range(m): 
       for l in range(m): 
        unrolled_K[i - skipped, i + j * n + l] = kernel[j, l] 
     else: 
      skipped += 1 
    return unrolled_K