2d convolution operator in HW layout. This is intended to be used as a subroutine from _conv2d_nchw_python. Using scipy.signal.convolve2d directly does not work for all dtypes (e.g. float16). Where possible, this function uses scipy.signal.convolve2d to take advantage of compi
(apad, w_np_fc)
| 78 | |
| 79 | |
| 80 | def _conv2d_hw(apad, w_np_fc): |
| 81 | """2d convolution operator in HW layout. |
| 82 | |
| 83 | This is intended to be used as a subroutine from |
| 84 | _conv2d_nchw_python. Using scipy.signal.convolve2d directly does |
| 85 | not work for all dtypes (e.g. float16). Where possible, this |
| 86 | function uses scipy.signal.convolve2d to take advantage of |
| 87 | compiled scipy routines, falling back to an explicit loop only |
| 88 | where needed |
| 89 | |
| 90 | Parameters |
| 91 | ---------- |
| 92 | a_np : numpy.ndarray |
| 93 | 2-D with shape [in_height, in_width] |
| 94 | |
| 95 | w_np : numpy.ndarray |
| 96 | 2-D with shape [filter_height, filter_width]. |
| 97 | |
| 98 | Returns |
| 99 | ------- |
| 100 | b_np : np.ndarray |
| 101 | 2-D with shape [out_height, out_width] |
| 102 | """ |
| 103 | |
| 104 | try: |
| 105 | return scipy.signal.convolve2d(apad, np.rot90(np.rot90(w_np_fc)), mode="valid") |
| 106 | except ValueError: |
| 107 | pass |
| 108 | |
| 109 | assert len(apad.shape) == len(w_np_fc.shape) == 2 |
| 110 | |
| 111 | dtype = apad.dtype |
| 112 | in_height, in_width = apad.shape |
| 113 | kernel_h, kernel_w = w_np_fc.shape |
| 114 | |
| 115 | output_shape = [a_dim - w_dim + 1 for a_dim, w_dim in zip(apad.shape, w_np_fc.shape)] |
| 116 | output = np.zeros(output_shape, dtype=apad.dtype) |
| 117 | |
| 118 | for y in range(output_shape[0]): |
| 119 | for x in range(output_shape[1]): |
| 120 | output[y][x] = np.sum(apad[y : y + kernel_h, x : x + kernel_w] * w_np_fc) |
| 121 | |
| 122 | return output |
| 123 | |
| 124 | |
| 125 | def conv2d_nchw_python(a_np, w_np, stride, padding, groups=1): |
no test coverage detected
searching dependent graphs…