0

The title may be a little obscure, sorry. I'm not quite sure how to phrase it otherwise.

The problem is as such: I have a 2D kernel (as is used for convolution) and a vector of weights (e.g., floats or ints).

I would like to produce a 2D array of the kernel multiplied by the weights, but stacked by the position of the weights. For example:

kernel = np.arange(6).reshape((2, 3))
nrows, kernel_length = kernel.shape
kernel_midpt = kernel_length // 2

weights = np.array([0, 1, 2, 3])

expected_output = np.zeros((nrows, len(weights) + 2*kernel_midpt))
for ii in range(len(weights)):
    expected_output[:, ii:ii+kernel_length] += weights[ii] * kernel
    
expected_output
> array([[ 0.,  0.,  1.,  4.,  7.,  6.],
         [ 0.,  3., 10., 22., 22., 15.]])

So basically, what this code is doing is taking the kernel

array([[0, 1, 2],
       [3, 4, 5]])

and multiplying by 0, and adding it to the first three columns (0, 1, 2) of the output. Next, it multiplies the kernel by 1 and adds the results to columns (1, 2, 3), etc.

I obviously the code to do it with a for loop, but for computational purposes, it is very expensive. Is there a simpler way to do this? I have considered einsum, but haven't figure out how to use it.

Aku
  • 526
  • 4
  • 17
  • The shift-multiply-add operation you describe is called "convolution". What do you mean by "invert"? – Matt Timmermans Jan 19 '22 at 18:15
  • The distinction here is that usually in convolution, you take a kernel and convolve it over an image of the same dimensionality, and get an array of values. Here, I'm going from the array of values and a kernel to "get" the image. – Aku Jan 19 '22 at 18:16
  • 1
    Turn your weight vector into a 1xN matrix. Then you can use scipy.signal.convolve2d to do what you want: https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.convolve2d.html – Matt Timmermans Jan 19 '22 at 18:21
  • Well, it worked. That was easy. Thanks! – Aku Jan 19 '22 at 18:25

0 Answers0