MCPcopy
hub / github.com/ddbourgin/numpy-ml / conv2D_naive

Function conv2D_naive

numpy_ml/neural_nets/utils/utils.py:797–856  ·  view source on GitHub ↗

A slow but more straightforward implementation of a 2D "convolution" (technically, cross-correlation) of input `X` with a collection of kernels `W`. Notes ----- This implementation uses ``for`` loops and direct indexing to perform the convolution. As a result, it is slower

(X, W, stride, pad, dilation=0)

Source from the content-addressed store, hash-verified

795
796
797def conv2D_naive(X, W, stride, pad, dilation=0):
798 """
799 A slow but more straightforward implementation of a 2D "convolution"
800 (technically, cross-correlation) of input `X` with a collection of kernels `W`.
801
802 Notes
803 -----
804 This implementation uses ``for`` loops and direct indexing to perform the
805 convolution. As a result, it is slower than the vectorized :func:`conv2D`
806 function that relies on the :func:`col2im` and :func:`im2col`
807 transformations.
808
809 Parameters
810 ----------
811 X : :py:class:`ndarray <numpy.ndarray>` of shape `(n_ex, in_rows, in_cols, in_ch)`
812 Input volume.
813 W: :py:class:`ndarray <numpy.ndarray>` of shape `(kernel_rows, kernel_cols, in_ch, out_ch)`
814 The volume of convolution weights/kernels.
815 stride : int
816 The stride of each convolution kernel.
817 pad : tuple, int, or 'same'
818 The padding amount. If 'same', add padding to ensure that the output of
819 a 2D convolution with a kernel of `kernel_shape` and stride `stride`
820 produces an output volume of the same dimensions as the input. If
821 2-tuple, specifies the number of padding rows and colums to add *on both
822 sides* of the rows/columns in `X`. If 4-tuple, specifies the number of
823 rows/columns to add to the top, bottom, left, and right of the input
824 volume.
825 dilation : int
826 Number of pixels inserted between kernel elements. Default is 0.
827
828 Returns
829 -------
830 Z : :py:class:`ndarray <numpy.ndarray>` of shape `(n_ex, out_rows, out_cols, out_ch)`
831 The covolution of `X` with `W`.
832 """
833 s, d = stride, dilation
834 X_pad, p = pad2D(X, pad, W.shape[:2], stride=s, dilation=d)
835
836 pr1, pr2, pc1, pc2 = p
837 fr, fc, in_ch, out_ch = W.shape
838 n_ex, in_rows, in_cols, in_ch = X.shape
839
840 # update effective filter shape based on dilation factor
841 fr, fc = fr * (d + 1) - d, fc * (d + 1) - d
842
843 out_rows = int((in_rows + pr1 + pr2 - fr) / s + 1)
844 out_cols = int((in_cols + pc1 + pc2 - fc) / s + 1)
845
846 Z = np.zeros((n_ex, out_rows, out_cols, out_ch))
847 for m in range(n_ex):
848 for c in range(out_ch):
849 for i in range(out_rows):
850 for j in range(out_cols):
851 i0, i1 = i * s, (i * s) + fr
852 j0, j1 = j * s, (j * s) + fc
853
854 window = X_pad[m, i0 : i1 : (d + 1), j0 : j1 : (d + 1), :]

Callers 1

test_convFunction · 0.90

Calls 1

pad2DFunction · 0.85

Tested by 1

test_convFunction · 0.72