1
$\begingroup$

I've been trying to implement "full convolution" w.r.t to convolution layer inputs. According to this article, it looks like this:

enter image description here

So, I wrote this function:

def full_convolve(filters, gradient):
    filters = np.ones((5,5))
    gradient = np.ones((8,8))
    result = list()
    output_shape = 12
    filter_r = filters.shape[0] - 1
    filter_c = filters.shape[1] - 1
    gradient_r = gradient.shape[0] - 1
    gradient_c = gradient.shape[1] - 1

    for i in range(0,output_shape):
        if (i <= filter_r):
            row_slice = (0, i + 1)
            filter_row_slice = ( 0 , i + 1)
        elif ( i > filter_r and i <= gradient_r):
            row_slice = (i - filter_r, i + 1)
            filter_row_slice = (0, i + 1)
        else: 
            rest = ((output_shape - 1) -  i )
            row_slice = (gradient_r  - rest, i + 1 )
            filter_row_slice = (0 ,rest + 1)
        for b in range(0,output_shape):
            if (b <= filter_c):
                col_slice = (0, b + 1)
                filter_col_slice = (0, b+1)
            elif (b > filter_c and b <= gradient_c):
                col_slice = (b - filter_c, b + 1)
                filter_col_slice = (0,b+1)
            else:
                rest = (output_shape - 1 ) - b 
                col_slice = (gradient_r - rest , b + 1)
                filter_col_slice = (0, rest + 1)
            r = np.sum(gradient[row_slice[0] : row_slice[1], col_slice[0] : col_slice[1]] * filters[filter_row_slice[0]: filter_row_slice[1], filter_col_slice[0]: filter_col_slice[1]])
            result.append(r)
    result = np.asarray(result).reshape(12,12)

I tested this with ones and the output seems correct (if I get "full convolution" right):

[[ 1.  2.  3.  4.  5.  5.  5.  5.  4.  3.  2.  1.]
 [ 2.  4.  6.  8. 10. 10. 10. 10.  8.  6.  4.  2.]
 [ 3.  6.  9. 12. 15. 15. 15. 15. 12.  9.  6.  3.]
 [ 4.  8. 12. 16. 20. 20. 20. 20. 16. 12.  8.  4.]
 [ 5. 10. 15. 20. 25. 25. 25. 25. 20. 15. 10.  5.]
 [ 5. 10. 15. 20. 25. 25. 25. 25. 20. 15. 10.  5.]
 [ 5. 10. 15. 20. 25. 25. 25. 25. 20. 15. 10.  5.]
 [ 5. 10. 15. 20. 25. 25. 25. 25. 20. 15. 10.  5.]
 [ 4.  8. 12. 16. 20. 20. 20. 20. 16. 12.  8.  4.]
 [ 3.  6.  9. 12. 15. 15. 15. 15. 12.  9.  6.  3.]
 [ 2.  4.  6.  8. 10. 10. 10. 10.  8.  6.  4.  2.]
 [ 1.  2.  3.  4.  5.  5.  5.  5.  4.  3.  2.  1.]]

However, I don't like all these manual checks and if/else statements. I feel there is a better way to implement this in NumPy (perhaps, using some zero paddings or something like this). Can anyone suggest a better approach? Thanks

$\endgroup$
1
$\begingroup$

Code:

import numpy as np
from scipy import signal

j5 = np.ones((5,5))
j8 = np.ones((8,8))

c58 = signal.convolve2d(j5, j8, boundary='fill')  # by default filled with 0, which is correct for your case

Results in:

print(c58)
[[ 1.  2.  3.  4.  5.  5.  5.  5.  4.  3.  2.  1.]
 [ 2.  4.  6.  8. 10. 10. 10. 10.  8.  6.  4.  2.]
 [ 3.  6.  9. 12. 15. 15. 15. 15. 12.  9.  6.  3.]
 [ 4.  8. 12. 16. 20. 20. 20. 20. 16. 12.  8.  4.]
 [ 5. 10. 15. 20. 25. 25. 25. 25. 20. 15. 10.  5.]
 [ 5. 10. 15. 20. 25. 25. 25. 25. 20. 15. 10.  5.]
 [ 5. 10. 15. 20. 25. 25. 25. 25. 20. 15. 10.  5.]
 [ 5. 10. 15. 20. 25. 25. 25. 25. 20. 15. 10.  5.]
 [ 4.  8. 12. 16. 20. 20. 20. 20. 16. 12.  8.  4.]
 [ 3.  6.  9. 12. 15. 15. 15. 15. 12.  9.  6.  3.]
 [ 2.  4.  6.  8. 10. 10. 10. 10.  8.  6.  4.  2.]
 [ 1.  2.  3.  4.  5.  5.  5.  5.  4.  3.  2.  1.]]

Reference to see other options when you'd need them: https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.convolve2d.html

$\endgroup$
3
  • $\begingroup$ Thanks, but this is one-liner. It would be more interesting to see how such function could be actually implemented. I checked the source but did not find the procedure. $\endgroup$
    – Jim
    Jan 16 '20 at 9:26
  • $\begingroup$ @Jim, the documentation is like: "pad input arrays with fillvalue. (default)". You pad the input arrays with (filterlength-1) with zero, in two dimensions, on all 4 sides. This makes your row slice ignore terms by multiplications with zero instead of an if then else. Alternatively you can use min/max to calculate starts and ends but those are hidden if/then/elses $\endgroup$
    – Pieter21
    Jan 16 '20 at 10:27
  • $\begingroup$ Thanks, that makes sense $\endgroup$
    – Jim
    Jan 16 '20 at 10:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.