我知道在1-d情況下,兩個矢量a,b
之間的卷積可以被計算爲 conv(a,b)
,而且作爲T_a
和b
之間的乘積,其中T_a
是相應的Toeplitz矩陣爲a
。2-d卷積作爲基質 - 矩陣乘法
是否有可能將此想法擴展到2-D?
鑑於a=[5 1 3;1 1 2;2 1 3]
和b=[4 3;1 2]
,是有可能a
轉換在託普利茲矩陣,並計算T_a
和b
作爲之間的矩陣矩陣產物在1-d的情況下?
我知道在1-d情況下,兩個矢量a,b
之間的卷積可以被計算爲 conv(a,b)
,而且作爲T_a
和b
之間的乘積,其中T_a
是相應的Toeplitz矩陣爲a
。2-d卷積作爲基質 - 矩陣乘法
是否有可能將此想法擴展到2-D?
鑑於a=[5 1 3;1 1 2;2 1 3]
和b=[4 3;1 2]
,是有可能a
轉換在託普利茲矩陣,並計算T_a
和b
作爲之間的矩陣矩陣產物在1-d的情況下?
是的,這是可能的,你也應該使用一個雙塊循環矩陣(這是矩陣的一個特例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輸入的例子。
這裏是與載體構建的矩陣:
而這與通過k
的滑動窗口超過x
所得到的結果相同。
如果你解開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
有必須是某種在年底重塑正確的?最後一個向量是4 x 1,但是卷積的結果是2 x 2 – jvans
@jvans是的,最後你應該重塑你的向量。它寫在這裏:**將得到的向量(其大小(n-m + 1)^ 2 X 1)轉換爲n-m + 1方陣** –