code: def nn_model(X, Y, n_h, num_iterations=10000, print_cost=False):
      
  
      np.random.seed(3)
      n_x = layer_sizes(X, Y)[0]
      n_y = layer_sizes(X, Y)[2]
  
      # Initialize parameters, then retrieve W1, b1, W2, b2.
      # Inputs: "n_x, n_h, n_y". Outputs = "W1, b1, W2, b2, parameters".
      parameters = initialize_parameters(n_x, n_h, n_y)
      W1 = parameters["W1"]
      b1 = parameters["b1"]
      W2 = parameters["W2"]
      b2 = parameters["b2"]
  
      # Loop (gradient descent)
  
      for i in range(0, num_iterations):
  
          # Forward propagation. Inputs: "X, parameters". Outputs: "A2, cache".
          A2, cache = forward_propagation(X, parameters)
  
          # Cost function. Inputs: "A2, Y, parameters". Outputs: "cost".
          cost = compute_cost(A2, Y, parameters)
  
          # Backpropagation. Inputs: "parameters, cache, X, Y". Outputs: "grads".
          grads = backward_propagation(parameters, cache, X, Y)
  
          # Gradient descent parameter update. Inputs: "parameters, grads". Outputs: "parameters".
          parameters = update_parameters(parameters, grads)
  
          # Print the cost every 1000 iterations
          if print_cost and i % 1000 == 0:
              print("Cost after iteration %i: %f" % (i, cost))
  
      return parameters
docs: Arguments:
      X -- dataset of shape (2, number of examples)
      Y -- labels of shape (1, number of examples)
      n_h -- size of the hidden layer
      num_iterations -- Number of iterations in gradient descent loop
      print_cost -- if True, print the cost every 1000 iterations
  
      Returns:
      parameters -- parameters learnt by the model. They can then be used to predict.