1.完成layers.py中的conv_forward_naive()
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,W,H=x.shape#N个样本,C个通道,
F,C,HH,WW=w.shape#F个样本,C个通道,HH是过滤器高度,WW是过滤器宽度
stride=conv_param['stride']#过滤器每次移动的步长
pad=conv_param['pad']#图片填充的宽度
#计算卷积结果矩阵的大小并分配全零值占位
new_H=1+int((H+2*pad-HH)/stride)
new_W=1+int((W+2*pad-WW)/stride)
out=np.zeros([N,F,new_H,new_W])
#开始卷积
for n in range(N):
for f in range(F):
conv_newH_newW=np.ones([new_H,new_W])*b[f]
for c in range(C):
pedded_x=np.lib.pad(x[n, c], pad_width=pad, mode='constant', constant_values=0)
for i in range(new_H):
for j in range(new_W):
conv_newH_newW[i,j]+=np.sum(pedded_x[i*stride:i*stride+HH,j*stride:j*stride+WW]*w[f,c,:,:])
out[n,f]=conv_newH_newW
###########################################################################
# END OF YOUR CODE #
###########################################################################
cache = (x, w, b, conv_param)
return out, cache
2.完成layers.py中的conv_backward_naive()
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
pad=conv_param['pad']
stride=conv_param['stride']
F,C,HH,WW=w.shape
N,C,H,W=x.shape
N,F,new_H,new_W=dout.shape
padded_x=np.lib.pad(x,((0,0),(0,0),(pad,pad),(pad,pad)),mode='constant',constant_values=0)
dw=np.zeros_like(w)
db=np.zeros_like(b)
for n in range(N):
for f in range(F):
for i in range(new_H):
for j in range(new_W):
db[f]+=dout[n,f,i,j]
dw[f]+=padded_x[n,:,i*stride:HH+i*stride,j*stride:WW+j*stride]*dout[n,f,i,j]
padded_x[n, :, i * stride:HH + i * stride, j * stride:WW + j * stride]+=w[f]*dout[n,f,i,j]
dx=padded_x[:,:,pad:pad+H,pad:pad+W]
###########################################################################
# END OF YOUR CODE #
###########################################################################
return dx, dw, db
3.完成layers.py中的max_pool_forward_naive()
def max_pool_forward_naive(x, pool_param):
"""
A naive implementation of the forward pass for a max-pooling layer.
Inputs:
- x: Input data, of shape (N, C, H, W)
- pool_param: dictionary with the following keys:
- 'pool_height': The height of each pooling region
- 'pool_width': The width of each pooling region
- 'stride': The distance between adjacent pooling regions
No padding is necessary here. Output size is given by
Returns a tuple of:
- out: Output data, of shape (N, C, H', W') where H' and W' are given by
H' = 1 + (H - pool_height) / stride
W' = 1 + (W - pool_width) / stride
- cache: (x, pool_param)
"""
out = None
###########################################################################
# TODO: Implement the max-pooling forward pass #
###########################################################################
N,C,H,W=x.shape
pool_height=pool_param['pool_height']
pool_width=pool_param['pool_width']
pool_stride=pool_param['stride']
new_H=1+int((H-pool_height)/pool_stride)
new_W=1+int((W-pool_width)/pool_stride)
out=np.zeros([N,C,new_H,new_W])
for n in range(N):
for c in range(C):
for i in range(new_H):
for j in range(new_W):
out[n,c,i,j]=np.max(x[n,c,i*pool_stride:i*pool_stride+pool_height,j*pool_stride:j*pool_stride+pool_height])
###########################################################################
# END OF YOUR CODE #
###########################################################################
cache = (x, pool_param)
return out, cache
4.完成layers.py中的max_pool_backward_naive()
def max_pool_backward_naive(dout, cache):
"""
A naive implementation of the backward pass for a max-pooling layer.
Inputs:
- dout: Upstream derivatives
- cache: A tuple of (x, pool_param) as in the forward pass.
Returns:
- dx: Gradient with respect to x
"""
dx = None
###########################################################################
# TODO: Implement the max-pooling backward pass #
###########################################################################
x,pool_param=cache
N,C,H,W=x.shape
pool_height=pool_param['pool_height']
pool_width=pool_param['pool_width']
pool_stride=pool_param['stride']
new_H=1+int((H-pool_height)/pool_stride)
new_W=1+int((W-pool_width)/pool_stride)
dx=np.zeros_like(x)
for n in range(N):
for c in range(C):
for i in range(new_H):
for j in range(new_W):
window=x[n,c,i*pool_stride:i*pool_stride+pool_height,j*pool_stride:j*pool_stride+pool_width]
dx[n,c,i*pool_stride:i*pool_stride+pool_height,j*pool_stride:j*pool_stride+pool_width]=(window==np.max(window))*dout[n,c,i,j]
###########################################################################
# END OF YOUR CODE #
###########################################################################
return dx
5.完成layers.py中的spatial_batchnorm_forward()
def spatial_batchnorm_forward(x, gamma, beta, bn_param):
"""
Computes the forward pass for spatial batch normalization.
Inputs:
- x: Input data of shape (N, C, H, W)
- gamma: Scale parameter, of shape (C,)
- beta: Shift parameter, of shape (C,)
- bn_param: Dictionary with the following keys:
- mode: 'train' or 'test'; required
- eps: Constant for numeric stability
- momentum: Constant for running mean / variance. momentum=0 means that
old information is discarded completely at every time step, while
momentum=1 means that new information is never incorporated. The
default of momentum=0.9 should work well in most situations.
- running_mean: Array of shape (D,) giving running mean of features
- running_var Array of shape (D,) giving running variance of features
Returns a tuple of:
- out: Output data, of shape (N, C, H, W)
- cache: Values needed for the backward pass
"""
out, cache = None, None
###########################################################################
# TODO: Implement the forward pass for spatial batch normalization. #
# #
# HINT: You can implement spatial batch normalization by calling the #
# vanilla version of batch normalization you implemented above. #
# Your implementation should be very short; ours is less than five lines. #
###########################################################################
N,C,H,W=x.shape
x_new=x.transpose(0,2,3,1).reshape(N*H*W,C)
out,cache=batchnorm_forward(x_new,gamma,beta,bn_param)
out=out.reshape(N,H,W,C).transpose(0,3,1,2)
###########################################################################
# END OF YOUR CODE #
###########################################################################
return out, cache
6.完成layers.py中的spatial_batchnorm_backward()
def spatial_batchnorm_backward(dout, cache):
"""
Computes the backward pass for spatial batch normalization.
Inputs:
- dout: Upstream derivatives, of shape (N, C, H, W)
- cache: Values from the forward pass
Returns a tuple of:
- dx: Gradient with respect to inputs, of shape (N, C, H, W)
- dgamma: Gradient with respect to scale parameter, of shape (C,)
- dbeta: Gradient with respect to shift parameter, of shape (C,)
"""
dx, dgamma, dbeta = None, None, None
###########################################################################
# TODO: Implement the backward pass for spatial batch normalization. #
# #
# HINT: You can implement spatial batch normalization by calling the #
# vanilla version of batch normalization you implemented above. #
# Your implementation should be very short; ours is less than five lines. #
###########################################################################
N,C,H,W=dout.shape
dout_new=dout.transpose(0,2,3,1).reshape(N*H*W,C)
dx,dgamma,dbeta=batchnorm_backward(dout_new,cache)
dx=dx.reshape(N,H,W,C).transpose(0,3,1,2)
###########################################################################
# END OF YOUR CODE #
###########################################################################
return dx, dgamma, dbeta
运行ConvolutionalNetworks.ipynb