Perform a "deconvolution" (more accurately, a transposed convolution) of an input volume `X` with a weight kernel `W`, incorporating stride, pad, and dilation. Notes ----- Rather than using the transpose of the convolution matrix, this approach uses a direct convolution
(X, W, stride, pad, dilation=0)
| 718 | |
| 719 | |
| 720 | def deconv2D_naive(X, W, stride, pad, dilation=0): |
| 721 | """ |
| 722 | Perform a "deconvolution" (more accurately, a transposed convolution) of an |
| 723 | input volume `X` with a weight kernel `W`, incorporating stride, pad, and |
| 724 | dilation. |
| 725 | |
| 726 | Notes |
| 727 | ----- |
| 728 | Rather than using the transpose of the convolution matrix, this approach |
| 729 | uses a direct convolution with zero padding, which, while conceptually |
| 730 | straightforward, is computationally inefficient. |
| 731 | |
| 732 | For further explanation, see [1]. |
| 733 | |
| 734 | References |
| 735 | ---------- |
| 736 | .. [1] Dumoulin & Visin (2016). "A guide to convolution arithmetic for deep |
| 737 | learning." https://arxiv.org/pdf/1603.07285v1.pdf |
| 738 | |
| 739 | Parameters |
| 740 | ---------- |
| 741 | X : :py:class:`ndarray <numpy.ndarray>` of shape `(n_ex, in_rows, in_cols, in_ch)` |
| 742 | Input volume (not padded) |
| 743 | W: :py:class:`ndarray <numpy.ndarray>` of shape `(kernel_rows, kernel_cols, in_ch, out_ch)` |
| 744 | A volume of convolution weights/kernels for a given layer |
| 745 | stride : int |
| 746 | The stride of each convolution kernel |
| 747 | pad : tuple, int, or 'same' |
| 748 | The padding amount. If 'same', add padding to ensure that the output of |
| 749 | a 2D convolution with a kernel of `kernel_shape` and stride `stride` |
| 750 | produces an output volume of the same dimensions as the input. If |
| 751 | 2-tuple, specifies the number of padding rows and colums to add *on both |
| 752 | sides* of the rows/columns in `X`. If 4-tuple, specifies the number of |
| 753 | rows/columns to add to the top, bottom, left, and right of the input |
| 754 | volume. |
| 755 | dilation : int |
| 756 | Number of pixels inserted between kernel elements. Default is 0. |
| 757 | |
| 758 | Returns |
| 759 | ------- |
| 760 | Y : :py:class:`ndarray <numpy.ndarray>` of shape `(n_ex, out_rows, out_cols, n_out)` |
| 761 | The decovolution of (padded) input volume `X` with `W` using stride `s` and |
| 762 | dilation `d`. |
| 763 | """ |
| 764 | if stride > 1: |
| 765 | X = dilate(X, stride - 1) |
| 766 | stride = 1 |
| 767 | |
| 768 | # pad the input |
| 769 | X_pad, p = pad2D(X, pad, W.shape[:2], stride=stride, dilation=dilation) |
| 770 | |
| 771 | n_ex, in_rows, in_cols, n_in = X_pad.shape |
| 772 | fr, fc, n_in, n_out = W.shape |
| 773 | s, d = stride, dilation |
| 774 | pr1, pr2, pc1, pc2 = p |
| 775 | |
| 776 | # update effective filter shape based on dilation factor |
| 777 | _fr, _fc = fr * (d + 1) - d, fc * (d + 1) - d |
no test coverage detected