Pool_backward(...) function

Here is my implmentation of the function pool_backward(…) which I am sure is correct but I cannot get the two tests of the function to produce the correct results from the Jupyter Notebook in the Programming Assignment: Convolutional Model, Step by Step of Course 4 Week 1.

def pool_backward(dA, cache, mode = "max"):
    """
    Implements the backward pass of the pooling layer
    
    Arguments:
    dA -- gradient of cost with respect to the output of the pooling layer, same shape as A
    cache -- cache output from the forward pass of the pooling layer, contains the layer's input and hparameters 
    mode -- the pooling mode you would like to use, defined as a string ("max" or "average")
    
    Returns:
    dA_prev -- gradient of cost with respect to the input of the pooling layer, same shape as A_prev
    """
    # Retrieve information from cache (≈1 line)
    # (A_prev, hparameters) = None
    
    # Retrieve hyperparameters from "hparameters" (≈2 lines)
    # stride = None
    # f = None
    
    # Retrieve dimensions from A_prev's shape and dA's shape (≈2 lines)
    # m, n_H_prev, n_W_prev, n_C_prev = None
    # m, n_H, n_W, n_C = None
    
    # Initialize dA_prev with zeros (≈1 line)
    # dA_prev = None
    
    # for i in range(None): # loop over the training examples
        
        # select training example from A_prev (≈1 line)
        # a_prev = None
        
        # for h in range(n_H):                   # loop on the vertical axis
            # for w in range(n_W):               # loop on the horizontal axis
                # for c in range(n_C):           # loop over the channels (depth)
        
                    # Find the corners of the current "slice" (≈4 lines)
                    # vert_start = None
                    # vert_end = None
                    # horiz_start = None
                    # horiz_end = None
                    
                    # Compute the backward propagation in both modes.
                    # if mode == "max":
                        
                        # Use the corners and "c" to define the current slice from a_prev (≈1 line)
                        # a_prev_slice = None
                        
                        # Create the mask from a_prev_slice (≈1 line)
                        # mask = None

                        # Set dA_prev to be dA_prev + (the mask multiplied by the correct entry of dA) (≈1 line)
                        # dA_prev[i, vert_start: vert_end, horiz_start: horiz_end, c] += None
                        
                    # elif mode == "average":
                        
                        # Get the value da from dA (≈1 line)
                        # da = None
                        
                        # Define the shape of the filter as fxf (≈1 line)
                        # shape = None

                        # Distribute it to get the correct slice of dA_prev. i.e. Add the distributed value of da. (≈1 line)
                        # dA_prev[i, vert_start: vert_end, horiz_start: horiz_end, c] += None
    # YOUR CODE STARTS HERE
    
    # Retrieve information from cache (≈1 line)
    (A_prev, hparameters) = cache
    
    # Retrieve hyperparameters from "hparameters" (≈2 lines)
    stride = hparameters["stride"]
    f = hparameters["f"]
    
    # Retrieve dimensions from A_prev's shape and dA's shape (≈2 lines)
    m, n_H_prev, n_W_prev, n_C_prev = A_prev.shape
    m, n_H,      n_W,      n_C = dA.shape
    
    # Initialize dA_prev with zeros (≈1 line)
    dA_prev = np.zeros(A_prev.shape)
    
    for i in range(m): # loop over the training examples
        
        # select training example from A_prev (≈1 line)
        a_prev = A_prev[i, :, :, :]
        
        for h in range(n_H):                   # loop on the vertical axis
            
            for w in range(n_W):               # loop on the horizontal axis
                
                for c in range(n_C):           # loop over the channels (depth)
        
                    # Find the corners of the current "slice" (≈4 lines)
                    vert_start = h * stride
                    vert_end = vert_start + f
                    
                    horiz_start = w * stride
                    horiz_end = horiz_start + f
                    
                    # Compute the backward propagation in both modes.
                    if mode == "max":
                        
                        # Use the corners and "c" to define the current slice from a_prev (≈1 line)
                        a_prev_slice = a_prev[vert_start:vert_end, horiz_start:horiz_end, c]
                        
                        # Create the mask from a_prev_slice (≈1 line)
                        mask = create_mask_from_window(a_prev_slice)

                        # Set dA_prev to be dA_prev + (the mask multiplied by the correct entry of dA) (≈1 line)
                        dA_prev[i, vert_start:vert_end, horiz_start:horiz_end, c] += mask * dA[i, vert_start:vert_end, horiz_start:horiz_end, c]
                        
                    elif mode == "average":
                        
                        # Get the value da from dA (≈1 line)
                        da = np.mean(dA)
                        
                        # Define the shape of the filter as fxf (≈1 line)
                        shape = (f, f)

                        # Distribute it to get the correct slice of dA_prev. i.e. Add the distributed value of da. (≈1 line)
                        dA_prev[i, vert_start:vert_end, horiz_start:horiz_end, c] += distribute_value(da, shape)
                    
                    else:
                        
                        pass
    
    # YOUR CODE ENDS HERE
    
    # Making sure your output shape is correct
    assert(dA_prev.shape == A_prev.shape)
    
    return dA_prev

Can anyone confirm or deny that my implementation is correct?

Hi @jjbarnes,

In if mode == "max":, it needs to be:

dA_prev[i, vert_start: vert_end, horiz_start: horiz_end, c] += mask * dA[i, h, w, c]

Thank you.

I think a visual representation of what this function needs to do in this programming assignment would have helped a lot to implement pool_backward(…).