2-D convolution as a matrix-matrix multiplication

前端 未结 4 1127
你的背包
你的背包 2020-11-29 17:07

I know that, in the 1D case, the convolution between two vectors, a and b, can be computed as conv(a, b), but also as the product betw

4条回答
  •  时光说笑
    2020-11-29 17:53

    If you unravel k to a m^2 vector and unroll X, you would then get:

    • a m**2 vectork
    • a ((n-m)**2, m**2) matrix for unrolled_X

    where unrolled_X could be obtained by the following Python code:

    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
    

    Unrolling X and not k allows a more compact representation (smaller matrices) than the other way around for each X - but you need to unroll each X. You could prefer unrolling k depending on what you want to do.

    Here, the unrolled_X is not sparse, whereas unrolled_k would be sparse, but of size ((n-m+1)^2,n^2) as @Salvador Dali mentioned.

    Unrolling k could be done like this:

    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
    

提交回复
热议问题