2013-05-28 14 views
6

wiem, że w przypadku 1-D splot między dwoma wektorami a,b można obliczyć conv(a,b), ale także jako produkt między T_a i b, gdzie T_a jest odpowiadająca matryca Toeplitza dla a.2-D splotu w macierzy matrycy

Czy można rozszerzyć ten pomysł na 2-D?

względu a=[5 1 3;1 1 2;2 1 3] i b=[4 3;1 2], możliwe jest przekształcenie a w matrycy Toeplitza i obliczyć iloczyn macierzy matrycy pomiędzy T_a i b jak w przypadku 1-D?

Odpowiedz

7

Tak, jest to możliwe i powinieneś także użyć podwójnie blokowej macierzy krążkowej (co jest szczególnym przypadkiem macierzy Toeplitz). Podam przykład z małym rozmiarem jądra i danymi wejściowymi, ale możliwe jest zbudowanie matrycy Toeplitza dla dowolnego jądra. Więc masz wejście 2d x i jądro 2d k i chcesz obliczyć splot x * k. Załóżmy także, że k jest już odwrócony. Załóżmy także, że x ma rozmiar nxn i k jest mxm.

więc rozwinąć k w rozrzedzony matrycy wielkości (n-m+1)^2 X n^2 i rozwinąć x do długiego wektora n^2 X 1. Oblicza się mnożenie tej rzadkiej macierzy za pomocą wektora i przekształca otrzymany wektor (który będzie miał rozmiar (n-m+1)^2 X 1) w macierz kwadratową n-m+1.

Jestem prawie pewien, że trudno to zrozumieć po prostu czytając. Oto przykład dla jądra 2x2 i wejścia 3x3.

enter image description here * enter image description here

tu jest wykonana matryca wektorem:

enter image description here

która jest równa enter image description here.

To jest ten sam rezultat, który można uzyskać, przesuwając okno k przez x.

+1

Nie musiałyby być jakieś przekształcenia na końcu jest prawidłowy? Ten ostatni wektor to 4 x 1, ale wynikiem splotu będzie 2 x 2 – jvans

+0

@jvans tak, w końcu powinieneś zmienić swój wektor. Jest tu napisane: ** przekształcić powstały wektor (który będzie miał rozmiar (n-m + 1)^2 X 1) na macierz kwadratową n-m + 1 ** –

2

Jeśli rozwikłać k Am^2 wektor i się rozwinąć X, by następnie dostać:

  • m**2 Wektor k
  • ((n-m)**2, m**2) Matryca unrolled_X

gdzie unrolled_X może być uzyskane za pomocą następującego kodu 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 

Rozwinięcie X, a nie k pozwala na uzyskanie bardziej zwartej reprezentacji (mniejsze macierze) niż odwrotnie dla każdego X - ale musisz rozwinąć każdy X. Wolisz rozwinąć k w zależności od tego, co chcesz zrobić.

Tutaj, unrolled_X nie jest rzadki, natomiast unrolled_k będzie rzadki, ale o rozmiarze ((n-m+1)^2,n^2) jako @ Salvador Dali wspomniano.

Rozwijanie k można zrobić tak:

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 
Powiązane problemy