Last active
September 14, 2018 14:14
-
-
Save raytroop/8ac364bf901f3bf3b2975b5381eb95ba to your computer and use it in GitHub Desktop.
conv2d implementation of cs231n spring1718_assignment2_v2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def conv_forward_naive(x, w, b, conv_param): | |
""" | |
A naive implementation of the forward pass for a convolutional layer. | |
The input consists of N data points, each with C channels, height H and | |
width W. We convolve each input with F different filters, where each filter | |
spans all C channels and has height HH and width WW. | |
Input: | |
- x: Input data of shape (N, C, H, W) | |
- w: Filter weights of shape (F, C, HH, WW) | |
- b: Biases, of shape (F,) | |
- conv_param: A dictionary with the following keys: | |
- 'stride': The number of pixels between adjacent receptive fields in the | |
horizontal and vertical directions. | |
- 'pad': The number of pixels that will be used to zero-pad the input. | |
During padding, 'pad' zeros should be placed symmetrically (i.e equally on both sides) | |
along the height and width axes of the input. Be careful not to modfiy the original | |
input x directly. | |
Returns a tuple of: | |
- out: Output data, of shape (N, F, H', W') where H' and W' are given by | |
H' = 1 + (H + 2 * pad - HH) / stride | |
W' = 1 + (W + 2 * pad - WW) / stride | |
- cache: (x, w, b, conv_param) | |
""" | |
out = None | |
########################################################################### | |
# TODO: Implement the convolutional forward pass. # | |
# Hint: you can use the function np.pad for padding. # | |
########################################################################### | |
N, C, H, W = x.shape | |
F, C, HH, WW = w.shape | |
stride = conv_param['stride'] | |
pad = conv_param['pad'] | |
Ho = 1 + (H + 2 * pad - HH) // stride | |
Wo = 1 + (W + 2 * pad - WW) // stride | |
x_padding = np.pad(x, ((0, 0), (0, 0), (pad, pad), (pad, pad)), mode='constant') | |
out = np.empty(shape=(N, F, Ho, Wo)) | |
for n in range(N): | |
for f in range(F): | |
x_nf = x_padding[n] # (C, H, W)) | |
w_nf = w[f] # (C, HH, WW) | |
for i in range(Ho): | |
for j in range(Wo): | |
x_nf_ij = x_nf[:, i*stride:i*stride+HH, j*stride:j*stride+WW] | |
o = np.sum(x_nf_ij * w_nf) | |
out[n, f, i, j] = o | |
out += b.reshape(1, F, 1, 1) | |
########################################################################### | |
# END OF YOUR CODE # | |
########################################################################### | |
cache = (x, w, b, conv_param) | |
return out, cache | |
def conv_backward_naive(dout, cache): | |
""" | |
A naive implementation of the backward pass for a convolutional layer. | |
Inputs: | |
- dout: Upstream derivatives. | |
- cache: A tuple of (x, w, b, conv_param) as in conv_forward_naive | |
Returns a tuple of: | |
- dx: Gradient with respect to x | |
- dw: Gradient with respect to w | |
- db: Gradient with respect to b | |
""" | |
dx, dw, db = None, None, None | |
########################################################################### | |
# TODO: Implement the convolutional backward pass. # | |
########################################################################### | |
x, w, b, conv_param = cache | |
N, C, H, W = x.shape | |
F, C, HH, WW = w.shape | |
stride = conv_param['stride'] | |
pad = conv_param['pad'] | |
Ho = 1 + (H + 2 * pad - HH) // stride | |
Wo = 1 + (W + 2 * pad - WW) // stride | |
x_padding = np.pad(x, ((0, 0), (0, 0), (pad, pad), (pad, pad)), mode='constant') | |
db = np.sum(dout, axis=(0, 2, 3)) | |
dx_padding = np.zeros_like(x_padding) | |
dw = np.zeros_like(w) | |
""" | |
- x: Input data of shape (N, C, H, W) | |
- w: Filter weights of shape (F, C, HH, WW) | |
- b: Biases, of shape (F,) | |
- out: Output data, of shape (N, F, H', W') where H' and W' are given by | |
H' = 1 + (H + 2 * pad - HH) / stride | |
W' = 1 + (W + 2 * pad - WW) / stride | |
""" # pylint: disable=W0105 | |
for n in range(N): | |
for f in range(F): | |
x_nf = x_padding[n] # (C, H, W)) | |
dx_nf = dx_padding[n] | |
w_nf = w[f] # (C, HH, WW) | |
dw_nf = dw[f] | |
for i in range(Ho): | |
for j in range(Wo): | |
x_nf_ij = x_nf[:, i*stride:i*stride+HH, j*stride:j*stride+WW] | |
dx_nf_ij = dx_nf[:, i*stride:i*stride+HH, j*stride:j*stride+WW] | |
# o = np.sum(x_nf_ij * w_nf) | |
# out[n, f, i, j] = o | |
dw_nf += x_nf_ij * dout[n, f, i, j] | |
dx_nf_ij += w_nf * dout[n, f, i, j] | |
dx = dx_padding[:, :, pad:-pad, pad:-pad] | |
########################################################################### | |
# END OF YOUR CODE # | |
########################################################################### | |
return dx, dw, db |
Author
raytroop
commented
Sep 14, 2018
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment