<jupyter_start><jupyter_text>Using Convolution Layers in TensorFlowLet's now apply what we've learned to build real CNNs in TensorFlow. In the below exercise, you'll be asked to set up the dimensions of the Convolution filters, the weights, the biases. This is in many ways the trickiest part to using CNNs in TensorFlow. Once you have a sense of how to set up the dimensions of these attributes, applying CNNs will be far more straight forward.ReviewYou should go over the TensorFlow documentation for 2D convolutions. Most of the documentation is straightforward, except perhaps the ```padding``` argument. The padding might differ depending on whether you pass ```'VALID'``` or ```'SAME'```.Here are a few more things worth reviewing:Introduction to TensorFlow -> TensorFlow Variables.How to determine the dimensions of the output based on the input size and the filter size (shown below). You'll use this to determine what the size of your filter should be.* ```new_height = (input_height - filter_height + 2 * P)/S + 1```* ```new_width = (input_width - filter_width + 2 * P)/S + 1```* Instructions:Finish off each `TODO` in the `conv2d` function.Setup the `strides`, `padding` and filter weight/bias (`F_w` and `F_b`) such that the output shape is ```(1, 2, 2, 3)```. Note that all of these except `strides` should be TensorFlow variables.<jupyter_code>import tensorflow as tf
import numpy as np
"""
Setup the strides, padding and filter weight/bias such that
the output shape is (1, 2, 2, 3).
"""
# `tf.nn.conv2d` requires the input be 4D (batch_size, height, width, depth)
# (1, 4, 4, 1)
x = np.array([
    [0, 1, 0.5, 10],
    [2, 2.5, 1, -8],
    [4, 0, 5, 6],
    [15, 1, 2, 3]], dtype=np.float32).reshape((1, 4, 4, 1))
X = tf.constant(x)

def conv2d(input_array):
    # Filter (weights and bias)
    # The shape of the filter weight is (height, width, input_depth, output_depth)
    # The shape of the filter bias is (output_depth,)
    # TODO: Define the filter weights `F_W` and filter bias `F_b`.
    # NOTE: Remember to wrap them in `tf.Variable`, they are trainable parameters after all.
    F_W = tf.Variable(tf.truncated_normal((2, 2, 1, 3)))
    F_b = tf.Variable(tf.zeros(3))
    # TODO: Set the stride for each dimension (batch_size, height, width, depth)
    strides = [1, 2, 2, 1]
    # TODO: set the padding, either 'VALID' or 'SAME'.
    padding = 'VALID'
    # https://www.tensorflow.org/versions/r0.11/api_docs/python/nn.html#conv2d
    # `tf.nn.conv2d` does not include the bias computation so we have to add it ourselves after.
    return tf.nn.conv2d(input_array, F_W, strides, padding) + F_b

output = conv2d(X)
output
##### Do Not Modify ######

import tensorflow as tf
import numpy as np
import json


def solution(input_array):
    # Filter (weights and bias)
    F_W = tf.Variable(tf.truncated_normal((2, 2, 1, 3)))
    F_b = tf.Variable(tf.zeros(3))
    strides = [1, 2, 2, 1]
    padding = 'VALID'
    return tf.nn.conv2d(input_array, F_W, strides, padding) + F_b

def get_result(input_array, student_func):
        
    result = {'is_correct': None, 'error': False, 'values': [], 'output': '', 'custom_msg': ''}
    ours = solution(input_array)
    theirs = student_func(input_array)

    dim_names = ['Batch', 'Height', 'Width', 'Depth']
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        our_shape = ours.get_shape().as_list()
        their_shape = theirs.get_shape().as_list()

        did_pass = False

        try:
            for dn, ov, tv in zip(dim_names, our_shape, their_shape):
                if ov != tv:
                    # dimension mismatch
                    raise Exception('{} dimension: mismatch we have {}, you have {}'.format(dn, ov, tv))
            if np.alltrue(our_shape == their_shape):
                did_pass = True
            else:
                did_pass = False
        except:
            did_pass = False

        if did_pass:
            result['is_correct'] = 'Great Job!'
            result['values'] = ['your output shape: {}'.format(their_shape)]
        else:
            result['values'] = ['correct shape: {}'.format(our_shape)]
            result['output'] = ['your output shape: {}'.format(their_shape)]

    return result
                    
def run_grader(input_array, student_func):
  
    grader_result = get_result(input_array, student_func)
    gt_shape = grader_result.get('values')
    student_func_shape = grader_result.get('output')
    comment = ""

    if grader_result['is_correct']:
        comment= "Great job! Your Convolution layer looks good :)"
    elif not grader_result['error']:
        comment = "Not quite. The correct output shape is {} while your output shape is {}.".format(gt_shape, student_func_shape)
    else:
        test_error = grader_result['error']
        comment = "Something went wrong with your submission: {}".format(test_error)

    grader_result['feedback'] = comment
    
    return grader_result.get('feedback')

test_X = tf.constant(np.random.randn(1, 4, 4, 1), dtype=tf.float32)

try:
    response = run_grader(test_X, conv2d)
    print(response)
    
    
except Exception as err:
    print(str(err))<jupyter_output>Great job! Your Convolution layer looks good :)
{'fraction_non_alphanumeric': 0.12020606754436176, 'fraction_numerical': 0.01526426254531578, 'mean_word_length': 3.2376717865804365, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 5, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '665322', 'license': 'MIT', 'n_tokens_mistral': 1694, 'n_tokens_neox': 1607, 'n_words': 568, 'path': 'HelperProjects/Convolutional-Neural-Networks/cnn-in-tensorflow/convolutional-layer-workspace.ipynb', 'repo_name': 'luk6xff/SelfDrivingCarND', 'size': '5241'}