1

I want to create a convolver function without using the convolve function of NumPy that get 4 elements:

convolver_1(j, matrices_list, filter_matrix, stride_size)

The function should return the output after performing a convolution operation with filter_matrix, with a stride of size ​stride_size, over matrix in index j at matrices_list, filter_matrix has lower dimensions than the matrices in ​matrices_list.

2
  • 1
    Exactly why don't you want to use numpy's convolve function? Commented Jan 2, 2020 at 11:15
  • Where are you stuck? Can you post the code from your current attempt? Commented Jan 2, 2020 at 13:26

2 Answers 2

3

Let's go through a simple implementation of np.convolve whose documentation can be found here.

import numpy as np

def convolve_1d(a, filter):
  N, M = len(a), len(filter)
  assert N >= M # assumption in the question
  # in the full mode (default of np.convolve), result length is N+M-1
  # therefore, pad should be M-1 on each side
  # N-M+2p+1 == N+M-1 => p = M-1
  result_length = N+M-1
  result = np.zeros(result_length) # allocating memory for result
  p = M-1
  padded_a = np.pad(a,p)
  flipped_filter = np.flip(filter)
  for i in range(result_length):
    result[i] = np.sum(np.multiply(flipped_filter, padded_a[i:i+M]))
  return result


a = np.array([1,2,3,4])
filter = np.array([1,-1,3])
convolve_1d(a, filter)

results in

array([ 1.,  1.,  4.,  7.,  5., 12.])

which is the same as the result for np.convolve(a, filter). So, it basically pads the input array with zeros, flips the filter and sums the element-wise multiplication of two arrays.

I am not sure about the index that you mentioned; the result is a 1d array and you can index its elements.

To add stride to this function, we need to modify the result_length and multiply the stride to the iterator:

def convolve_1d_strided(a, filter, stride):
  N, M = len(a), len(filter)
  assert N >= M # assumption in the question
  # in the full mode (default of np.convolve), result length is N+M-1
  # therefore, pad should be M-1 on each side
  # N-M+2p+1 == N+M-1 => p = M-1
  result_length = (N+M-1)//stride
  result = np.zeros(result_length) # allocating memory for result
  p = M-1
  padded_a = np.pad(a,p)
  flipped_filter = np.flip(filter)
  for i in range(result_length):
    result[i] = np.sum(np.multiply(flipped_filter, padded_a[i*stride:i*stride+M]))
  return result

a = np.array([1,2,3,4])
filter = np.array([1,-1,3])
convolve_1d_strided(a, filter, 2)
array([1., 4., 5.])

Hope it helps and if that is what you liked to see, I am happy to expand it to two dimensions.

Sign up to request clarification or add additional context in comments.

Comments

1

For 1D arrays:

import numpy as np
from numpy.lib.stride_tricks import as_strided


def conv1d(A, kernel, stride, reverse_kernel=True, mode='full'):
    if reverse_kernel:
        kernel = kernel[::-1]

    if mode == 'full':    
        A = np.pad(A, kernel.shape[0] - 1)
    #else: convolution in 'valid' mode

    # Sliding-window view of A
    output_size = (A.shape[0] - kernel.shape[0])//stride + 1
    A_w = as_strided(A, shape=(output_size, kernel.shape[0]), 
                        strides=(stride*A.strides[0], A.strides[0]))

    # Return convolution of A with kernel
    return np.sum(A_w * kernel, axis=1)

Here A = matrices_list[j]. Note that in Deep Learning the filters in convolution are not reversed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.